| 1 |
|
| 2 |
|
| 3 |
|
| 4 |
|
| 5 |
|
| 6 |
|
| 7 |
|
| 8 |
|
| 9 |
|
| 10 |
|
| 11 |
|
| 12 |
|
| 13 |
package org.locationtech.jts.geom.util; |
| 14 |
|
| 15 |
import org.locationtech.jts.geom.Coordinate; |
| 16 |
import org.locationtech.jts.geom.Envelope; |
| 17 |
import org.locationtech.jts.geom.Geometry; |
| 18 |
import org.locationtech.jts.geom.GeometryFactory; |
| 19 |
import org.locationtech.jts.geom.LinearRing; |
| 20 |
import org.locationtech.jts.geom.Polygon; |
| 21 |
import org.locationtech.jts.util.GeometricShapeFactory; |
| 22 |
|
| 23 |
/** |
| 24 |
* Creates geometries which are shaped like multi-armed stars |
| 25 |
* with each arm shaped like a sine wave. |
| 26 |
* These kinds of geometries are useful as a more complex |
| 27 |
* geometry for testing algorithms. |
| 28 |
* |
| 29 |
* @author Martin Davis |
| 30 |
* |
| 31 |
*/ |
| 32 |
public class SineStarFactory |
| 33 |
extends GeometricShapeFactory |
| 34 |
{ |
| 35 |
/** |
| 36 |
* Creates a sine star with the given parameters. |
| 37 |
* |
| 38 |
* @param origin the origin point |
| 39 |
* @param size the size of the star |
| 40 |
* @param nPts the number of points in the star |
| 41 |
* @param nArms the number of arms to generate |
| 42 |
* @param armLengthRatio the arm length ratio |
| 43 |
* @return a sine star shape |
| 44 |
*/ |
| 45 |
public static Geometry create(Coordinate origin, double size, int nPts, int nArms, double armLengthRatio) { |
| 46 |
SineStarFactory gsf = new SineStarFactory(); |
| 47 |
gsf.setCentre(origin); |
| 48 |
gsf.setSize(size); |
| 49 |
gsf.setNumPoints(nPts); |
| 50 |
gsf.setArmLengthRatio(armLengthRatio); |
| 51 |
gsf.setNumArms(nArms); |
| 52 |
Geometry poly = gsf.createSineStar(); |
| 53 |
return poly; |
| 54 |
} |
| 55 |
|
| 56 |
protected int numArms = 8; |
| 57 |
protected double armLengthRatio = 0.5; |
| 58 |
|
| 59 |
/** |
| 60 |
* Creates a factory which will create sine stars using the default |
| 61 |
* {@link GeometryFactory}. |
| 62 |
*/ |
| 63 |
public SineStarFactory() |
| 64 |
{ |
| 65 |
super(); |
| 66 |
} |
| 67 |
|
| 68 |
/** |
| 69 |
* Creates a factory which will create sine stars using the given |
| 70 |
* {@link GeometryFactory}. |
| 71 |
* |
| 72 |
* @param geomFact the factory to use |
| 73 |
*/ |
| 74 |
public SineStarFactory(GeometryFactory geomFact) |
| 75 |
{ |
| 76 |
super(geomFact); |
| 77 |
} |
| 78 |
|
| 79 |
/** |
| 80 |
* Sets the number of arms in the star |
| 81 |
* |
| 82 |
* @param numArms the number of arms to generate |
| 83 |
*/ |
| 84 |
public void setNumArms(int numArms) |
| 85 |
{ |
| 86 |
this.numArms = numArms; |
| 87 |
} |
| 88 |
|
| 89 |
/** |
| 90 |
* Sets the ratio of the length of each arm to the radius of the star. |
| 91 |
* A smaller number makes the arms shorter. |
| 92 |
* Value should be between 0.0 and 1.0 |
| 93 |
* |
| 94 |
* @param armLengthRatio the ratio determining the length of them arms. |
| 95 |
*/ |
| 96 |
public void setArmLengthRatio(double armLengthRatio) |
| 97 |
{ |
| 98 |
this.armLengthRatio = armLengthRatio; |
| 99 |
} |
| 100 |
|
| 101 |
/** |
| 102 |
* Generates the geometry for the sine star |
| 103 |
* |
| 104 |
* @return the geometry representing the sine star |
| 105 |
*/ |
| 106 |
public Geometry createSineStar() |
| 107 |
{ |
| 108 |
Envelope env = dim.getEnvelope(); |
| 109 |
double radius = env.getWidth() / 2.0; |
| 110 |
|
| 111 |
double armRatio = armLengthRatio; |
| 112 |
if (armRatio < 0.0) |
| 113 |
armRatio = 0.0; |
| 114 |
if (armRatio > 1.0) |
| 115 |
armRatio = 1.0; |
| 116 |
|
| 117 |
double armMaxLen = armRatio * radius; |
| 118 |
double insideRadius = (1 - armRatio) * radius; |
| 119 |
|
| 120 |
double centreX = env.getMinX() + radius; |
| 121 |
double centreY = env.getMinY() + radius; |
| 122 |
|
| 123 |
Coordinate[] pts = new Coordinate[nPts + 1]; |
| 124 |
int iPt = 0; |
| 125 |
for (int i = 0; i < nPts; i++) { |
| 126 |
|
| 127 |
double ptArcFrac = (i / (double) nPts) * numArms; |
| 128 |
double armAngFrac = ptArcFrac - Math.floor(ptArcFrac); |
| 129 |
|
| 130 |
|
| 131 |
|
| 132 |
double armAng = 2 * Math.PI * armAngFrac; |
| 133 |
|
| 134 |
double armLenFrac = (Math.cos(armAng) + 1.0) / 2.0; |
| 135 |
|
| 136 |
|
| 137 |
double curveRadius = insideRadius + armMaxLen * armLenFrac; |
| 138 |
|
| 139 |
|
| 140 |
double ang = i * (2 * Math.PI / nPts); |
| 141 |
double x = curveRadius * Math.cos(ang) + centreX; |
| 142 |
double y = curveRadius * Math.sin(ang) + centreY; |
| 143 |
pts[iPt++] = coord(x, y); |
| 144 |
} |
| 145 |
pts[iPt] = new Coordinate(pts[0]); |
| 146 |
|
| 147 |
LinearRing ring = geomFact.createLinearRing(pts); |
| 148 |
Polygon poly = geomFact.createPolygon(ring); |
| 149 |
return poly; |
| 150 |
} |
| 151 |
} |
| 152 |
|