1 /* 2 * Copyright (c) 2011, 2018, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package javafx.scene.transform; 27 28 import javafx.beans.property.DoubleProperty; 29 import javafx.beans.property.DoublePropertyBase; 30 31 import com.sun.javafx.geom.transform.Affine3D; 32 import com.sun.javafx.geom.transform.BaseTransform; 33 import javafx.geometry.Point2D; 34 import javafx.geometry.Point3D; 35 36 37 /** 38 * This class represents an {@code Affine} object that translates coordinates 39 * by the specified factors. The matrix representing the translating 40 * transformation by distances {@code x}, {@code y} and {@code z} is as follows: 41 * <pre> 42 * [ 1 0 0 x ] 43 * [ 0 1 0 y ] 44 * [ 0 0 1 z ] 45 * </pre> 46 * @since JavaFX 2.0 47 */ 48 49 public class Translate extends Transform { 50 51 /** 52 * Creates a default Translate (identity). 53 */ 54 public Translate() { 55 } 56 57 /** 58 * Creates a two-dimensional Translate. 59 * @param x the distance by which coordinates are translated in the 60 * X axis direction 61 * @param y the distance by which coordinates are translated in the 62 * Y axis direction 63 */ 64 public Translate(double x, double y) { 65 setX(x); 66 setY(y); 67 } 68 69 /** 70 * Creates a three-dimensional Translate. 71 * @param x the distance by which coordinates are translated in the 72 * X axis direction 73 * @param y the distance by which coordinates are translated in the 74 * Y axis direction 75 * @param z the distance by which coordinates are translated in the 76 * Z axis direction 77 */ 78 public Translate(double x, double y, double z) { 79 this(x, y); 80 setZ(z); 81 } 82 83 /** 84 * Defines the distance by which coordinates are translated in the 85 * X axis direction 86 */ 87 private DoubleProperty x; 88 89 90 public final void setX(double value) { 91 xProperty().set(value); 92 } 93 94 public final double getX() { 95 return x == null ? 0.0 : x.get(); 96 } 97 98 public final DoubleProperty xProperty() { 99 if (x == null) { 100 x = new DoublePropertyBase() { 101 102 @Override 103 public void invalidated() { 104 transformChanged(); 105 } 106 107 @Override 108 public Object getBean() { 109 return Translate.this; 110 } 111 112 @Override 113 public String getName() { 114 return "x"; 115 } 116 }; 117 } 118 return x; 119 } 120 121 /** 122 * Defines the distance by which coordinates are translated in the 123 * Y axis direction 124 */ 125 private DoubleProperty y; 126 127 128 public final void setY(double value) { 129 yProperty().set(value); 130 } 131 132 public final double getY() { 133 return y == null ? 0.0 : y.get(); 134 } 135 136 public final DoubleProperty yProperty() { 137 if (y == null) { 138 y = new DoublePropertyBase() { 139 140 @Override 141 public void invalidated() { 142 transformChanged(); 143 } 144 145 @Override 146 public Object getBean() { 147 return Translate.this; 148 } 149 150 @Override 151 public String getName() { 152 return "y"; 153 } 154 }; 155 } 156 return y; 157 } 158 159 /** 160 * Defines the distance by which coordinates are translated in the 161 * Z axis direction 162 */ 163 private DoubleProperty z; 164 165 166 public final void setZ(double value) { 167 zProperty().set(value); 168 } 169 170 public final double getZ() { 171 return z == null ? 0.0 : z.get(); 172 } 173 174 public final DoubleProperty zProperty() { 175 if (z == null) { 176 z = new DoublePropertyBase() { 177 178 @Override 179 public void invalidated() { 180 transformChanged(); 181 } 182 183 @Override 184 public Object getBean() { 185 return Translate.this; 186 } 187 188 @Override 189 public String getName() { 190 return "z"; 191 } 192 }; 193 } 194 return z; 195 } 196 197 /* ************************************************************************* 198 * * 199 * Element getters * 200 * * 201 **************************************************************************/ 202 203 @Override 204 public double getTx() { 205 return getX(); 206 } 207 208 @Override 209 public double getTy() { 210 return getY(); 211 } 212 213 @Override 214 public double getTz() { 215 return getZ(); 216 } 217 218 /* ************************************************************************* 219 * * 220 * State getters * 221 * * 222 **************************************************************************/ 223 224 @Override 225 boolean computeIs2D() { 226 return getZ() == 0.0; 227 } 228 229 @Override 230 boolean computeIsIdentity() { 231 return getX() == 0.0 && getY() == 0.0 && getZ() == 0.0; 232 } 233 234 /* ************************************************************************* 235 * * 236 * Array getters * 237 * * 238 **************************************************************************/ 239 240 @Override 241 void fill2DArray(double[] array) { 242 array[0] = 1.0; 243 array[1] = 0.0; 244 array[2] = getX(); 245 array[3] = 0.0; 246 array[4] = 1.0; 247 array[5] = getY(); 248 } 249 250 @Override 251 void fill3DArray(double[] array) { 252 array[0] = 1.0; 253 array[1] = 0.0; 254 array[2] = 0.0; 255 array[3] = getX(); 256 array[4] = 0.0; 257 array[5] = 1.0; 258 array[6] = 0.0; 259 array[7] = getY(); 260 array[8] = 0.0; 261 array[9] = 0.0; 262 array[10] = 1.0; 263 array[11] = getZ(); 264 } 265 266 /* ************************************************************************* 267 * * 268 * Transform creators * 269 * * 270 **************************************************************************/ 271 272 @Override 273 public Transform createConcatenation(Transform transform) { 274 if (transform instanceof Translate) { 275 final Translate t = (Translate) transform; 276 return new Translate( 277 getX() + t.getX(), 278 getY() + t.getY(), 279 getZ() + t.getZ()); 280 } 281 282 if (transform instanceof Scale) { 283 final Scale s = (Scale) transform; 284 285 final double sx = s.getX(); 286 final double sy = s.getY(); 287 final double sz = s.getZ(); 288 289 final double tx = getX(); 290 final double ty = getY(); 291 final double tz = getZ(); 292 293 if ((tx == 0.0 || sx != 1.0) && 294 (ty == 0.0 || sy != 1.0) && 295 (tz == 0.0 || sz != 1.0)) { 296 return new Scale( 297 sx, sy, sz, 298 s.getPivotX() + (sx == 1.0 ? 0 : tx / (1.0 - sx)), 299 s.getPivotY() + (sy == 1.0 ? 0 : ty / (1.0 - sy)), 300 s.getPivotZ() + (sz == 1.0 ? 0 : tz / (1.0 - sz))); 301 } 302 } 303 304 if (transform instanceof Affine) { 305 Affine a = (Affine) transform.clone(); 306 a.prepend(this); 307 return a; 308 } 309 310 final double txx = transform.getMxx(); 311 final double txy = transform.getMxy(); 312 final double txz = transform.getMxz(); 313 final double ttx = transform.getTx(); 314 final double tyx = transform.getMyx(); 315 final double tyy = transform.getMyy(); 316 final double tyz = transform.getMyz(); 317 final double tty = transform.getTy(); 318 final double tzx = transform.getMzx(); 319 final double tzy = transform.getMzy(); 320 final double tzz = transform.getMzz(); 321 final double ttz = transform.getTz(); 322 return new Affine( 323 txx, txy, txz, ttx + getX(), 324 tyx, tyy, tyz, tty + getY(), 325 tzx, tzy, tzz, ttz + getZ()); 326 } 327 328 @Override 329 public Translate createInverse() { 330 return new Translate(-getX(), -getY(), -getZ()); 331 } 332 333 @Override 334 public Translate clone() { 335 return new Translate(getX(), getY(), getZ()); 336 } 337 338 /* ************************************************************************* 339 * * 340 * Transform, Inverse Transform * 341 * * 342 **************************************************************************/ 343 344 @Override 345 public Point2D transform(double x, double y) { 346 ensureCanTransform2DPoint(); 347 return new Point2D( 348 x + getX(), 349 y + getY()); 350 } 351 352 @Override 353 public Point3D transform(double x, double y, double z) { 354 return new Point3D( 355 x + getX(), 356 y + getY(), 357 z + getZ()); 358 } 359 360 @Override 361 void transform2DPointsImpl(double[] srcPts, int srcOff, 362 double[] dstPts, int dstOff, int numPts) { 363 final double tx = getX(); 364 final double ty = getY(); 365 366 while (--numPts >= 0) { 367 final double x = srcPts[srcOff++]; 368 final double y = srcPts[srcOff++]; 369 370 dstPts[dstOff++] = x + tx; 371 dstPts[dstOff++] = y + ty; 372 } 373 } 374 375 @Override 376 void transform3DPointsImpl(double[] srcPts, int srcOff, 377 double[] dstPts, int dstOff, int numPts) { 378 379 final double tx = getX(); 380 final double ty = getY(); 381 final double tz = getZ(); 382 383 while (--numPts >= 0) { 384 final double x = srcPts[srcOff++]; 385 final double y = srcPts[srcOff++]; 386 final double z = srcPts[srcOff++]; 387 388 dstPts[dstOff++] = x + tx; 389 dstPts[dstOff++] = y + ty; 390 dstPts[dstOff++] = z + tz; 391 } 392 } 393 394 @Override 395 public Point2D deltaTransform(double x, double y) { 396 ensureCanTransform2DPoint(); 397 return new Point2D(x, y); 398 } 399 400 @Override 401 public Point2D deltaTransform(Point2D point) { 402 if (point == null) { 403 throw new NullPointerException(); 404 } 405 ensureCanTransform2DPoint(); 406 return point; 407 } 408 409 @Override 410 public Point3D deltaTransform(double x, double y, double z) { 411 return new Point3D(x, y, z); 412 } 413 414 @Override 415 public Point3D deltaTransform(Point3D point) { 416 if (point == null) { 417 throw new NullPointerException(); 418 } 419 return point; 420 } 421 422 @Override 423 public Point2D inverseTransform(double x, double y) { 424 ensureCanTransform2DPoint(); 425 return new Point2D( 426 x - getX(), 427 y - getY()); 428 } 429 430 @Override 431 public Point3D inverseTransform(double x, double y, double z) { 432 return new Point3D( 433 x - getX(), 434 y - getY(), 435 z - getZ()); 436 } 437 438 @Override 439 void inverseTransform2DPointsImpl(double[] srcPts, int srcOff, 440 double[] dstPts, int dstOff, int numPts) { 441 final double tx = getX(); 442 final double ty = getY(); 443 444 while (--numPts >= 0) { 445 dstPts[dstOff++] = srcPts[srcOff++] - tx; 446 dstPts[dstOff++] = srcPts[srcOff++] - ty; 447 } 448 } 449 450 @Override 451 void inverseTransform3DPointsImpl(double[] srcPts, int srcOff, 452 double[] dstPts, int dstOff, int numPts) { 453 454 final double tx = getX(); 455 final double ty = getY(); 456 final double tz = getZ(); 457 458 while (--numPts >= 0) { 459 dstPts[dstOff++] = srcPts[srcOff++] - tx; 460 dstPts[dstOff++] = srcPts[srcOff++] - ty; 461 dstPts[dstOff++] = srcPts[srcOff++] - tz; 462 } 463 } 464 465 @Override 466 public Point2D inverseDeltaTransform(double x, double y) { 467 ensureCanTransform2DPoint(); 468 return new Point2D(x, y); 469 } 470 471 @Override 472 public Point2D inverseDeltaTransform(Point2D point) { 473 if (point == null) { 474 throw new NullPointerException(); 475 } 476 ensureCanTransform2DPoint(); 477 return point; 478 } 479 480 @Override 481 public Point3D inverseDeltaTransform(double x, double y, double z) { 482 return new Point3D(x, y, z); 483 } 484 485 @Override 486 public Point3D inverseDeltaTransform(Point3D point) { 487 if (point == null) { 488 throw new NullPointerException(); 489 } 490 return point; 491 } 492 493 /* ************************************************************************* 494 * * 495 * Other API * 496 * * 497 **************************************************************************/ 498 499 /** 500 * Returns a string representation of this {@code Translate} object. 501 * @return a string representation of this {@code Translate} object. 502 */ 503 @Override 504 public String toString() { 505 final StringBuilder sb = new StringBuilder("Translate ["); 506 507 sb.append("x=").append(getX()); 508 sb.append(", y=").append(getY()); 509 sb.append(", z=").append(getZ()); 510 511 return sb.append("]").toString(); 512 } 513 514 /* ************************************************************************* 515 * * 516 * Internal implementation stuff * 517 * * 518 **************************************************************************/ 519 520 @Override 521 void apply(final Affine3D trans) { 522 trans.translate(getX(), getY(), getZ()); 523 } 524 525 @Override 526 BaseTransform derive(final BaseTransform trans) { 527 return trans.deriveWithTranslation(getX(), getY(), getZ()); 528 } 529 530 @Override 531 void validate() { 532 getX(); 533 getY(); 534 getZ(); 535 } 536 537 @Override 538 void appendTo(Affine a) { 539 a.appendTranslation(getTx(), getTy(), getTz()); 540 } 541 542 @Override 543 void prependTo(Affine a) { 544 a.prependTranslation(getTx(), getTy(), getTz()); 545 } 546 }