Skip to content

Commit 1e7f248

Browse files
committed
Add TriangleFunctions.innerHexagon
1 parent 5eaa040 commit 1e7f248

File tree

1 file changed

+57
-2
lines changed

1 file changed

+57
-2
lines changed

modules/app/src/main/java/org/locationtech/jtstest/function/TriangleFunctions.java

Lines changed: 57 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
*/
1212
package org.locationtech.jtstest.function;
1313

14+
import org.locationtech.jts.algorithm.Orientation;
1415
import org.locationtech.jts.geom.Coordinate;
16+
import org.locationtech.jts.geom.CoordinateArrays;
1517
import org.locationtech.jts.geom.Geometry;
1618
import org.locationtech.jts.geom.GeometryFactory;
1719
import org.locationtech.jts.geom.LineSegment;
@@ -112,12 +114,65 @@ public static Geometry angleBisectors(Geometry g)
112114
return geomFact.createMultiLineString(line);
113115
}
114116

115-
116117
private static Coordinate[] trianglePts(Geometry g)
117118
{
118-
Coordinate[] pts = g.getCoordinates();
119+
Coordinate[] pts = CoordinateArrays.copyDeep(g.getCoordinates());
120+
if (Orientation.isCCW(pts)) {
121+
CoordinateArrays.reverse(pts);
122+
}
119123
if (pts.length < 3)
120124
throw new IllegalArgumentException("Input geometry must have at least 3 points");
121125
return pts;
122126
}
127+
128+
/**
129+
* Constructs the inner hexagon of a triangle,
130+
* created by intersecting the chords of the triangle running from each vertex to
131+
* points a distance of (side / nSections) from each end of the opposite side.
132+
*
133+
* When the parameter is 3 this provides a visualization of
134+
* Marion Walter's Theorem (https://en.wikipedia.org/wiki/Marion_Walter#Recognition).
135+
* The theorem states that if each side of an arbitrary triangle is trisected
136+
* and lines are drawn to the opposite vertices,
137+
* the area of the hexagon created in the middle is one-tenth the area of the original triangle.
138+
*
139+
* @param g a triangle
140+
* @param nSections the number of sections to divide each side into (>= 3)
141+
* @return the inner hexagon
142+
*/
143+
public static Geometry innerHexagon(Geometry g, int nSections) {
144+
Coordinate[] pts = trianglePts(g);
145+
//-- return empty polygon for degenerate cases
146+
if (nSections < 3) {
147+
return g.getFactory().createEmpty(2);
148+
}
149+
150+
LineSegment side0 = new LineSegment(pts[0], pts[1]);
151+
LineSegment side1 = new LineSegment(pts[1], pts[2]);
152+
LineSegment side2 = new LineSegment(pts[2], pts[0]);
153+
154+
double frac = 1.0 / nSections;
155+
LineSegment chord0a = chord(pts[0], side1, frac);
156+
LineSegment chord0b = chord(pts[0], side1, 1.0 - frac);
157+
LineSegment chord1a = chord(pts[1], side2, frac);
158+
LineSegment chord1b = chord(pts[1], side2, 1.0 - frac);
159+
LineSegment chord2a = chord(pts[2], side0, frac);
160+
LineSegment chord2b = chord(pts[2], side0, 1.0 - frac);
161+
162+
Coordinate[] hexPts = new Coordinate[7];
163+
hexPts[0] = chord0a.intersection(chord1b);
164+
hexPts[1] = chord0a.intersection(chord2b);
165+
hexPts[2] = chord1a.intersection(chord2b);
166+
hexPts[3] = chord1a.intersection(chord0b);
167+
hexPts[4] = chord2a.intersection(chord0b);
168+
hexPts[5] = chord2a.intersection(chord1b);
169+
hexPts[6] = hexPts[0].copy();
170+
171+
return g.getFactory().createPolygon(hexPts);
172+
}
173+
174+
private static LineSegment chord(Coordinate apex, LineSegment side, double frac) {
175+
Coordinate opp = side.pointAlong(frac);
176+
return new LineSegment(apex, opp);
177+
}
123178
}

0 commit comments

Comments
 (0)