You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by ma...@apache.org on 2021/04/09 19:41:30 UTC
[commons-geometry] branch master updated: GEOMETRY-117:
implementing AffineTransformMatrix2D shear methods
This is an automated email from the ASF dual-hosted git repository.
mattjuntunen pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-geometry.git
The following commit(s) were added to refs/heads/master by this push:
new e50641a GEOMETRY-117: implementing AffineTransformMatrix2D shear methods
e50641a is described below
commit e50641a482161c79c0605828d5d19361bf66451d
Author: Matt Juntunen <ma...@apache.org>
AuthorDate: Thu Apr 8 23:28:10 2021 -0400
GEOMETRY-117: implementing AffineTransformMatrix2D shear methods
---
.../euclidean/twod/AffineTransformMatrix2D.java | 31 +++++
.../twod/AffineTransformMatrix2DTest.java | 127 +++++++++++++++++++++
2 files changed, 158 insertions(+)
diff --git a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/AffineTransformMatrix2D.java b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/AffineTransformMatrix2D.java
index 0b7f658..3ae67d4 100644
--- a/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/AffineTransformMatrix2D.java
+++ b/commons-geometry-euclidean/src/main/java/org/apache/commons/geometry/euclidean/twod/AffineTransformMatrix2D.java
@@ -301,6 +301,17 @@ public final class AffineTransformMatrix2D extends AbstractAffineTransformMatrix
return rotate(center, rotation.getAngle());
}
+ /** Apply a shear to the current instance, returning the result as a new transform.
+ * @param shx multiplier by which coordinates are shifted along the positive x-axis as a factor of their
+ * y coordinate; a value of 0 indicates no shift along the x-axis
+ * @param shy multiplier by which coordinates are shifted along the positive y-axis as a factor of their
+ * x coordinate; a value of 0 indicates no shift along the y-axis
+ * @return a new transform containing the result of applying a shear to the current instance
+ */
+ public AffineTransformMatrix2D shear(final double shx, final double shy) {
+ return multiply(createShear(shx, shy), this);
+ }
+
/** Get a new transform created by multiplying this instance by the argument.
* This is equivalent to the expression {@code A * M} where {@code A} is the
* current transform matrix and {@code M} is the given transform matrix. In
@@ -617,6 +628,26 @@ public final class AffineTransformMatrix2D extends AbstractAffineTransformMatrix
return createRotation(center, rotation.getAngle());
}
+ /** Create a transform representing a shear operation. The returned instance contains the
+ * matrix values
+ * <pre>
+ * [ 1, shx, 0 ]
+ * [ shy, 1, 0 ]
+ * [ 0, 0, 0 ]
+ * </pre>
+ * @param shx multiplier by which coordinates are shifted along the positive x-axis as a factor of their
+ * y coordinate; a value of 0 indicates no shift along the x-axis
+ * @param shy multiplier by which coordinates are shifted along the positive y-axis as a factor of their
+ * x coordinate; a value of 0 indicates no shift along the y-axis
+ * @return a new transform representing the shear operation
+ */
+ public static AffineTransformMatrix2D createShear(final double shx, final double shy) {
+ return new AffineTransformMatrix2D(
+ 1, shx, 0,
+ shy, 1, 0
+ );
+ }
+
/** Multiply two transform matrices together.
* @param a first transform
* @param b second transform
diff --git a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/AffineTransformMatrix2DTest.java b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/AffineTransformMatrix2DTest.java
index 1a14d3d..c713364 100644
--- a/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/AffineTransformMatrix2DTest.java
+++ b/commons-geometry-euclidean/src/test/java/org/apache/commons/geometry/euclidean/twod/AffineTransformMatrix2DTest.java
@@ -426,6 +426,57 @@ public class AffineTransformMatrix2DTest {
}
@Test
+ public void testCreateShear() {
+ // act
+ final AffineTransformMatrix2D transform = AffineTransformMatrix2D.createShear(2, 3);
+
+ // assert
+ final double[] expected = {
+ 1, 2, 0,
+ 3, 1, 0
+ };
+ Assertions.assertArrayEquals(expected, transform.toArray(), 0.0);
+ }
+
+ @Test
+ public void testShear() {
+ // arrange
+ final AffineTransformMatrix2D a = AffineTransformMatrix2D.of(
+ 1, 2, 3,
+ 4, 5, 6
+ );
+
+ // act
+ final AffineTransformMatrix2D result = a.shear(-2, 3);
+
+ // assert
+ final double[] expected = {
+ -7, -8, -9,
+ 7, 11, 15
+ };
+ Assertions.assertArrayEquals(expected, result.toArray(), EPS);
+ }
+
+ @Test
+ public void testShear_noShear() {
+ // arrange
+ final AffineTransformMatrix2D a = AffineTransformMatrix2D.of(
+ 1, 2, 3,
+ 4, 5, 6
+ );
+
+ // act
+ final AffineTransformMatrix2D result = a.shear(0, 0);
+
+ // assert
+ final double[] expected = {
+ 1, 2, 3,
+ 4, 5, 6
+ };
+ Assertions.assertArrayEquals(expected, result.toArray(), EPS);
+ }
+
+ @Test
public void testApply_identity() {
// arrange
final AffineTransformMatrix2D transform = AffineTransformMatrix2D.identity();
@@ -527,6 +578,82 @@ public class AffineTransformMatrix2DTest {
}
@Test
+ public void testApply_shearAlongX() {
+ // arrange
+ final double shearFactor = -2;
+ final AffineTransformMatrix2D transform = AffineTransformMatrix2D.identity()
+ .shear(shearFactor, 0);
+
+ // act/assert
+ runWithCoordinates((x, y) -> {
+ final Vector2D vec = Vector2D.of(x, y);
+
+ final Vector2D expectedVec = Vector2D.of(x + (shearFactor * y), y);
+
+ EuclideanTestUtils.assertCoordinatesEqual(expectedVec, transform.apply(vec), EPS);
+ });
+ }
+
+ @Test
+ public void testApply_shearAlongY() {
+ // arrange
+ final double shearFactor = 2;
+ final AffineTransformMatrix2D transform = AffineTransformMatrix2D.identity()
+ .shear(0, shearFactor);
+
+ // act/assert
+ runWithCoordinates((x, y) -> {
+ final Vector2D vec = Vector2D.of(x, y);
+
+ final Vector2D expectedVec = Vector2D.of(x, y + (shearFactor * x));
+
+ EuclideanTestUtils.assertCoordinatesEqual(expectedVec, transform.apply(vec), EPS);
+ });
+ }
+
+ @Test
+ public void testApply_shearAlongXAndY() {
+ // arrange
+ final double shearX = 2;
+ final double shearY = -3;
+ final AffineTransformMatrix2D transform = AffineTransformMatrix2D.identity()
+ .shear(shearX, shearY);
+
+ // act/assert
+ runWithCoordinates((x, y) -> {
+ final Vector2D vec = Vector2D.of(x, y);
+
+ final Vector2D expectedVec = Vector2D.of(x + (shearX * y), y + (shearY * x));
+
+ EuclideanTestUtils.assertCoordinatesEqual(expectedVec, transform.apply(vec), EPS);
+ });
+ }
+
+ @Test
+ public void testApply_translateShear() {
+ // arrange
+ final Vector2D translation = Vector2D.of(7, 8);
+ final double shearX = -4;
+ final double shearY = 5;
+ final AffineTransformMatrix2D transform = AffineTransformMatrix2D.identity()
+ .translate(translation)
+ .shear(shearX, shearY);
+
+ // act/assert
+ runWithCoordinates((x, y) -> {
+ final Vector2D vec = Vector2D.of(x, y);
+
+ final double tx = x + translation.getX();
+ final double ty = y + translation.getY();
+
+ final Vector2D expectedVec = Vector2D.of(tx + (shearX * ty), ty + (shearY * tx));
+
+ EuclideanTestUtils.assertCoordinatesEqual(expectedVec, transform.apply(vec), EPS);
+ });
+ }
+
+
+ @Test
public void testApply_translateScaleRotate() {
// arrange
final Vector2D translation = Vector2D.of(-2.0, -3.0);