package com.revolsys.geometry.test.function; import java.util.ArrayList; import java.util.List; import com.revolsys.geometry.model.BoundingBox; import com.revolsys.geometry.model.Geometry; import com.revolsys.geometry.model.GeometryFactory; import com.revolsys.geometry.model.Point; import com.revolsys.geometry.model.coordinates.list.CoordinatesListUtil; import com.revolsys.geometry.model.impl.PointDoubleXY; import com.revolsys.geometry.shape.random.RandomPointsBuilder; import com.revolsys.geometry.shape.random.RandomPointsInGridBuilder; public class CreateRandomShapeFunctions { private static double haltonOrdinate(final int index, final int base) { double result = 0; double f = 1.0 / base; int i = index; while (i > 0) { result = result + f * (i % base); i = (int)Math.floor(i / (double)base); f = f / base; } return result; } public static Geometry haltonPoints(final Geometry g, final int nPts) { return haltonPointsWithBases(g, nPts, 2, 3); } public static Geometry haltonPoints57(final Geometry g, final int nPts) { return haltonPointsWithBases(g, nPts, 5, 7); } public static Geometry haltonPointsWithBases(final Geometry g, final int nPts, final int basei, final int basej) { final BoundingBox env = FunctionsUtil.getEnvelopeOrDefault(g); final Point[] pts = new Point[nPts]; final double baseX = env.getMinX(); final double baseY = env.getMinY(); int i = 0; while (i < nPts) { final double x = baseX + env.getWidth() * haltonOrdinate(i + 1, basei); final double y = baseY + env.getHeight() * haltonOrdinate(i + 1, basej); final Point p = new PointDoubleXY(x, y); if (!env.covers(p)) { continue; } pts[i++] = p; } return FunctionsUtil.getFactoryOrDefault(g).punctual(pts); } public static Geometry randomLineString(final Geometry g, final int nPts) { final BoundingBox env = FunctionsUtil.getEnvelopeOrDefault(g); final GeometryFactory geomFact = FunctionsUtil.getFactoryOrDefault(g); final double width = env.getWidth(); final double hgt = env.getHeight(); final Point[] pts = new Point[nPts]; for (int i = 0; i < nPts; i++) { final double xLen = width * Math.random(); final double yLen = hgt * Math.random(); pts[i] = randomPtInRectangleAround(env.getCentre(), xLen, yLen); } return geomFact.lineString(pts); } private static Point randomPointInTriangle(final Point p0, final Point p1, final Point p2) { double s = Math.random(); double t = Math.random(); if (s + t > 1) { s = 1.0 - s; t = 1.0 - t; } final double a = 1 - (s + t); final double b = s; final double c = t; final double rpx = a * p0.getX() + b * p1.getX() + c * p2.getX(); final double rpy = a * p0.getY() + b * p1.getY() + c * p2.getY(); return new PointDoubleXY(rpx, rpy); } public static Geometry randomPoints(final Geometry g, final int nPts) { final RandomPointsBuilder shapeBuilder = new RandomPointsBuilder( FunctionsUtil.getFactoryOrDefault(g)); shapeBuilder.setExtent(FunctionsUtil.getEnvelopeOrDefault(g)); shapeBuilder.setNumPoints(nPts); return shapeBuilder.getGeometry(); } public static Geometry randomPointsInGrid(final Geometry g, final int nPts) { final RandomPointsInGridBuilder shapeBuilder = new RandomPointsInGridBuilder( FunctionsUtil.getFactoryOrDefault(g)); shapeBuilder.setExtent(FunctionsUtil.getEnvelopeOrDefault(g)); shapeBuilder.setNumPoints(nPts); return shapeBuilder.getGeometry(); } public static Geometry randomPointsInGridCircles(final Geometry g, final int nPts) { final RandomPointsInGridBuilder shapeBuilder = new RandomPointsInGridBuilder( FunctionsUtil.getFactoryOrDefault(g)); shapeBuilder.setExtent(FunctionsUtil.getEnvelopeOrDefault(g)); shapeBuilder.setNumPoints(nPts); shapeBuilder.setConstrainedToCircle(true); return shapeBuilder.getGeometry(); } public static Geometry randomPointsInGridWithGutter(final Geometry g, final int nPts, final double gutterFraction) { final RandomPointsInGridBuilder shapeBuilder = new RandomPointsInGridBuilder( FunctionsUtil.getFactoryOrDefault(g)); shapeBuilder.setExtent(FunctionsUtil.getEnvelopeOrDefault(g)); shapeBuilder.setNumPoints(nPts); shapeBuilder.setGutterFraction(gutterFraction); return shapeBuilder.getGeometry(); } public static Geometry randomPointsInPolygon(final Geometry g, final int nPts) { final RandomPointsBuilder shapeBuilder = new RandomPointsBuilder( FunctionsUtil.getFactoryOrDefault(g)); shapeBuilder.setExtent(g); shapeBuilder.setNumPoints(nPts); return shapeBuilder.getGeometry(); } public static Geometry randomPointsInTriangle(final Geometry g, final int nPts) { final GeometryFactory geomFact = FunctionsUtil.getFactoryOrDefault(g); final Point[] gpts = CoordinatesListUtil.getPointArray(g); final Point tri0 = gpts[0]; final Point tri1 = gpts[1]; final Point tri2 = gpts[2]; final List pts = new ArrayList(); for (int i = 0; i < nPts; i++) { pts.add(geomFact.point(randomPointInTriangle(tri0, tri1, tri2))); } return geomFact.buildGeometry(pts); } private static Point randomPtInRectangleAround(final Point centre, final double width, final double height) { final double x0 = centre.getX() + width * (Math.random() - 0.5); final double y0 = centre.getY() + height * (Math.random() - 0.5); return new PointDoubleXY(x0, y0); } public static Geometry randomRadialPoints(final Geometry g, final int nPts) { final BoundingBox env = FunctionsUtil.getEnvelopeOrDefault(g); final GeometryFactory geomFact = FunctionsUtil.getFactoryOrDefault(g); final double xLen = env.getWidth(); final double yLen = env.getHeight(); final double rMax = Math.min(xLen, yLen) / 2.0; final double centreX = env.getMinX() + xLen / 2; final double centreY = env.getMinY() + yLen / 2; final List pts = new ArrayList(); for (int i = 0; i < nPts; i++) { final double rand = Math.random(); // use rand^2 to accentuate radial distribution final double r = rMax * rand * rand; // produces even distribution // double r = rMax * Math.sqrt(rand); final double ang = 2 * Math.PI * Math.random(); final double x = centreX + r * Math.cos(ang); final double y = centreY + r * Math.sin(ang); pts.add(geomFact.point(x, y)); } return geomFact.buildGeometry(pts); } public static Geometry randomRectilinearWalk(final Geometry g, final int nPts) { final BoundingBox env = FunctionsUtil.getEnvelopeOrDefault(g); final GeometryFactory geomFact = FunctionsUtil.getFactoryOrDefault(g); final double xLen = env.getWidth(); final double yLen = env.getHeight(); final Point[] pts = new Point[nPts]; boolean xory = true; for (int i = 0; i < nPts; i++) { Point pt = null; if (i == 0) { pt = randomPtInRectangleAround(env.getCentre(), xLen, yLen); } else { final double dist = xLen * (Math.random() - 0.5); double x = pts[i - 1].getX(); double y = pts[i - 1].getY(); if (xory) { x += dist; } else { y += dist; } // switch orientation xory = !xory; pt = new PointDoubleXY(x, y); } pts[i] = pt; } return geomFact.lineString(pts); } public static Geometry randomSegments(final Geometry g, final int nPts) { final BoundingBox env = FunctionsUtil.getEnvelopeOrDefault(g); final GeometryFactory geomFact = FunctionsUtil.getFactoryOrDefault(g); final double xLen = env.getWidth(); final double yLen = env.getHeight(); final List lines = new ArrayList(); for (int i = 0; i < nPts; i++) { final double x0 = env.getMinX() + xLen * Math.random(); final double y0 = env.getMinY() + yLen * Math.random(); final double x1 = env.getMinX() + xLen * Math.random(); final double y1 = env.getMinY() + yLen * Math.random(); lines.add(geomFact.lineString(new Point[] { new PointDoubleXY(x0, y0), new PointDoubleXY(x1, y1) })); } return geomFact.buildGeometry(lines); } public static Geometry randomSegmentsInGrid(final Geometry g, final int nPts) { final BoundingBox env = FunctionsUtil.getEnvelopeOrDefault(g); final GeometryFactory geomFact = FunctionsUtil.getFactoryOrDefault(g); final int nCell = (int)Math.sqrt(nPts) + 1; final double xLen = env.getWidth() / nCell; final double yLen = env.getHeight() / nCell; final List lines = new ArrayList(); for (int i = 0; i < nCell; i++) { for (int j = 0; j < nCell; j++) { final double x0 = env.getMinX() + i * xLen + xLen * Math.random(); final double y0 = env.getMinY() + j * yLen + yLen * Math.random(); final double x1 = env.getMinX() + i * xLen + xLen * Math.random(); final double y1 = env.getMinY() + j * yLen + yLen * Math.random(); lines.add(geomFact.lineString(2, x0, y0, x1, y1)); } } return geomFact.buildGeometry(lines); } }