Ejemplo n.º 1
0
 /**
  * Initialize this polygon to the intersection, union, or difference (A - B)
  * of the given two polygons. The "vertexMergeRadius" determines how close two
  * vertices must be to be merged together and how close a vertex must be to an
  * edge in order to be spliced into it (see S2PolygonBuilder for details). By
  * default, the merge radius is just large enough to compensate for errors
  * that occur when computing intersection points between edges
  * (S2EdgeUtil.DEFAULT_INTERSECTION_TOLERANCE).
  *
  * If you are going to convert the resulting polygon to a lower-precision
  * format, it is necessary to increase the merge radius in order to get a
  * valid result after rounding (i.e. no duplicate vertices, etc). For example,
  * if you are going to convert them to geostore.PolygonProto format, then
  * S1Angle.e7(1) is a good value for "vertex_merge_radius".
  *#/
  * public void initToIntersection(final S2Polygon a, final S2Polygon b) {
  * initToIntersectionSloppy(a, b, S2EdgeUtil.DEFAULT_INTERSECTION_TOLERANCE);
  * }
  *
  * public void initToIntersectionSloppy(
  * final S2Polygon a, final S2Polygon b, S1Angle vertexMergeRadius) {
  * Preconditions.checkState(numLoops() == 0);
  * if (!a.bound.intersects(b.bound)) {
  * return;
  * }
  *
  * // We want the boundary of A clipped to the interior of B,
  * // plus the boundary of B clipped to the interior of A,
  * // plus one copy of any directed edges that are in both boundaries.
  *
  * S2PolygonBuilder.Options options = S2PolygonBuilder.Options.DIRECTED_XOR;
  * options.setMergeDistance(vertexMergeRadius);
  * S2PolygonBuilder builder = new S2PolygonBuilder(options);
  * clipBoundary(a, false, b, false, false, true, builder);
  * clipBoundary(b, false, a, false, false, false, builder);
  * if (!builder.assemblePolygon(this, null)) {
  * // TODO (andriy): do something more meaningful here.
  * log.severe("Bad directed edges");
  * }
  * }
  *
  * public void initToUnion(final S2Polygon a, final S2Polygon b) {
  * initToUnionSloppy(a, b, S2EdgeUtil.DEFAULT_INTERSECTION_TOLERANCE);
  * }
  *
  * public void initToUnionSloppy(final S2Polygon a, final S2Polygon b, S1Angle vertexMergeRadius) {
  * Preconditions.checkState(numLoops() == 0);
  *
  * // We want the boundary of A clipped to the exterior of B,
  * // plus the boundary of B clipped to the exterior of A,
  * // plus one copy of any directed edges that are in both boundaries.
  *
  * S2PolygonBuilder.Options options = S2PolygonBuilder.Options.DIRECTED_XOR;
  * options.setMergeDistance(vertexMergeRadius);
  * S2PolygonBuilder builder = new S2PolygonBuilder(options);
  * clipBoundary(a, false, b, false, true, true, builder);
  * clipBoundary(b, false, a, false, true, false, builder);
  * if (!builder.assemblePolygon(this, null)) {
  * // TODO(andriy): do something more meaningful here.
  * log.severe("Bad directed edges");
  * }
  * }
  *
  * /**
  * Return a polygon which is the union of the given polygons. Note: clears the
  * List!
  *#/
  * public static S2Polygon destructiveUnion(List
  * <S2Polygon> polygons) {
  * return destructiveUnionSloppy(polygons, S2EdgeUtil.DEFAULT_INTERSECTION_TOLERANCE);
  * }
  *
  * /**
  * Return a polygon which is the union of the given polygons; combines
  * vertices that form edges that are almost identical, as defined by
  * vertexMergeRadius. Note: clears the List!
  *#/
  * public static S2Polygon destructiveUnionSloppy(
  * List
  * <S2Polygon> polygons, S1Angle vertexMergeRadius) {
  * // Effectively create a priority queue of polygons in order of number of
  * // vertices. Repeatedly union the two smallest polygons and add the result
  * // to the queue until we have a single polygon to return.
  *
  * // map: # of vertices -> polygon
  * TreeMultimap
  * <Integer
  * , S2Polygon> queue = TreeMultimap.create();
  *
  * for (S2Polygon polygon : polygons) {
  * queue.put(polygon.getNumVertices(), polygon);
  * }
  * polygons.clear();
  *
  * Set
  * <Map.Entry
  * <Integer
  * , S2Polygon>> queueSet = queue.entries();
  * while (queueSet.size() > 1) {
  * // Pop two simplest polygons from queue.
  * queueSet = queue.entries();
  * Iterator
  * <Map.Entry
  * <Integer
  * , S2Polygon>> smallestIter = queueSet.iterator();
  *
  * Map.Entry
  * <Integer
  * , S2Polygon> smallest = smallestIter.next();
  * int aSize = smallest.getKey().intValue();
  * S2Polygon aPolygon = smallest.getValue();
  * smallestIter.remove();
  *
  * smallest = smallestIter.next();
  * int bSize = smallest.getKey().intValue();
  * S2Polygon bPolygon = smallest.getValue();
  * smallestIter.remove();
  *
  * // Union and add result back to queue.
  * S2Polygon unionPolygon = new S2Polygon();
  * unionPolygon.initToUnionSloppy(aPolygon, bPolygon, vertexMergeRadius);
  * int unionSize = aSize + bSize;
  * queue.put(unionSize, unionPolygon);
  * // We assume that the number of vertices in the union polygon is the
  * // sum of the number of vertices in the original polygons, which is not
  * // always true, but will almost always be a decent approximation, and
  * // faster than recomputing.
  * }
  *
  * if (queue.isEmpty()) {
  * return new S2Polygon();
  * } else {
  * return queue.get(queue.asMap().firstKey()).first();
  * }
  * }
  *
  * public boolean isNormalized() {
  * Multiset
  * <S2Point> vertices = HashMultiset.
  * <S2Point>create();
  * S2Loop lastParent = null;
  * for (int i = 0; i < numLoops(); ++i) {
  * S2Loop child = loop(i);
  * if (child.depth() == 0) {
  * continue;
  * }
  * S2Loop parent = loop(getParent(i));
  * if (parent != lastParent) {
  * vertices.clear();
  * for (int j = 0; j < parent.numVertices(); ++j) {
  * vertices.add(parent.vertex(j));
  * }
  * lastParent = parent;
  * }
  * int count = 0;
  * for (int j = 0; j < child.numVertices(); ++j) {
  * if (vertices.count(child.vertex(j)) > 0) {
  * ++count;
  * }
  * }
  * if (count > 1) {
  * return false;
  * }
  * }
  * return true;
  * }
  *
  * /**
  * Return true if two polygons have the same boundary except for vertex
  * perturbations. Both polygons must have loops with the same cyclic vertex
  * order and the same nesting hierarchy, but the vertex locations are allowed
  * to differ by up to "max_error". Note: This method mostly useful only for
  * testing purposes.
  *#/
  * boolean boundaryApproxEquals(S2Polygon b, double maxError) {
  * if (numLoops() != b.numLoops()) {
  * log.severe(
  * "!= loops: " + Integer.toString(numLoops()) + " vs. " + Integer.toString(b.numLoops()));
  * return false;
  * }
  *
  * // For now, we assume that there is at most one candidate match for each
  * // loop. (So far this method is just used for testing.)
  * for (int i = 0; i < numLoops(); ++i) {
  * S2Loop aLoop = loop(i);
  * boolean success = false;
  * for (int j = 0; j < numLoops(); ++j) {
  * S2Loop bLoop = b.loop(j);
  * if (bLoop.depth() == aLoop.depth() && bLoop.boundaryApproxEquals(aLoop, maxError)) {
  * success = true;
  * break;
  * }
  * }
  * if (!success) {
  * return false;
  * }
  * }
  * return true;
  * }
  *
  * // S2Region interface (see S2Region.java for details):
  *
  * /** Return a bounding spherical cap. */
 public function getCapBound()
 {
     return $this->bound->getCapBound();
 }