- * Returns an ID associated with the current Geometry. The ID is passed - * along and is returned by some operators to preserve relationship between - * the input and output geometry classes. It is not always possible to - * preserve an ID during an operation. - */ - public abstract long getByteBufferID(); - - public abstract SimpleStateEnum getSimpleState(); - - public abstract String getFeatureID(); - - public abstract boolean hasNext(); + /** + * Moves the cursor to the next ByteBuffer. Returns null when reached the + * end. + */ + public abstract ByteBuffer next(); + + /** + * Returns the ID of the current ByteBuffer. The ID is propagated across the + * operations (when possible). + *
+ * Returns an ID associated with the current Geometry. The ID is passed
+ * along and is returned by some operators to preserve relationship between
+ * the input and output geometry classes. It is not always possible to
+ * preserve an ID during an operation.
+ */
+ public abstract long getByteBufferID();
+
+ public abstract SimpleStateEnum getSimpleState();
+
+ public abstract String getFeatureID();
+
+ public abstract boolean hasNext();
}
diff --git a/src/main/java/com/esri/core/geometry/ClassicSort.java b/src/main/java/com/esri/core/geometry/ClassicSort.java
index 8a5d0355..b6828897 100644
--- a/src/main/java/com/esri/core/geometry/ClassicSort.java
+++ b/src/main/java/com/esri/core/geometry/ClassicSort.java
@@ -28,8 +28,8 @@
package com.esri.core.geometry;
abstract class ClassicSort {
- public abstract void userSort(int begin, int end,
- AttributeStreamOfInt32 indices);
+ public abstract void userSort(int begin, int end,
+ AttributeStreamOfInt32 indices);
- public abstract double getValue(int index);
+ public abstract double getValue(int index);
}
diff --git a/src/main/java/com/esri/core/geometry/Clipper.java b/src/main/java/com/esri/core/geometry/Clipper.java
index 08e19e8d..59dc9d1d 100644
--- a/src/main/java/com/esri/core/geometry/Clipper.java
+++ b/src/main/java/com/esri/core/geometry/Clipper.java
@@ -24,1249 +24,1249 @@
package com.esri.core.geometry;
class Clipper {
- Envelope2D m_extent;
- EditShape m_shape;
- int m_geometry;
- int m_vertices_on_extent_index;
- AttributeStreamOfInt32 m_vertices_on_extent;
-
- int checkSegmentIntersection_(Envelope2D seg_env, int side,
- double clip_value) {
- switch (side) {
- case 0:
- if (seg_env.xmin < clip_value && seg_env.xmax <= clip_value) {
- return 0; // outside (or on the border)
- } else if (seg_env.xmin >= clip_value) {
- return 1;// inside
- } else
- return -1; // intersects
- case 1:
- if (seg_env.ymin < clip_value && seg_env.ymax <= clip_value) {
- return 0;
- } else if (seg_env.ymin >= clip_value) {
- return 1;
- } else
- return -1;
- case 2:
- if (seg_env.xmin >= clip_value && seg_env.xmax > clip_value) {
- return 0;
- } else if (seg_env.xmax <= clip_value) {
- return 1;
- } else
- return -1;
- case 3:
- if (seg_env.ymin >= clip_value && seg_env.ymax > clip_value) {
- return 0;
- } else if (seg_env.ymax <= clip_value) {
- return 1;
- } else
- return -1;
- }
- assert (false);// cannot be here
- return 0;
- }
-
- MultiPath clipMultiPath2_(MultiPath multi_path_in, double tolerance,
- double densify_dist) {
- boolean b_is_polygon = multi_path_in.getType() == Geometry.Type.Polygon;
- if (b_is_polygon)
- return clipPolygon2_((Polygon) multi_path_in, tolerance,
- densify_dist);
- else
- return clipPolyline_((Polyline) multi_path_in, tolerance);
- }
-
- MultiPath clipPolygon2_(Polygon polygon_in, double tolerance,
- double densify_dist) {
- // If extent is degenerate, return 0.
- if (m_extent.getWidth() == 0 || m_extent.getHeight() == 0)
- return (MultiPath) polygon_in.createInstance();
-
- Envelope2D orig_env2D = new Envelope2D();
- polygon_in.queryLooseEnvelope(orig_env2D);
-
- // m_shape = GCNEW Edit_shape();
- m_geometry = m_shape.addGeometry(polygon_in);
-
- // Forward decl for java port
- Envelope2D seg_env = new Envelope2D();
- Envelope2D sub_seg_env = new Envelope2D();
- Point2D pt_1 = new Point2D();
- Point2D pt_2 = new Point2D();
- double[] result_ordinates = new double[9];
- double[] parameters = new double[9];
- SegmentBuffer sub_segment_buffer = new SegmentBuffer();
- Line line = new Line();
- AttributeStreamOfInt32 delete_candidates = new AttributeStreamOfInt32(0);
- delete_candidates.reserve(Math.min(100, polygon_in.getPointCount()));
- // clip the polygon successively by each plane
- boolean b_all_outside = false;
- for (int iclip_plane = 0; !b_all_outside && iclip_plane < 4; iclip_plane++) {
- boolean b_intersects_plane = false;
- boolean b_axis_x = (iclip_plane & 1) != 0;
- double clip_value = 0;
- switch (iclip_plane) {
- case 0:
- clip_value = m_extent.xmin;
- b_intersects_plane = orig_env2D.xmin <= clip_value
- && orig_env2D.xmax >= clip_value;
- assert (b_intersects_plane || clip_value < orig_env2D.xmin);
- break;
- case 1:
- clip_value = m_extent.ymin;
- b_intersects_plane = orig_env2D.ymin <= clip_value
- && orig_env2D.ymax >= clip_value;
- assert (b_intersects_plane || clip_value < orig_env2D.ymin);
- break;
- case 2:
- clip_value = m_extent.xmax;
- b_intersects_plane = orig_env2D.xmin <= clip_value
- && orig_env2D.xmax >= clip_value;
- assert (b_intersects_plane || clip_value > orig_env2D.xmax);
- break;
- case 3:
- clip_value = m_extent.ymax;
- b_intersects_plane = orig_env2D.ymin <= clip_value
- && orig_env2D.ymax >= clip_value;
- assert (b_intersects_plane || clip_value > orig_env2D.ymax);
- break;
- }
-
- if (!b_intersects_plane)
- continue;// Optimize for common case when only few sides of the
- // clipper envelope intersect the geometry.
-
- b_all_outside = true;
- for (int path = m_shape.getFirstPath(m_geometry); path != -1; ) {
- int inside = -1;
- int firstinside = -1;
- int first = m_shape.getFirstVertex(path);
- int vertex = first;
- do {
- Segment segment = m_shape.getSegment(vertex);
- if (segment == null) {
- segment = line;
- m_shape.getXY(vertex, pt_1);
- segment.setStartXY(pt_1);
- m_shape.getXY(m_shape.getNextVertex(vertex), pt_2);
- segment.setEndXY(pt_2);
- }
- segment.queryEnvelope2D(seg_env);
- int seg_plane_intersection_status = checkSegmentIntersection_(
- seg_env, iclip_plane, clip_value);
- int split_count = 0;
- int next_vertex = -1;
-
- if (seg_plane_intersection_status == -1) // intersects plane
- {
- int count = segment.intersectionWithAxis2D(b_axis_x,
- clip_value, result_ordinates, parameters);
- if (count > 0) {
- split_count = m_shape.splitSegment(vertex,
- parameters, count);
- } else {
- assert (count == 0);// might be -1 when the segment
- // is almost parallel to the
- // clip lane. Just to see this
- // happens.
- split_count = 0;
- }
-
- // add +1 to ensure we check the original segment if no
- // split produced due to degeneracy.
- // Also +1 is necessary to check the last segment of the
- // split
- split_count += 1;// split_count will never be 0 after
- // this if-block.
-
- int split_vert = vertex;
- int next_split_vert = m_shape.getNextVertex(split_vert);
- for (int i = 0; i < split_count; i++) {
- m_shape.getXY(split_vert, pt_1);
- m_shape.getXY(next_split_vert, pt_2);
-
- Segment sub_seg = m_shape.getSegment(split_vert);
- if (sub_seg == null) {
- sub_seg = line;
- sub_seg.setStartXY(pt_1);
- sub_seg.setEndXY(pt_2);
- }
-
- sub_seg.queryEnvelope2D(sub_seg_env);
- int sub_segment_plane_intersection_status = checkSegmentIntersection_(
- sub_seg_env, iclip_plane, clip_value);
- if (sub_segment_plane_intersection_status == -1) {
- // subsegment is intertsecting the plane. We
- // need to snap one of the endpoints to ensure
- // no intersection.
- // TODO: ensure this works for curves. For
- // curves we have to adjust the curve shape.
- if (!b_axis_x) {
- assert ((pt_1.x < clip_value && pt_2.x > clip_value) || (pt_1.x > clip_value && pt_2.x < clip_value));
- double d_1 = Math.abs(pt_1.x - clip_value);
- double d_2 = Math.abs(pt_2.x - clip_value);
- if (d_1 < d_2) {
- pt_1.x = clip_value;
- m_shape.setXY(split_vert, pt_1);
- } else {
- pt_2.x = clip_value;
- m_shape.setXY(next_split_vert, pt_2);
- }
- } else {
- assert ((pt_1.y < clip_value && pt_2.y > clip_value) || (pt_1.y > clip_value && pt_2.y < clip_value));
- double d_1 = Math.abs(pt_1.y - clip_value);
- double d_2 = Math.abs(pt_2.y - clip_value);
- if (d_1 < d_2) {
- pt_1.y = clip_value;
- m_shape.setXY(split_vert, pt_1);
- } else {
- pt_2.y = clip_value;
- m_shape.setXY(next_split_vert, pt_2);
- }
- }
-
- // after the endpoint has been adjusted, recheck
- // the segment.
- sub_seg = m_shape.getSegment(split_vert);
- if (sub_seg == null) {
- sub_seg = line;
- sub_seg.setStartXY(pt_1);
- sub_seg.setEndXY(pt_2);
- }
- sub_seg.queryEnvelope2D(sub_seg_env);
- sub_segment_plane_intersection_status = checkSegmentIntersection_(
- sub_seg_env, iclip_plane, clip_value);
- }
-
- assert (sub_segment_plane_intersection_status != -1);
-
- int old_inside = inside;
- inside = sub_segment_plane_intersection_status;
- if (firstinside == -1)
- firstinside = inside;
-
- // add connections along the clipping plane line
- if (old_inside == 0 && inside == 1) {
- // going from outside to inside. Do nothing
- } else if (old_inside == 1 && inside == 0) {
- // going from inside to outside
- } else if (old_inside == 0 && inside == 0) {
- // staying outside
- // remember the start point of the outside
- // segment to be deleted.
- delete_candidates.add(split_vert); // is a
- // candidate
- // to be
- // deleted
- }
-
- if (inside == 1) {
- b_all_outside = false;
- }
-
- split_vert = next_split_vert;
- next_vertex = split_vert;
- next_split_vert = m_shape
- .getNextVertex(next_split_vert);
- }
- }
-
- if (split_count == 0) {
- assert (seg_plane_intersection_status != -1);// cannot
- // happen.
- int old_inside = inside;
- inside = seg_plane_intersection_status;
- if (firstinside == -1)
- firstinside = inside;
-
- if (old_inside == 0 && inside == 1) {
- // going from outside to inside.
- } else if (old_inside == 1 && inside == 0) {
- // going from inside to outside
- } else if (old_inside == 0 && inside == 0) {
- // remember the start point of the outside segment
- // to be deleted.
- delete_candidates.add(vertex); // is a candidate to
- // be deleted
- }
-
- if (inside == 1) {
- b_all_outside = false;
- }
-
- next_vertex = m_shape.getNextVertex(vertex);
- }
- vertex = next_vertex;
- } while (vertex != first);
-
- if (firstinside == 0 && inside == 0) {// first vertex need to be
- // deleted.
- delete_candidates.add(first); // is a candidate to be
- // deleted
- }
-
- for (int i = 0, n = delete_candidates.size(); i < n; i++) {
- int delete_vert = delete_candidates.get(i);
- m_shape.removeVertex(delete_vert, false);
- }
- delete_candidates.clear(false);
- if (m_shape.getPathSize(path) < 3) {
- path = m_shape.removePath(path);
- } else {
- path = m_shape.getNextPath(path);
- }
- }
- }
-
- if (b_all_outside)
- return (MultiPath) polygon_in.createInstance();
-
- // After the clipping, we could have produced unwanted segment overlaps
- // along the clipping envelope boundary.
- // Detect and resolve that case if possible.
- resolveBoundaryOverlaps_();
- if (densify_dist > 0)
- densifyAlongClipExtent_(densify_dist);
-
- return (MultiPath) m_shape.getGeometry(m_geometry);
- }
-
- MultiPath clipPolyline_(Polyline polyline_in, double tolerance) {
- // Forward decl for java port
- Envelope2D seg_env = new Envelope2D();
- Envelope2D sub_seg_env = new Envelope2D();
- double[] result_ordinates = new double[9];
- double[] parameters = new double[9];
- SegmentBuffer sub_segment_buffer = new SegmentBuffer();
- MultiPath result_poly = polyline_in;
- Envelope2D orig_env2D = new Envelope2D();
- polyline_in.queryLooseEnvelope(orig_env2D);
- for (int iclip_plane = 0; iclip_plane < 4; iclip_plane++) {
- boolean b_intersects_plane = false;
- boolean b_axis_x = (iclip_plane & 1) != 0;
- double clip_value = 0;
- switch (iclip_plane) {
- case 0:
- clip_value = m_extent.xmin;
- b_intersects_plane = orig_env2D.xmin <= clip_value
- && orig_env2D.xmax >= clip_value;
- assert (b_intersects_plane || clip_value < orig_env2D.xmin);
- break;
- case 1:
- clip_value = m_extent.ymin;
- b_intersects_plane = orig_env2D.ymin <= clip_value
- && orig_env2D.ymax >= clip_value;
- assert (b_intersects_plane || clip_value < orig_env2D.ymin);
- break;
- case 2:
- clip_value = m_extent.xmax;
- b_intersects_plane = orig_env2D.xmin <= clip_value
- && orig_env2D.xmax >= clip_value;
- assert (b_intersects_plane || clip_value > orig_env2D.xmax);
- break;
- case 3:
- clip_value = m_extent.ymax;
- b_intersects_plane = orig_env2D.ymin <= clip_value
- && orig_env2D.ymax >= clip_value;
- assert (b_intersects_plane || clip_value > orig_env2D.ymax);
- break;
- }
-
- if (!b_intersects_plane)
- continue;// Optimize for common case when only few sides of the
- // clipper envelope intersect the geometry.
-
- MultiPath src_poly = result_poly;
- result_poly = (MultiPath) polyline_in.createInstance();
-
- MultiPathImpl mp_impl_src = (MultiPathImpl) src_poly._getImpl();
- SegmentIteratorImpl seg_iter = mp_impl_src.querySegmentIterator();
- seg_iter.resetToFirstPath();
- Point2D pt_prev;
- Point2D pt = new Point2D();
- while (seg_iter.nextPath()) {
- int inside = -1;
- boolean b_start_new_path = true;
- while (seg_iter.hasNextSegment()) {
- Segment segment = seg_iter.nextSegment();
- segment.queryEnvelope2D(seg_env);
- int seg_plane_intersection_status = checkSegmentIntersection_(
- seg_env, iclip_plane, clip_value);
- if (seg_plane_intersection_status == -1) // intersects plane
- {
- int count = segment.intersectionWithAxis2D(b_axis_x,
- clip_value, result_ordinates, parameters);
- if (count > 0) {
- double t0 = 0.0;
- pt_prev = segment.getStartXY();
- for (int i = 0; i <= count; i++) {
- double t = i < count ? parameters[i] : 1.0;
- if (t0 == t)
- continue;
-
- segment.cut(t0, t, sub_segment_buffer);
- Segment sub_seg = sub_segment_buffer.get();
- sub_seg.setStartXY(pt_prev);
- if (i < count) {// snap to plane
- if (b_axis_x) {
- pt.x = result_ordinates[i];
- pt.y = clip_value;
- } else {
- pt.x = clip_value;
- pt.y = result_ordinates[i];
- }
- sub_seg.setEndXY(pt);
- }
-
- sub_seg.queryEnvelope2D(sub_seg_env);
- int sub_segment_plane_intersection_status = checkSegmentIntersection_(
- sub_seg_env, iclip_plane, clip_value);
-
- if (sub_segment_plane_intersection_status == -1) {
- // subsegment is intertsecting the plane. We
- // need to snap one of the endpoints to
- // ensure no intersection.
- // TODO: ensure this works for curves. For
- // curves we have to adjust the curve shape.
- Point2D pt_1 = sub_seg.getStartXY();
- Point2D pt_2 = sub_seg.getEndXY();
- if (!b_axis_x) {
- assert ((pt_1.x < clip_value && pt_2.x > clip_value) || (pt_1.x > clip_value && pt_2.x < clip_value));
- double d_1 = Math.abs(pt_1.x
- - clip_value);
- double d_2 = Math.abs(pt_2.x
- - clip_value);
- if (d_1 < d_2) {
- pt_1.x = clip_value;
- sub_seg.setStartXY(pt_1);
- } else {
- pt_2.x = clip_value;
- sub_seg.setEndXY(pt_2);
- }
- } else {
- assert ((pt_1.y < clip_value && pt_2.y > clip_value) || (pt_1.y > clip_value && pt_2.y < clip_value));
- double d_1 = Math.abs(pt_1.y
- - clip_value);
- double d_2 = Math.abs(pt_2.y
- - clip_value);
- if (d_1 < d_2) {
- pt_1.y = clip_value;
- sub_seg.setStartXY(pt_1);
- } else {
- pt_2.y = clip_value;
- sub_seg.setEndXY(pt_2);
- }
- }
-
- // after the endpoint has been adjusted,
- // recheck the segment.
- sub_seg.queryEnvelope2D(sub_seg_env);
- sub_segment_plane_intersection_status = checkSegmentIntersection_(
- sub_seg_env, iclip_plane,
- clip_value);
- }
-
- assert (sub_segment_plane_intersection_status != -1);
-
- pt_prev = sub_seg.getEndXY();
- t0 = t;
-
- inside = sub_segment_plane_intersection_status;
- if (inside == 1) {
- result_poly.addSegment(sub_seg,
- b_start_new_path);
- b_start_new_path = false;
- } else
- b_start_new_path = true;
- }
- }
- } else {
- inside = seg_plane_intersection_status;
- if (inside == 1) {
- result_poly.addSegment(segment, b_start_new_path);
- b_start_new_path = false;
- } else
- b_start_new_path = true;
- }
- }
- }
- }
-
- return result_poly;
- }
-
- void resolveBoundaryOverlaps_() {
- m_vertices_on_extent_index = -1;
- splitSegments_(false, m_extent.xmin);
- splitSegments_(false, m_extent.xmax);
- splitSegments_(true, m_extent.ymin);
- splitSegments_(true, m_extent.ymax);
-
- m_vertices_on_extent.resize(0);
- m_vertices_on_extent.reserve(100);
- m_vertices_on_extent_index = m_shape.createUserIndex();
-
- Point2D pt = new Point2D();
- for (int path = m_shape.getFirstPath(m_geometry); path != -1; path = m_shape
- .getNextPath(path)) {
- int vertex = m_shape.getFirstVertex(path);
- for (int ivert = 0, nvert = m_shape.getPathSize(path); ivert < nvert; ivert++, vertex = m_shape
- .getNextVertex(vertex)) {
- m_shape.getXY(vertex, pt);
- if (m_extent.xmin == pt.x || m_extent.xmax == pt.x
- || m_extent.ymin == pt.y || m_extent.ymax == pt.y) {
- m_shape.setUserIndex(vertex, m_vertices_on_extent_index,
- m_vertices_on_extent.size());
- m_vertices_on_extent.add(vertex);
- }
- }
- }
- // dbg_check_path_first_();
- resolveOverlaps_(false, m_extent.xmin);
- // dbg_check_path_first_();
- resolveOverlaps_(false, m_extent.xmax);
- // dbg_check_path_first_();
- resolveOverlaps_(true, m_extent.ymin);
- // dbg_check_path_first_();
- resolveOverlaps_(true, m_extent.ymax);
- fixPaths_();
- }
-
- void densifyAlongClipExtent_(double densify_dist) {
- assert (densify_dist > 0);
- Point2D pt_1 = new Point2D();
- Point2D pt_2 = new Point2D();
- double[] split_scalars = new double[2048];
- for (int path = m_shape.getFirstPath(m_geometry); path != -1; path = m_shape
- .getNextPath(path)) {
- int first_vertex = m_shape.getFirstVertex(path);
- int vertex = first_vertex;
- do {
- int next_vertex = m_shape.getNextVertex(vertex);
- m_shape.getXY(vertex, pt_1);
- int b_densify_x = -1;
- if (pt_1.x == m_extent.xmin) {
- m_shape.getXY(next_vertex, pt_2);
- if (pt_2.x == m_extent.xmin) {
- b_densify_x = 1;
- }
- } else if (pt_1.x == m_extent.xmax) {
- m_shape.getXY(next_vertex, pt_2);
- if (pt_2.x == m_extent.xmax) {
- b_densify_x = 1;
- }
- }
-
- if (pt_1.y == m_extent.ymin) {
- m_shape.getXY(next_vertex, pt_2);
- if (pt_2.y == m_extent.ymin) {
- b_densify_x = 0;
- }
- } else if (pt_1.y == m_extent.ymax) {
- m_shape.getXY(next_vertex, pt_2);
- if (pt_2.y == m_extent.ymax) {
- b_densify_x = 0;
- }
- }
-
- if (b_densify_x == -1) {
- vertex = next_vertex;
- continue;
- }
-
- double len = Point2D.distance(pt_1, pt_2);
- int num = (int) Math.min(Math.ceil(len / densify_dist), 2048.0);
- if (num <= 1) {
- vertex = next_vertex;
- continue;
- }
-
- for (int i = 1; i < num; i++) {
- split_scalars[i - 1] = (1.0 * i) / num;
- }
-
- int actual_splits = m_shape.splitSegment(vertex, split_scalars,
- num - 1);
- assert (actual_splits == num - 1);
- vertex = next_vertex;
- } while (vertex != first_vertex);
- }
- }
-
- void splitSegments_(boolean b_axis_x, double clip_value) {
- // After the clipping, we could have produced unwanted segment overlaps
- // along the clipping envelope boundary.
- // Detect and resolve that case if possible.
- int usage_index = m_shape.createUserIndex();
- Point2D pt = new Point2D();
- AttributeStreamOfInt32 sorted_vertices = new AttributeStreamOfInt32(0);
- sorted_vertices.reserve(100);
- for (int path = m_shape.getFirstPath(m_geometry); path != -1; path = m_shape
- .getNextPath(path)) {
- int vertex = m_shape.getFirstVertex(path);
- for (int ivert = 0, nvert = m_shape.getPathSize(path); ivert < nvert; ivert++) {
- int next_vertex = m_shape.getNextVertex(vertex);
- m_shape.getXY(vertex, pt);
- if (b_axis_x ? pt.y == clip_value : pt.x == clip_value) {
- m_shape.getXY(next_vertex, pt);
- if (b_axis_x ? pt.y == clip_value : pt.x == clip_value) {
- if (m_shape.getUserIndex(vertex, usage_index) != 1) {
- sorted_vertices.add(vertex);
- m_shape.setUserIndex(vertex, usage_index, 1);
- }
-
- if (m_shape.getUserIndex(next_vertex, usage_index) != 1) {
- sorted_vertices.add(next_vertex);
- m_shape.setUserIndex(next_vertex, usage_index, 1);
- }
- }
- }
- vertex = next_vertex;
- }
- }
-
- m_shape.removeUserIndex(usage_index);
- if (sorted_vertices.size() < 3) {
- return;
- }
-
- sorted_vertices.Sort(0, sorted_vertices.size(),
- new ClipperVertexComparer(this));
-
- Point2D pt_tmp = new Point2D(); // forward declare for java port
- // optimization
- Point2D pt_0 = new Point2D();
- Point2D pt_1 = new Point2D();
- pt_0.setNaN();
- int index_0 = -1;
- AttributeStreamOfInt32 active_intervals = new AttributeStreamOfInt32(0);
- AttributeStreamOfInt32 new_active_intervals = new AttributeStreamOfInt32(
- 0);
-
- int node1 = m_shape.createUserIndex();
- int node2 = m_shape.createUserIndex();
- for (int index = 0, n = sorted_vertices.size(); index < n; index++) {
- int vert = sorted_vertices.get(index);
- m_shape.getXY(vert, pt);
- if (!pt.isEqual(pt_0)) {
- if (index_0 == -1) {
- index_0 = index;
- pt_0.setCoords(pt);
- continue;
- }
-
- // add new intervals, that started at pt_0
- for (int i = index_0; i < index; i++) {
- int v = sorted_vertices.get(i);
- int nextv = m_shape.getNextVertex(v);
- int prevv = m_shape.getPrevVertex(v);
- boolean bAdded = false;
- if (compareVertices_(v, nextv) < 0) {
- m_shape.getXY(nextv, pt_tmp);
- if (b_axis_x ? pt_tmp.y == clip_value
- : pt_tmp.x == clip_value) {
- active_intervals.add(v);
- bAdded = true;
- m_shape.setUserIndex(v, node2, 1);
- }
- }
- if (compareVertices_(v, prevv) < 0) {
- m_shape.getXY(prevv, pt_tmp);
- if (b_axis_x ? pt_tmp.y == clip_value
- : pt_tmp.x == clip_value) {
- if (!bAdded)
- active_intervals.add(v);
- m_shape.setUserIndex(v, node1, 1);
- }
- }
- }
-
- // Split all active intervals at new point
- for (int ia = 0, na = active_intervals.size(); ia < na; ia++) {
- int v = active_intervals.get(ia);
- int n_1 = m_shape.getUserIndex(v, node1);
- int n_2 = m_shape.getUserIndex(v, node2);
- if (n_1 == 1) {
- int prevv = m_shape.getPrevVertex(v);
- m_shape.getXY(prevv, pt_1);
- double[] t = new double[1];
- t[0] = 0;
- if (!pt_1.isEqual(pt)) {// Split the active segment
- double active_segment_length = Point2D
- .distance(pt_0, pt_1);
- t[0] = Point2D.distance(pt_1, pt)
- / active_segment_length;
- assert (t[0] >= 0 && t[0] <= 1.0);
- if (t[0] == 0)
- t[0] = NumberUtils.doubleEps();// some
- // roundoff
- // issue.
- // split
- // anyway.
- else if (t[0] == 1.0) {
- t[0] = 1.0 - NumberUtils.doubleEps();// some
- // roundoff
- // issue.
- // split
- // anyway.
- assert (t[0] != 1.0);
- }
-
- int split_count = m_shape.splitSegment(prevv,
- t, 1);
- assert (split_count > 0);
- int v_1 = m_shape.getPrevVertex(v);
- m_shape.setXY(v_1, pt);
- new_active_intervals.add(v_1);
- m_shape.setUserIndex(v_1, node1, 1);
- m_shape.setUserIndex(v_1, node2, -1);
- } else {
- // The active segment ends at the current point.
- // We skip it, and it goes away.
- }
- }
- if (n_2 == 1) {
- int nextv = m_shape.getNextVertex(v);
- m_shape.getXY(nextv, pt_1);
- double[] t = new double[1];
- t[0] = 0;
- if (!pt_1.isEqual(pt)) {
- double active_segment_length = Point2D
- .distance(pt_0, pt_1);
- t[0] = Point2D.distance(pt_0, pt)
- / active_segment_length;
- assert (t[0] >= 0 && t[0] <= 1.0);
- if (t[0] == 0)
- t[0] = NumberUtils.doubleEps();// some
- // roundoff
- // issue.
- // split
- // anyway.
- else if (t[0] == 1.0) {
- t[0] = 1.0 - NumberUtils.doubleEps();// some
- // roundoff
- // issue.
- // split
- // anyway.
- assert (t[0] != 1.0);
- }
-
- int split_count = m_shape.splitSegment(v, t, 1);
- assert (split_count > 0);
- int v_1 = m_shape.getNextVertex(v);
- m_shape.setXY(v_1, pt);
- new_active_intervals.add(v_1);
- m_shape.setUserIndex(v_1, node1, -1);
- m_shape.setUserIndex(v_1, node2, 1);
- }
- }
- }
-
- AttributeStreamOfInt32 tmp = active_intervals;
- active_intervals = new_active_intervals;
- new_active_intervals = tmp;
- new_active_intervals.clear(false);
-
- index_0 = index;
- pt_0.setCoords(pt);
- }
- }
-
- m_shape.removeUserIndex(node1);
- m_shape.removeUserIndex(node2);
- }
-
- void resolveOverlaps_(boolean b_axis_x, double clip_value) {
- // Along the envelope boundary there could be overlapped segments.
- // Example, exterior ring with a hole is cut with a line, that
- // passes through the center of the hole.
- // Detect pairs of opposite overlapping segments and get rid of them
- Point2D pt = new Point2D();
- AttributeStreamOfInt32 sorted_vertices = new AttributeStreamOfInt32(0);
- sorted_vertices.reserve(100);
- int sorted_index = m_shape.createUserIndex();
- // DEBUGPRINTF(L"ee\n");
- for (int ivert = 0, nvert = m_vertices_on_extent.size(); ivert < nvert; ivert++) {
- int vertex = m_vertices_on_extent.get(ivert);
- if (vertex == -1)
- continue;
-
- int next_vertex = m_shape.getNextVertex(vertex);
- m_shape.getXY(vertex, pt);
- // DEBUGPRINTF(L"%f\t%f\n", pt.x, pt.y);
- if (b_axis_x ? pt.y == clip_value : pt.x == clip_value) {
- m_shape.getXY(next_vertex, pt);
- if (b_axis_x ? pt.y == clip_value : pt.x == clip_value) {
- assert (m_shape.getUserIndex(next_vertex,
- m_vertices_on_extent_index) != -1);
- if (m_shape.getUserIndex(vertex, sorted_index) != -2) {
- sorted_vertices.add(vertex);// remember the vertex. The
- // attached segment belongs
- // to the given clip plane.
- m_shape.setUserIndex(vertex, sorted_index, -2);
- }
-
- if (m_shape.getUserIndex(next_vertex, sorted_index) != -2) {
- sorted_vertices.add(next_vertex);
- m_shape.setUserIndex(next_vertex, sorted_index, -2);
- }
- }
- }
- }
-
- if (sorted_vertices.size() == 0) {
- m_shape.removeUserIndex(sorted_index);
- return;
- }
-
- sorted_vertices.Sort(0, sorted_vertices.size(),
- new ClipperVertexComparer(this));
- // std::sort(sorted_vertices.get_ptr(), sorted_vertices.get_ptr() +
- // sorted_vertices.size(), Clipper_vertex_comparer(this));
-
- // DEBUGPRINTF(L"**\n");
- for (int index = 0, n = sorted_vertices.size(); index < n; index++) {
- int vert = sorted_vertices.get(index);
- m_shape.setUserIndex(vert, sorted_index, index);
- // Point_2D pt;
- // m_shape.get_xy(vert, pt);
- // DEBUGPRINTF(L"%f\t%f\t%d\n", pt.x, pt.y, vert);
- }
-
- Point2D pt_tmp = new Point2D();
- Point2D pt_0 = new Point2D();
- pt_0.setNaN();
- int index_0 = -1;
- for (int index = 0, n = sorted_vertices.size(); index < n; index++) {
- int vert = sorted_vertices.get(index);
- if (vert == -1)
- continue;
-
- m_shape.getXY(vert, pt);
- if (!pt.isEqual(pt_0)) {
- if (index_0 != -1) {
- while (true) {
- boolean b_overlap_resolved = false;
- int index_to = index - index_0 > 1 ? index - 1 : index;
- for (int i = index_0; i < index_to; i++) {
- int v = sorted_vertices.get(i);
- if (v == -1)
- continue;
- int nextv = -1;
- int nv = m_shape.getNextVertex(v);
- if (compareVertices_(v, nv) < 0) {
- m_shape.getXY(nv, pt_tmp);
- if (b_axis_x ? pt_tmp.y == clip_value
- : pt_tmp.x == clip_value)
- nextv = nv;
- }
- int prevv = -1;
- int pv = m_shape.getPrevVertex(v);
- if (compareVertices_(v, pv) < 0) {
- m_shape.getXY(pv, pt_tmp);
- if (b_axis_x ? pt_tmp.y == clip_value
- : pt_tmp.x == clip_value)
- prevv = pv;
- }
-
- if (nextv != -1 && prevv != -1) {
- // we have a cusp here. remove the vertex.
- beforeRemoveVertex_(v, sorted_vertices,
- sorted_index);
- m_shape.removeVertex(v, false);
- beforeRemoveVertex_(nextv, sorted_vertices,
- sorted_index);
- m_shape.removeVertex(nextv, false);
- b_overlap_resolved = true;
- continue;
- }
-
- if (nextv == -1 && prevv == -1)
- continue;
-
- for (int j = i + 1; j < index; j++) {
- int v_1 = sorted_vertices.get(j);
- if (v_1 == -1)
- continue;
- int nv1 = m_shape.getNextVertex(v_1);
- int nextv1 = -1;
- if (compareVertices_(v_1, nv1) < 0) {
- m_shape.getXY(nv1, pt_tmp);
- if (b_axis_x ? pt_tmp.y == clip_value
- : pt_tmp.x == clip_value)
- nextv1 = nv1;
- }
-
- int pv1 = m_shape.getPrevVertex(v_1);
- int prevv_1 = -1;
- if (compareVertices_(v_1, pv1) < 0) {
- m_shape.getXY(pv1, pt_tmp);
- if (b_axis_x ? pt_tmp.y == clip_value
- : pt_tmp.x == clip_value)
- prevv_1 = pv1;
- }
- if (nextv1 != -1 && prevv_1 != -1) {
- // we have a cusp here. remove the vertex.
- beforeRemoveVertex_(v_1, sorted_vertices,
- sorted_index);
- m_shape.removeVertex(v_1, false);
- beforeRemoveVertex_(nextv1,
- sorted_vertices, sorted_index);
- m_shape.removeVertex(nextv1, false);
- b_overlap_resolved = true;
- break;
- }
- if (nextv != -1 && prevv_1 != -1) {
- removeOverlap_(sorted_vertices, v, nextv,
- v_1, prevv_1, sorted_index);
- b_overlap_resolved = true;
- break;
- } else if (prevv != -1 && nextv1 != -1) {
- removeOverlap_(sorted_vertices, v_1,
- nextv1, v, prevv, sorted_index);
- b_overlap_resolved = true;
- break;
- }
- }
-
- if (b_overlap_resolved)
- break;
- }
-
- if (!b_overlap_resolved)
- break;
- }
- }
-
- index_0 = index;
- pt_0.setCoords(pt);
- }
- }
-
- m_shape.removeUserIndex(sorted_index);
- }
-
- void beforeRemoveVertex_(int v_1, AttributeStreamOfInt32 sorted_vertices,
- int sorted_index) {
- int ind = m_shape.getUserIndex(v_1, sorted_index);
- sorted_vertices.set(ind, -1);
- ind = m_shape.getUserIndex(v_1, m_vertices_on_extent_index);
- m_vertices_on_extent.set(ind, -1);
- int path = m_shape.getPathFromVertex(v_1);
- if (path != -1) {
- int first = m_shape.getFirstVertex(path);
- if (first == v_1) {
- m_shape.setFirstVertex_(path, -1);
- m_shape.setLastVertex_(path, -1);
- }
- }
- }
-
- void removeOverlap_(AttributeStreamOfInt32 sorted_vertices, int v,
- int nextv, int v_1, int prevv_1, int sorted_index) {
- assert (m_shape.isEqualXY(v, v_1));
- assert (m_shape.isEqualXY(nextv, prevv_1));
- assert (m_shape.getNextVertex(v) == nextv);
- assert (m_shape.getNextVertex(prevv_1) == v_1);
- m_shape.setNextVertex_(v, v_1);
- m_shape.setPrevVertex_(v_1, v);
- m_shape.setPrevVertex_(nextv, prevv_1);
- m_shape.setNextVertex_(prevv_1, nextv);
-
- beforeRemoveVertex_(v_1, sorted_vertices, sorted_index);
- m_shape.removeVertexInternal_(v_1, false);
- beforeRemoveVertex_(prevv_1, sorted_vertices, sorted_index);
- m_shape.removeVertexInternal_(prevv_1, true);
- }
-
- void fixPaths_() {
- for (int ivert = 0, nvert = m_vertices_on_extent.size(); ivert < nvert; ivert++) {
- int vertex = m_vertices_on_extent.get(ivert);
- if (vertex != -1)
- m_shape.setPathToVertex_(vertex, -1);
- }
-
- int path_count = 0;
- int geometry_size = 0;
- for (int path = m_shape.getFirstPath(m_geometry); path != -1; ) {
- int first = m_shape.getFirstVertex(path);
- if (first == -1 || path != m_shape.getPathFromVertex(first)) { // The
- // path's
- // first
- // vertex
- // has
- // been
- // deleted.
- // Or
- // the
- // path
- // first
- // vertex
- // is
- // now
- // part
- // of
- // another
- // path.
- // We
- // have
- // to
- // delete
- // such
- // path
- // object.
- int p = path;
- path = m_shape.getNextPath(path);
- m_shape.setFirstVertex_(p, -1);
- m_shape.removePathOnly_(p);
- continue;
- }
- assert (path == m_shape.getPathFromVertex(first));
- int vertex = first;
- int path_size = 0;
- do {
- m_shape.setPathToVertex_(vertex, path);
- path_size++;
- vertex = m_shape.getNextVertex(vertex);
- } while (vertex != first);
-
- if (path_size <= 2) {
- int ind = m_shape.getUserIndex(first,
- m_vertices_on_extent_index);
- m_vertices_on_extent.set(ind, -1);
- int nv = m_shape.removeVertex(first, false);
- if (path_size == 2) {
- ind = m_shape.getUserIndex(nv, m_vertices_on_extent_index);
- m_vertices_on_extent.set(ind, -1);
- m_shape.removeVertex(nv, false);
- }
- int p = path;
- path = m_shape.getNextPath(path);
- m_shape.setFirstVertex_(p, -1);
- m_shape.removePathOnly_(p);
- continue;
- }
-
- m_shape.setRingAreaValid_(path, false);
- m_shape.setLastVertex_(path, m_shape.getPrevVertex(first));
- m_shape.setPathSize_(path, path_size);
- geometry_size += path_size;
- path_count++;
- path = m_shape.getNextPath(path);
- }
-
- for (int ivert = 0, nvert = m_vertices_on_extent.size(); ivert < nvert; ivert++) {
- int vertex = m_vertices_on_extent.get(ivert);
- if (vertex == -1)
- continue;
- int path = m_shape.getPathFromVertex(vertex);
- if (path != -1)
- continue;
-
- path = m_shape.insertPath(m_geometry, -1);
- int path_size = 0;
- int first = vertex;
- do {
- m_shape.setPathToVertex_(vertex, path);
- path_size++;
- vertex = m_shape.getNextVertex(vertex);
- } while (vertex != first);
-
- if (path_size <= 2) {
- int ind = m_shape.getUserIndex(first,
- m_vertices_on_extent_index);
- m_vertices_on_extent.set(ind, -1);
- int nv = m_shape.removeVertex(first, false);
- if (path_size == 2) {
- ind = m_shape.getUserIndex(nv, m_vertices_on_extent_index);
- if (ind >= 0)
- m_vertices_on_extent.set(ind, -1);
- else {
- // this vertex is not on the extent.
- }
- m_shape.removeVertex(nv, false);
- }
-
- int p = path;
- path = m_shape.getNextPath(path);
- m_shape.setFirstVertex_(p, -1);
- m_shape.removePathOnly_(p);
- continue;
- }
-
- m_shape.setClosedPath(path, true);
- m_shape.setPathSize_(path, path_size);
- m_shape.setFirstVertex_(path, first);
- m_shape.setLastVertex_(path, m_shape.getPrevVertex(first));
- m_shape.setRingAreaValid_(path, false);
- geometry_size += path_size;
- path_count++;
- }
-
- m_shape.setGeometryPathCount_(m_geometry, path_count);
- m_shape.setGeometryVertexCount_(m_geometry, geometry_size);
-
- int total_point_count = 0;
- for (int geometry = m_shape.getFirstGeometry(); geometry != -1; geometry = m_shape
- .getNextGeometry(geometry)) {
- total_point_count += m_shape.getPointCount(geometry);
- }
-
- m_shape.setTotalPointCount_(total_point_count);
- }
-
- static Geometry clipMultiPath_(MultiPath multipath, Envelope2D extent,
- double tolerance, double densify_dist) {
- Clipper clipper = new Clipper(extent);
- return clipper.clipMultiPath2_(multipath, tolerance, densify_dist);
- }
-
- Clipper(Envelope2D extent) {
- m_extent = extent;
- m_shape = new EditShape();
- m_vertices_on_extent = new AttributeStreamOfInt32(0);
- }
-
- // static std::shared_ptr
- * 0 = lower left corner
- *
- * 1 = top-left corner
- *
- * 2 = top right corner
- *
- * 3 = bottom right corner
- * @param ptDst The point whose coordinates are used to set the envelope's
- * coordinate at a specified corner.
- */
- public void queryCornerByVal(int index, Point ptDst) {
- ptDst.assignVertexDescription(m_description);
- int nattrib = getDescription().getAttributeCount() - 1;
- switch (index) {
- case 0: {
- for (int i = 0; i < nattrib; i++) {
- int semantics = m_description.getSemantics(i);
- int ncomp = VertexDescription.getComponentCount(semantics);
- for (int iord = 0; iord < ncomp; iord++)
- ptDst.setAttribute(semantics, iord,
- _getAttributeAsDbl(0, semantics, iord));
- }
- ptDst.setXY(m_envelope.xmin, m_envelope.ymin);
- return;
- }
-
- case 1: {
- for (int i = 0; i < nattrib; i++) {
- int semantics = m_description.getSemantics(i);
- int ncomp = VertexDescription.getComponentCount(semantics);
- for (int iord = 0; iord < ncomp; iord++)
- ptDst.setAttribute(semantics, iord,
- _getAttributeAsDbl(1, semantics, iord));
- }
- ptDst.setXY(m_envelope.xmin, m_envelope.ymax);
- return;
- }
- case 2: {
- for (int i = 0; i < nattrib; i++) {
- int semantics = m_description.getSemantics(i);
- int ncomp = VertexDescription.getComponentCount(semantics);
- for (int iord = 0; iord < ncomp; iord++)
- ptDst.setAttribute(semantics, iord,
- _getAttributeAsDbl(0, semantics, iord));
- }
- ptDst.setXY(m_envelope.xmax, m_envelope.ymax);
-
- return;
- }
- case 3: {
- for (int i = 0; i < nattrib; i++) {
- int semantics = m_description.getSemantics(i);
- int ncomp = VertexDescription.getComponentCount(semantics);
- for (int iord = 0; iord < ncomp; iord++)
- ptDst.setAttribute(semantics, iord,
- _getAttributeAsDbl(1, semantics, iord));
- }
- ptDst.setXY(m_envelope.xmax, m_envelope.ymin);
- return;
- }
- default:
- throw new IndexOutOfBoundsException();
- }
- }
-
- public void queryCorner(int index, Point2D ptDst) {
- Point2D p = m_envelope.queryCorner(index);
- ptDst.setCoords(p.x, p.y);
- }
-
- int getEndPointOffset(VertexDescription descr, int end_point) {
- return end_point * (descr.getTotalComponentCount() - 2);
- }
-
- double getAttributeAsDblImpl_(int end_point, int semantics, int ordinate) {
- if (m_envelope.isEmpty())
- throw new GeometryException("empty geometry");
-
- assert (end_point == 0 || end_point == 1);
-
- if (semantics == VertexDescription.Semantics.POSITION) {
- if (end_point != 0) {
- return ordinate != 0 ? m_envelope.ymax : m_envelope.xmax;
- } else {
- return ordinate != 0 ? m_envelope.ymin : m_envelope.xmin;
- }
- }
-
- int ncomps = VertexDescription.getComponentCount(semantics);
- if (ordinate >= ncomps)
- throw new IllegalArgumentException();
-
- int attribute_index = m_description.getAttributeIndex(semantics);
- _ensureAttributes();
- if (attribute_index >= 0) {
- return m_attributes[getEndPointOffset(m_description, end_point)
- + m_description.getPointAttributeOffset_(attribute_index)
- - 2 + ordinate];
- }
-
- return VertexDescription.getDefaultValue(semantics);
- }
-
- void setAttributeAsDblImpl_(int end_point, int semantics, int ordinate,
- double value) {
- assert (end_point == 0 || end_point == 1);
-
- if (semantics == VertexDescription.Semantics.POSITION) {
- if (end_point != 0) {
- if (ordinate != 0)
- m_envelope.ymax = value;
- else
- m_envelope.xmax = value;
- } else {
- if (ordinate != 0)
- m_envelope.ymin = value;
- else
- m_envelope.xmin = value;
- }
-
- return;
- }
-
- int ncomps = VertexDescription.getComponentCount(semantics);
- if (ordinate >= ncomps)
- throw new IllegalArgumentException();
-
- addAttribute(semantics);
- _ensureAttributes();
- int attribute_index = m_description.getAttributeIndex(semantics);
- m_attributes[getEndPointOffset(m_description, end_point)
- + m_description.getPointAttributeOffset_(attribute_index) - 2
- + ordinate] = value;
- }
-
- void _ensureAttributes() {
- _touch();
- if (m_attributes == null && m_description.getTotalComponentCount() > 2) {
- m_attributes = new double[(m_description.getTotalComponentCount() - 2) * 2];
- int offset0 = _getEndPointOffset(m_description, 0);
- int offset1 = _getEndPointOffset(m_description, 1);
-
- int j = 0;
- for (int i = 1, n = m_description.getAttributeCount(); i < n; i++) {
- int semantics = m_description.getSemantics(i);
- int nords = VertexDescription.getComponentCount(semantics);
- double d = VertexDescription.getDefaultValue(semantics);
- for (int ord = 0; ord < nords; ord++) {
- m_attributes[offset0 + j] = d;
- m_attributes[offset1 + j] = d;
- j++;
- }
- }
- }
- }
-
- @Override
- protected void _assignVertexDescriptionImpl(VertexDescription newDescription) {
- if (m_attributes == null) {
- m_description = newDescription;
- return;
- }
-
- if (newDescription.getTotalComponentCount() > 2) {
- int[] mapping = VertexDescriptionDesignerImpl.mapAttributes(newDescription, m_description);
-
- double[] newAttributes = new double[(newDescription.getTotalComponentCount() - 2) * 2];
-
- int old_offset0 = _getEndPointOffset(m_description, 0);
- int old_offset1 = _getEndPointOffset(m_description, 1);
-
- int new_offset0 = _getEndPointOffset(newDescription, 0);
- int new_offset1 = _getEndPointOffset(newDescription, 1);
-
- int j = 0;
- for (int i = 1, n = newDescription.getAttributeCount(); i < n; i++) {
- int semantics = newDescription.getSemantics(i);
- int nords = VertexDescription.getComponentCount(semantics);
- if (mapping[i] == -1) {
- double d = VertexDescription.getDefaultValue(semantics);
- for (int ord = 0; ord < nords; ord++) {
- newAttributes[new_offset0 + j] = d;
- newAttributes[new_offset1 + j] = d;
- j++;
- }
- } else {
- int m = mapping[i];
- int offset = m_description._getPointAttributeOffset(m) - 2;
- for (int ord = 0; ord < nords; ord++) {
- newAttributes[new_offset0 + j] = m_attributes[old_offset0 + offset];
- newAttributes[new_offset1 + j] = m_attributes[old_offset1 + offset];
- j++;
- offset++;
- }
- }
-
- }
-
- m_attributes = newAttributes;
- } else {
- m_attributes = null;
- }
-
- m_description = newDescription;
- }
-
- double _getAttributeAsDbl(int endPoint, int semantics, int ordinate) {
- if (m_envelope.isEmpty())
- throw new GeometryException(
- "This operation was performed on an Empty Geometry.");
-
- // _ASSERT(endPoint == 0 || endPoint == 1);
-
- if (semantics == Semantics.POSITION) {
- if (endPoint != 0) {
- return ordinate != 0 ? m_envelope.ymax : m_envelope.xmax;
- } else {
- return ordinate != 0 ? m_envelope.ymin : m_envelope.xmin;
- }
- }
-
- int ncomps = VertexDescription.getComponentCount(semantics);
- if (ordinate >= ncomps)
- throw new IndexOutOfBoundsException();
-
- int attributeIndex = m_description.getAttributeIndex(semantics);
- if (attributeIndex >= 0) {
- _ensureAttributes();
- return m_attributes[_getEndPointOffset(m_description, endPoint)
- + m_description._getPointAttributeOffset(attributeIndex)
- - 2 + ordinate];
- } else
- return VertexDescription.getDefaultValue(semantics);
- }
-
- void _setAttributeAsDbl(int endPoint, int semantics, int ordinate,
- double value) {
- _touch();
- // _ASSERT(endPoint == 0 || endPoint == 1);
-
- if (semantics == Semantics.POSITION) {
- if (endPoint != 0) {
- if (ordinate != 0)
- m_envelope.ymax = value;
- else
- m_envelope.xmax = value;
- } else {
- if (ordinate != 0)
- m_envelope.ymin = value;
- else
- m_envelope.xmin = value;
- }
-
- return;
- }
-
- int ncomps = VertexDescription.getComponentCount(semantics);
- if (ordinate >= ncomps)
- throw new IndexOutOfBoundsException();
-
- if (!hasAttribute(semantics)) {
- if (VertexDescription.isDefaultValue(semantics, value))
- return;
-
- addAttribute(semantics);
- }
-
- int attributeIndex = m_description.getAttributeIndex(semantics);
- _ensureAttributes();
- m_attributes[_getEndPointOffset(m_description, endPoint)
- + m_description._getPointAttributeOffset(attributeIndex) - 2
- + ordinate] = value;
- }
-
- int _getAttributeAsInt(int endPoint, int semantics, int ordinate) {
- return (int) _getAttributeAsDbl(endPoint, semantics, ordinate);
- }
-
- static int _getEndPointOffset(VertexDescription vd, int endPoint) {
- return endPoint * (vd.getTotalComponentCount() - 2);
- }
-
- public boolean isIntersecting(Envelope2D other) {
- return m_envelope.isIntersecting(other);
- }
-
- /**
- * Changes this envelope to be the intersection of itself with the other
- * envelope.
- *
- * @param other The envelope to intersect.
- * @return Returns true if the result is not empty.
- */
- public boolean intersect(Envelope other) {
- _touch();
- Envelope2D e2d = new Envelope2D();
- other.queryEnvelope2D(e2d);
- return m_envelope.intersect(e2d);
- }
-
- /**
- * Returns true if the envelope and the other given envelope intersect.
- *
- * @param other The envelope to with which to test intersection.
- * @return Returns true if the two envelopes intersect.
- */
- public boolean isIntersecting(Envelope other) {// TODO: attributes.
- return m_envelope.isIntersecting(other.m_envelope);
- }
-
- /**
- * Sets the envelope's corners to be centered around the specified point,
- * using its center, width, and height.
- *
- * @param c The point around which to center the envelope.
- * @param w The width to be set for the envelope.
- * @param h The height to be set for this envelope.
- */
- public void centerAt(Point c, double w, double h) {
- _touch();
- if (c.isEmpty()) {
- setEmpty();
- return;
- }
-
- _setFromPoint(c, w, h);
- }
-
- /**
- * Offsets the envelope by the specified distances along x and y-coordinates.
- *
- * @param dx The X offset to be applied.
- * @param dy The Y offset to be applied.
- */
- public void offset(double dx, double dy) {
- _touch();
- m_envelope.offset(dx, dy);
- }
-
- /**
- * Normalizes envelopes if the minimum dimension is larger than the
- * maximum dimension.
- */
- public void normalize() {// TODO: attributes
- _touch();
- m_envelope.normalize();
- }
-
- /**
- * Gets the center point of the envelope. The center point occurs at: ((XMin
- * + XMax) / 2, (YMin + YMax) / 2).
- *
- * @return The center point of the envelope.
- */
- public Point2D getCenter2D() {
- return m_envelope.getCenter();
- }
-
- /**
- * Returns the center point of the envelope.
- *
- * @return The center point of the envelope.
- */
- public Point getCenter() {
- Point pointOut = new Point(m_description);
- if (isEmpty()) {
- return pointOut;
- }
- int nattrib = m_description.getAttributeCount();
- for (int i = 1; i < nattrib; i++) {
- int semantics = m_description._getSemanticsImpl(i);
- int ncomp = VertexDescription.getComponentCount(semantics);
- for (int iord = 0; iord < ncomp; iord++) {
- double v = 0.5 * (_getAttributeAsDbl(0, semantics, iord) + _getAttributeAsDbl(
- 1, semantics, iord));
- pointOut.setAttribute(semantics, iord, v);
- }
- }
- pointOut.setXY(m_envelope.getCenterX(), m_envelope.getCenterY());
- return pointOut;
- }
-
- /**
- * Centers the envelope around the specified point preserving the envelope's
- * width and height.
- *
- * @param c The new center point.
- */
- public void centerAt(Point c) {
- _touch();
- if (c.isEmpty()) {
- setEmpty();
- return;
- }
- m_envelope.centerAt(c.getX(), c.getY());
- }
-
- /**
- * Returns the envelope's lower left corner point.
- *
- * @return Returns the lower left corner point.
- */
- public Point getLowerLeft() {
- return new Point(m_envelope.getLowerLeft());
- }
-
- /**
- * Returns the envelope's upper right corner point.
- *
- * @return Returns the upper right corner point.
- */
- public Point getUpperRight() {
- return new Point(m_envelope.getUpperRight());
- }
-
- /**
- * Returns the envelope's lower right corner point.
- *
- * @return Returns the lower right corner point.
- */
- public Point getLowerRight() {
- return new Point(m_envelope.getLowerRight());
- }
-
- /**
- * Returns the envelope's upper left corner point.
- *
- * @return Returns the upper left corner point.
- */
- public Point getUpperLeft() {
- return new Point(m_envelope.getUpperLeft());
- }
-
- /**
- * Checks if this envelope contains (covers) the specified point.
- *
- * @param p The Point to be tested for coverage.
- * @return TRUE if this envelope contains (covers) the specified point.
- */
- public boolean contains(Point p) {
- if (p.isEmpty())
- return false;
- return m_envelope.contains(p.getX(), p.getY());
- }
-
- /**
- * Checks if this envelope contains (covers) other envelope.
- *
- * @param env The envelope to be tested for coverage.
- * @return TRUE if this envelope contains (covers) the specified envelope.
- */
- public boolean contains(Envelope env) {
- return m_envelope.contains(env.m_envelope);
- }
-
- /**
- * Returns TRUE when this geometry has exactly same type, properties, and
- * coordinates as the other geometry.
- */
- @Override
- public boolean equals(Object _other) {
- if (_other == this)
- return true;
-
- if (!(_other instanceof Envelope))
- return false;
-
- Envelope other = (Envelope) _other;
-
- if (m_description != other.m_description)
- return false;
-
- if (isEmpty())
- if (other.isEmpty())
- return true;
- else
- return false;
-
- if (!this.m_envelope.equals(other.m_envelope))
- return false;
-
- for (int i = 0, n = (m_description.getTotalComponentCount() - 2) * 2; i < n; i++)
- if (m_attributes[i] != other.m_attributes[i])
- return false;
-
- return true;
- }
-
- /**
- * Returns a hash code value for this envelope.
- *
- * @return A hash code value for this envelope.
- */
- @Override
- public int hashCode() {
- int hashCode = m_description.hashCode();
- hashCode = NumberUtils.hash(hashCode, m_envelope.hashCode());
- if (!isEmpty() && m_attributes != null) {
- for (int i = 0, n = (m_description.getTotalComponentCount() - 2) * 2; i < n; i++) {
- hashCode = NumberUtils.hash(hashCode, m_attributes[i]);
- }
- }
- return hashCode;
- }
-
- /**
- * Returns the X coordinate of the left corners of the envelope.
- *
- * @return The X coordinate of the left corners.
- */
- public final double getXMin() {
- return m_envelope.xmin;
- }
-
- /**
- * Returns the Y coordinate of the bottom corners of the envelope.
- *
- * @return The Y coordinate of the bottom corners.
- */
- public final double getYMin() {
- return m_envelope.ymin;
- }
-
- /**
- * Returns the X coordinate of the right corners of the envelope.
- *
- * @return The X coordinate of the right corners.
- */
- public final double getXMax() {
- return m_envelope.xmax;
- }
-
- /**
- * Returns the Y coordinate of the top corners of the envelope.
- *
- * @return The Y coordinate of the top corners.
- */
- public final double getYMax() {
- return m_envelope.ymax;
- }
-
- /**
- * Sets the left X coordinate.
- *
- * @param x The X coordinate of the left corner
- */
- public void setXMin(double x) {
- _touch();
- m_envelope.xmin = x;
- }
-
- /**
- * Sets the right X coordinate.
- *
- * @param x The X coordinate of the right corner.
- */
- public void setXMax(double x) {
- _touch();
- m_envelope.xmax = x;
- }
-
- /**
- * Sets the bottom Y coordinate.
- *
- * @param y the Y coordinate of the bottom corner.
- */
- public void setYMin(double y) {
- _touch();
- m_envelope.ymin = y;
- }
-
- /**
- * Sets the top Y coordinate.
- *
- * @param y The Y coordinate of the top corner.
- */
- public void setYMax(double y) {
- _touch();
- m_envelope.ymax = y;
- }
-
- @Override
- public Geometry getBoundary() {
- return Boundary.calculate(this, null);
- }
-
- @Override
- public void replaceNaNs(int semantics, double value) {
- addAttribute(semantics);
- if (isEmpty())
- return;
-
- int ncomps = VertexDescription.getComponentCount(semantics);
- for (int i = 0; i < ncomps; i++) {
- Envelope1D interval = queryInterval(semantics, i);
- if (interval.isEmpty()) {
- interval.vmin = value;
- interval.vmax = value;
- setInterval(semantics, i, interval);
- }
- }
- }
-
- /**
- * The output of this method can be only used for debugging. It is subject to change without notice.
- */
- @Override
- public String toString() {
- if (isEmpty())
- return "Envelope: []";
-
- String s = "Envelope: [" + m_envelope.xmin + ", " + m_envelope.ymin + ", " + m_envelope.xmax + ", " + m_envelope.ymax + "]";
- return s;
- }
+ @Override
+ public void queryEnvelope2D(Envelope2D env) {
+ env.xmin = m_envelope.xmin;
+ env.ymin = m_envelope.ymin;
+ env.xmax = m_envelope.xmax;
+ env.ymax = m_envelope.ymax;
+ }
+ @Override
+ void queryEnvelope3D(Envelope3D env) {
+ env.xmin = m_envelope.xmin;
+ env.ymin = m_envelope.ymin;
+ env.xmax = m_envelope.xmax;
+ env.ymax = m_envelope.ymax;
+ env.setCoords(m_envelope.xmin, m_envelope.ymin,
+ _getAttributeAsDbl(0, Semantics.Z, 0), m_envelope.xmax,
+ m_envelope.ymax, _getAttributeAsDbl(1, Semantics.Z, 0));
+ }
+
+ @Override
+ public Envelope1D queryInterval(int semantics, int ordinate) {
+ Envelope1D env = new Envelope1D();
+ env.setCoords(_getAttributeAsDbl(0, semantics, ordinate),
+ _getAttributeAsDbl(1, semantics, ordinate));
+ return env;
+ }
+
+ public void setInterval(int semantics, int ordinate, Envelope1D env) {
+ _touch();
+ if (semantics == Semantics.POSITION) {
+ if (ordinate == 0) {
+ m_envelope.xmin = env.vmin;
+ m_envelope.xmax = env.vmax;
+ } else if (ordinate == 1) {
+ m_envelope.ymin = env.vmin;
+ m_envelope.ymax = env.vmax;
+ } else
+ throw new IndexOutOfBoundsException();
+ } else {
+ _setAttributeAsDbl(0, semantics, ordinate, env.vmin);
+ _setAttributeAsDbl(1, semantics, ordinate, env.vmax);
+ }
+ }
+
+ public void queryCoordinates(Point2D[] dst) {
+ if (dst == null || dst.length < 4 || m_envelope.isEmpty())
+ throw new IllegalArgumentException();
+
+ m_envelope.queryCorners(dst);
+ }
+
+ /**
+ * Sets the point's coordinates to the coordinates of the envelope at the
+ * given corner.
+ *
+ * @param index
+ * The index of the envelope's corners from 0 to 3.
+ *
+ * 0 = lower left corner
+ *
+ * 1 = top-left corner
+ *
+ * 2 = top right corner
+ *
+ * 3 = bottom right corner
+ * @param ptDst
+ * The point whose coordinates are used to set the envelope's
+ * coordinate at a specified corner.
+ */
+ public void queryCornerByVal(int index, Point ptDst) {
+ ptDst.assignVertexDescription(m_description);
+ int nattrib = getDescription().getAttributeCount() - 1;
+ switch (index) {
+ case 0: {
+ for (int i = 0; i < nattrib; i++) {
+ int semantics = m_description.getSemantics(i);
+ int ncomp = VertexDescription.getComponentCount(semantics);
+ for (int iord = 0; iord < ncomp; iord++)
+ ptDst.setAttribute(semantics, iord,
+ _getAttributeAsDbl(0, semantics, iord));
+ }
+ ptDst.setXY(m_envelope.xmin, m_envelope.ymin);
+ return;
+ }
+
+ case 1: {
+ for (int i = 0; i < nattrib; i++) {
+ int semantics = m_description.getSemantics(i);
+ int ncomp = VertexDescription.getComponentCount(semantics);
+ for (int iord = 0; iord < ncomp; iord++)
+ ptDst.setAttribute(semantics, iord,
+ _getAttributeAsDbl(1, semantics, iord));
+ }
+ ptDst.setXY(m_envelope.xmin, m_envelope.ymax);
+ return;
+ }
+ case 2: {
+ for (int i = 0; i < nattrib; i++) {
+ int semantics = m_description.getSemantics(i);
+ int ncomp = VertexDescription.getComponentCount(semantics);
+ for (int iord = 0; iord < ncomp; iord++)
+ ptDst.setAttribute(semantics, iord,
+ _getAttributeAsDbl(0, semantics, iord));
+ }
+ ptDst.setXY(m_envelope.xmax, m_envelope.ymax);
+
+ return;
+ }
+ case 3: {
+ for (int i = 0; i < nattrib; i++) {
+ int semantics = m_description.getSemantics(i);
+ int ncomp = VertexDescription.getComponentCount(semantics);
+ for (int iord = 0; iord < ncomp; iord++)
+ ptDst.setAttribute(semantics, iord,
+ _getAttributeAsDbl(1, semantics, iord));
+ }
+ ptDst.setXY(m_envelope.xmax, m_envelope.ymin);
+ return;
+ }
+ default:
+ throw new IndexOutOfBoundsException();
+ }
+ }
+
+ public void queryCorner(int index, Point2D ptDst) {
+ Point2D p = m_envelope.queryCorner(index);
+ ptDst.setCoords(p.x, p.y);
+ }
+
+ int getEndPointOffset(VertexDescription descr, int end_point) {
+ return end_point * (descr.getTotalComponentCount() - 2);
+ }
+
+ double getAttributeAsDblImpl_(int end_point, int semantics, int ordinate) {
+ if (m_envelope.isEmpty())
+ throw new GeometryException("empty geometry");
+
+ assert (end_point == 0 || end_point == 1);
+
+ if (semantics == VertexDescription.Semantics.POSITION) {
+ if (end_point != 0) {
+ return ordinate != 0 ? m_envelope.ymax : m_envelope.xmax;
+ } else {
+ return ordinate != 0 ? m_envelope.ymin : m_envelope.xmin;
+ }
+ }
+
+ int ncomps = VertexDescription.getComponentCount(semantics);
+ if (ordinate >= ncomps)
+ throw new IllegalArgumentException();
+
+ int attribute_index = m_description.getAttributeIndex(semantics);
+ if (attribute_index >= 0) {
+ return m_attributes[getEndPointOffset(m_description, end_point)
+ + m_description.getPointAttributeOffset_(attribute_index)
+ - 2 + ordinate];
+ }
+
+ return VertexDescription.getDefaultValue(semantics);
+ }
+
+ void setAttributeAsDblImpl_(int end_point, int semantics, int ordinate,
+ double value) {
+ assert (end_point == 0 || end_point == 1);
+
+ if (semantics == VertexDescription.Semantics.POSITION) {
+ if (end_point != 0) {
+ if (ordinate != 0)
+ m_envelope.ymax = value;
+ else
+ m_envelope.xmax = value;
+ } else {
+ if (ordinate != 0)
+ m_envelope.ymin = value;
+ else
+ m_envelope.xmin = value;
+ }
+
+ return;
+ }
+
+ int ncomps = VertexDescription.getComponentCount(semantics);
+ if (ordinate >= ncomps)
+ throw new IllegalArgumentException();
+
+ addAttribute(semantics);
+ int attribute_index = m_description.getAttributeIndex(semantics);
+ m_attributes[getEndPointOffset(m_description, end_point)
+ + m_description.getPointAttributeOffset_(attribute_index) - 2
+ + ordinate] = value;
+ }
+
+ void _ensureAttributes() {
+ _touch();
+ if (m_attributes == null && m_description.getTotalComponentCount() > 2) {
+ int halfLength = m_description.getTotalComponentCount() - 2;
+ m_attributes = new double[halfLength * 2];
+ int offset0 = _getEndPointOffset(m_description, 0);
+ int offset1 = _getEndPointOffset(m_description, 1);
+ System.arraycopy(m_description._getDefaultPointAttributes(), 2, m_attributes, offset0, halfLength);
+ System.arraycopy(m_description._getDefaultPointAttributes(), 2, m_attributes, offset1, halfLength);
+ }
+ }
+
+ @Override
+ protected void _assignVertexDescriptionImpl(VertexDescription newDescription) {
+ if (newDescription.getTotalComponentCount() > 2) {
+ int[] mapping = VertexDescriptionDesignerImpl.mapAttributes(newDescription, m_description);
+
+ double[] newAttributes = new double[(newDescription.getTotalComponentCount() - 2) * 2];
+
+ int old_offset0 = _getEndPointOffset(m_description, 0);
+ int old_offset1 = _getEndPointOffset(m_description, 1);
+
+ int new_offset0 = _getEndPointOffset(newDescription, 0);
+ int new_offset1 = _getEndPointOffset(newDescription, 1);
+
+ int j = 0;
+ for (int i = 1, n = newDescription.getAttributeCount(); i < n; i++) {
+ int semantics = newDescription.getSemantics(i);
+ int nords = VertexDescription.getComponentCount(semantics);
+ if (mapping[i] == -1)
+ {
+ double d = VertexDescription.getDefaultValue(semantics);
+ for (int ord = 0; ord < nords; ord++)
+ {
+ newAttributes[new_offset0 + j] = d;
+ newAttributes[new_offset1 + j] = d;
+ j++;
+ }
+ }
+ else {
+ int m = mapping[i];
+ int offset = m_description._getPointAttributeOffset(m) - 2;
+ for (int ord = 0; ord < nords; ord++)
+ {
+ newAttributes[new_offset0 + j] = m_attributes[old_offset0 + offset];
+ newAttributes[new_offset1 + j] = m_attributes[old_offset1 + offset];
+ j++;
+ offset++;
+ }
+ }
+
+ }
+
+ m_attributes = newAttributes;
+ }
+ else {
+ m_attributes = null;
+ }
+
+ m_description = newDescription;
+ }
+
+ double _getAttributeAsDbl(int endPoint, int semantics, int ordinate) {
+ if (m_envelope.isEmpty())
+ throw new GeometryException(
+ "This operation was performed on an Empty Geometry.");
+
+ if (semantics == Semantics.POSITION) {
+ if (endPoint != 0) {
+ return ordinate != 0 ? m_envelope.ymax : m_envelope.xmax;
+ } else {
+ return ordinate != 0 ? m_envelope.ymin : m_envelope.xmin;
+ }
+ }
+
+ int ncomps = VertexDescription.getComponentCount(semantics);
+ if (ordinate >= ncomps)
+ throw new IndexOutOfBoundsException();
+
+ int attributeIndex = m_description.getAttributeIndex(semantics);
+ if (attributeIndex >= 0) {
+ return m_attributes[_getEndPointOffset(m_description, endPoint)
+ + m_description._getPointAttributeOffset(attributeIndex)
+ - 2 + ordinate];
+ } else
+ return VertexDescription.getDefaultValue(semantics);
+ }
+
+ void _setAttributeAsDbl(int endPoint, int semantics, int ordinate,
+ double value) {
+ _touch();
+ // _ASSERT(endPoint == 0 || endPoint == 1);
+
+ if (semantics == Semantics.POSITION) {
+ if (endPoint != 0) {
+ if (ordinate != 0)
+ m_envelope.ymax = value;
+ else
+ m_envelope.xmax = value;
+ } else {
+ if (ordinate != 0)
+ m_envelope.ymin = value;
+ else
+ m_envelope.xmin = value;
+ }
+
+ return;
+ }
+
+ int ncomps = VertexDescription.getComponentCount(semantics);
+ if (ordinate >= ncomps)
+ throw new IndexOutOfBoundsException();
+
+ if (!hasAttribute(semantics)) {
+ addAttribute(semantics);
+ }
+
+ int attributeIndex = m_description.getAttributeIndex(semantics);
+ m_attributes[_getEndPointOffset(m_description, endPoint)
+ + m_description._getPointAttributeOffset(attributeIndex) - 2
+ + ordinate] = value;
+ }
+
+ int _getAttributeAsInt(int endPoint, int semantics, int ordinate) {
+ return (int) _getAttributeAsDbl(endPoint, semantics, ordinate);
+ }
+
+ static int _getEndPointOffset(VertexDescription vd, int endPoint) {
+ return endPoint * (vd.getTotalComponentCount() - 2);
+ }
+
+ public boolean isIntersecting(Envelope2D other) {
+ return m_envelope.isIntersecting(other);
+ }
+
+ /**
+ * Changes this envelope to be the intersection of itself with the other
+ * envelope.
+ *
+ * @param other
+ * The envelope to intersect.
+ * @return Returns true if the result is not empty.
+ */
+ public boolean intersect(Envelope other) {
+ _touch();
+ Envelope2D e2d = new Envelope2D();
+ other.queryEnvelope2D(e2d);
+ return m_envelope.intersect(e2d);
+ }
+
+ /**
+ * Returns true if the envelope and the other given envelope intersect.
+ *
+ * @param other
+ * The envelope to with which to test intersection.
+ * @return Returns true if the two envelopes intersect.
+ */
+ public boolean isIntersecting(Envelope other) {// TODO: attributes.
+ return m_envelope.isIntersecting(other.m_envelope);
+ }
+
+ /**
+ * Sets the envelope's corners to be centered around the specified point,
+ * using its center, width, and height.
+ *
+ * @param c
+ * The point around which to center the envelope.
+ * @param w
+ * The width to be set for the envelope.
+ * @param h
+ * The height to be set for this envelope.
+ */
+ public void centerAt(Point c, double w, double h) {
+ _touch();
+ if (c.isEmpty()) {
+ setEmpty();
+ return;
+ }
+
+ _setFromPoint(c, w, h);
+ }
+
+ /**
+ * Offsets the envelope by the specified distances along x and y-coordinates.
+ *
+ * @param dx
+ * The X offset to be applied.
+ * @param dy
+ * The Y offset to be applied.
+ */
+ public void offset(double dx, double dy) {
+ _touch();
+ m_envelope.offset(dx, dy);
+ }
+
+ /**
+ * Normalizes envelopes if the minimum dimension is larger than the
+ * maximum dimension.
+ */
+ public void normalize() {// TODO: attributes
+ _touch();
+ m_envelope.normalize();
+ }
+
+ /**
+ * Gets the center point of the envelope. The center point occurs at: ((XMin
+ * + XMax) / 2, (YMin + YMax) / 2).
+ *
+ * @return The center point of the envelope.
+ */
+ public Point2D getCenter2D() {
+ return m_envelope.getCenter();
+ }
+
+ /**
+ * Returns the center point of the envelope.
+ *
+ * @return The center point of the envelope.
+ */
+ public Point getCenter() {
+ Point pointOut = new Point(m_description);
+ if (isEmpty()) {
+ return pointOut;
+ }
+ int nattrib = m_description.getAttributeCount();
+ for (int i = 1; i < nattrib; i++) {
+ int semantics = m_description._getSemanticsImpl(i);
+ int ncomp = VertexDescription.getComponentCount(semantics);
+ for (int iord = 0; iord < ncomp; iord++) {
+ double v = 0.5 * (_getAttributeAsDbl(0, semantics, iord) + _getAttributeAsDbl(
+ 1, semantics, iord));
+ pointOut.setAttribute(semantics, iord, v);
+ }
+ }
+ pointOut.setXY(m_envelope.getCenterX(), m_envelope.getCenterY());
+ return pointOut;
+ }
+
+ /**
+ * Centers the envelope around the specified point preserving the envelope's
+ * width and height.
+ *
+ * @param c
+ * The new center point.
+ */
+ public void centerAt(Point c) {
+ _touch();
+ if (c.isEmpty()) {
+ setEmpty();
+ return;
+ }
+ m_envelope.centerAt(c.getX(), c.getY());
+ }
+
+ /**
+ * Returns the envelope's lower left corner point.
+ *
+ * @return Returns the lower left corner point.
+ */
+ public Point getLowerLeft() {
+ return new Point(m_envelope.getLowerLeft());
+ }
+
+ /**
+ * Returns the envelope's upper right corner point.
+ *
+ * @return Returns the upper right corner point.
+ */
+ public Point getUpperRight() {
+ return new Point(m_envelope.getUpperRight());
+ }
+
+ /**
+ * Returns the envelope's lower right corner point.
+ *
+ * @return Returns the lower right corner point.
+ */
+ public Point getLowerRight() {
+ return new Point(m_envelope.getLowerRight());
+ }
+
+ /**
+ * Returns the envelope's upper left corner point.
+ *
+ * @return Returns the upper left corner point.
+ */
+ public Point getUpperLeft() {
+ return new Point(m_envelope.getUpperLeft());
+ }
+
+ /**
+ * Checks if this envelope contains (covers) the specified point.
+ *
+ * @param p
+ * The Point to be tested for coverage.
+ * @return TRUE if this envelope contains (covers) the specified point.
+ */
+ public boolean contains(Point p) {
+ if (p.isEmpty())
+ return false;
+ return m_envelope.contains(p.getX(), p.getY());
+ }
+
+ /**
+ * Checks if this envelope contains (covers) other envelope.
+ *
+ * @param env
+ * The envelope to be tested for coverage.
+ * @return TRUE if this envelope contains (covers) the specified envelope.
+ */
+ public boolean contains(Envelope env) {
+ return m_envelope.contains(env.m_envelope);
+ }
+
+ /**
+ * Returns TRUE when this geometry has exactly same type, properties, and
+ * coordinates as the other geometry.
+ */
+ @Override
+ public boolean equals(Object _other) {
+ if (_other == this)
+ return true;
+
+ if (!(_other instanceof Envelope))
+ return false;
+
+ Envelope other = (Envelope) _other;
+
+ if (m_description != other.m_description)
+ return false;
+
+ if (isEmpty())
+ if (other.isEmpty())
+ return true;
+ else
+ return false;
+
+ if (!this.m_envelope.equals(other.m_envelope))
+ return false;
+
+ for (int i = 0, n = (m_description.getTotalComponentCount() - 2) * 2; i < n; i++)
+ if (!NumberUtils.isEqualNonIEEE(m_attributes[i], other.m_attributes[i]))
+ return false;
+
+ return true;
+ }
+
+ /**
+ * Returns a hash code value for this envelope.
+ *
+ * @return A hash code value for this envelope.
+ */
+ @Override
+ public int hashCode() {
+ int hashCode = m_description.hashCode();
+ hashCode = NumberUtils.hash(hashCode, m_envelope.hashCode());
+ if (!isEmpty()) {
+ for (int i = 0, n = (m_description.getTotalComponentCount() - 2) * 2; i < n; i++) {
+ hashCode = NumberUtils.hash(hashCode, m_attributes[i]);
+ }
+ }
+ return hashCode;
+ }
+
+ /**
+ * Returns the X coordinate of the left corners of the envelope.
+ *
+ * @return The X coordinate of the left corners.
+ */
+ public final double getXMin() {
+ return m_envelope.xmin;
+ }
+
+ /**
+ * Returns the Y coordinate of the bottom corners of the envelope.
+ *
+ * @return The Y coordinate of the bottom corners.
+ */
+ public final double getYMin() {
+ return m_envelope.ymin;
+ }
+
+ /**
+ * Returns the X coordinate of the right corners of the envelope.
+ *
+ * @return The X coordinate of the right corners.
+ */
+ public final double getXMax() {
+ return m_envelope.xmax;
+ }
+
+ /**
+ * Returns the Y coordinate of the top corners of the envelope.
+ *
+ * @return The Y coordinate of the top corners.
+ */
+ public final double getYMax() {
+ return m_envelope.ymax;
+ }
+
+ /**
+ * Sets the left X coordinate.
+ *
+ * @param x
+ * The X coordinate of the left corner
+ */
+ public void setXMin(double x) {
+ _touch();
+ m_envelope.xmin = x;
+ }
+
+ /**
+ * Sets the right X coordinate.
+ *
+ * @param x
+ * The X coordinate of the right corner.
+ */
+ public void setXMax(double x) {
+ _touch();
+ m_envelope.xmax = x;
+ }
+
+ /**
+ * Sets the bottom Y coordinate.
+ *
+ * @param y
+ * the Y coordinate of the bottom corner.
+ */
+ public void setYMin(double y) {
+ _touch();
+ m_envelope.ymin = y;
+ }
+
+ /**
+ * Sets the top Y coordinate.
+ *
+ * @param y
+ * The Y coordinate of the top corner.
+ */
+ public void setYMax(double y) {
+ _touch();
+ m_envelope.ymax = y;
+ }
+
+ @Override
+ public Geometry getBoundary() {
+ return Boundary.calculate(this, null);
+ }
+
+ @Override
+ public void replaceNaNs(int semantics, double value) {
+ addAttribute(semantics);
+ if (isEmpty())
+ return;
+
+ int ncomps = VertexDescription.getComponentCount(semantics);
+ for (int i = 0; i < ncomps; i++) {
+ Envelope1D interval = queryInterval(semantics, i);
+ if (interval.isEmpty()) {
+ interval.vmin = value;
+ interval.vmax = value;
+ setInterval(semantics, i, interval);
+ }
+ }
+ }
+
+ /**
+ * The output of this method can be only used for debugging. It is subject to change without notice.
+ */
+ @Override
+ public String toString() {
+ if (isEmpty())
+ return "Envelope: []";
+
+ String s = "Envelope: [" + m_envelope.xmin + ", " + m_envelope.ymin + ", " + m_envelope.xmax + ", " + m_envelope.ymax +"]";
+ return s;
+ }
+
}
diff --git a/src/main/java/com/esri/core/geometry/Envelope1D.java b/src/main/java/com/esri/core/geometry/Envelope1D.java
index f81bada7..e000ef0a 100644
--- a/src/main/java/com/esri/core/geometry/Envelope1D.java
+++ b/src/main/java/com/esri/core/geometry/Envelope1D.java
@@ -31,194 +31,207 @@
* A 1-dimensional interval.
*/
public final class Envelope1D implements Serializable {
- private static final long serialVersionUID = 1L;
-
- public double vmin;
-
- public double vmax;
-
- public Envelope1D() {
-
- }
-
- public Envelope1D(double _vmin, double _vmax) {
- setCoords(_vmin, _vmax);
- }
-
- public Envelope1D(Envelope1D other) {
- setCoords(other);
- }
-
- public void setCoords(double _vmin, double _vmax) {
- vmin = _vmin;
- vmax = _vmax;
- normalize();
- }
-
- public void setCoords(Envelope1D other) {
- setCoords(other.vmin, other.vmax);
- }
-
- public void normalize() {
- if (NumberUtils.isNaN(vmin))
- return;
- if (vmin > vmax) {
- double v = vmin;
- vmin = vmax;
- vmax = v;
- }
- if (NumberUtils.isNaN(vmax))// vmax can be NAN
- {
- setEmpty();
- }
- }
-
- public void setEmpty() {
- vmin = NumberUtils.NaN();
- vmax = NumberUtils.NaN();
- }
-
- public boolean isEmpty() {
- return NumberUtils.isNaN(vmin) || NumberUtils.isNaN(vmax);
- }
-
- public void setInfinite() {
- vmin = NumberUtils.negativeInf();
- vmax = NumberUtils.positiveInf();
- }
-
- public void merge(double v) {
- if (isEmpty()) {
- vmin = v;
- vmax = v;
- return;
- }
-
- // no need to check for NaN, because all comparisons with NaN are false.
- mergeNE(v);
- }
-
- public void merge(Envelope1D other) {
- if (other.isEmpty())
- return;
-
- if (isEmpty()) {
- vmin = other.vmin;
- vmax = other.vmax;
- return;
- }
-
- if (vmin > other.vmin)
- vmin = other.vmin;
- if (vmax < other.vmax)
- vmax = other.vmax;
-
- if (vmin > vmax)
- setEmpty();
- }
-
- public void mergeNE(double v) {
- // Note, if v is NaN, vmin and vmax are unchanged
- if (v < vmin)
- vmin = v;
- else if (v > vmax)
- vmax = v;
- }
-
- public boolean contains(double v) {
- // If vmin is NaN, return false. No need to check for isEmpty.
- return v >= vmin && v <= vmax;
- }
-
- /**
- * Returns True if the envelope contains the other envelope (boundary
- * inclusive). Note: Will return false if either envelope is empty.
- */
- public boolean contains(/* const */Envelope1D other) /* const */ {
- return other.vmin >= vmin && other.vmax <= vmax;
- }
-
- public void intersect(Envelope1D other) {
- if (isEmpty() || other.isEmpty()) {
- setEmpty();
- return;
- }
-
- if (vmin < other.vmin)
- vmin = other.vmin;
- if (vmax > other.vmax)
- vmax = other.vmax;
-
- if (vmin > vmax)
- setEmpty();
- }
-
- public void inflate(double delta) {
- if (isEmpty())
- return;
-
- vmin -= delta;
- vmax += delta;
- if (vmax < vmin)
- setEmpty();
- }
-
- double _calculateToleranceFromEnvelope() {
- if (isEmpty())
- return NumberUtils.doubleEps() * 100.0; // GEOMTERYX_EPSFACTOR
- // 100.0;
- double r = Math.abs(vmin) + Math.abs(vmax) + 1;
- return r * NumberUtils.doubleEps() * 100.0; // GEOMTERYX_EPSFACTOR
- // 100.0;
- }
-
- void normalizeNoNaN_() {
- if (vmin > vmax) {
- double v = vmin;
- vmin = vmax;
- vmax = v;
- }
- }
-
- void setCoordsNoNaN_(double vmin_, double vmax_) {
- vmin = vmin_;
- vmax = vmax_;
- normalizeNoNaN_();
- }
-
- public double snapClip(double v) /* const */ {
- return NumberUtils.snap(v, vmin, vmax);
- }
-
- public double getWidth() /* const */ {
- return vmax - vmin;
- }
-
- public double getCenter() /* const */ {
- return 0.5 * (vmin + vmax);
- }
-
- @Override
- public boolean equals(Object _other) {
- if (_other == this)
- return true;
-
- if (!(_other instanceof Envelope1D))
- return false;
-
- Envelope1D other = (Envelope1D) _other;
- if (isEmpty() && other.isEmpty())
- return true;
-
- if (vmin != other.vmin || vmax != other.vmax)
- return false;
-
- return true;
- }
-
- @Override
- public int hashCode() {
- return NumberUtils.hash(NumberUtils.hash(vmin), vmax);
- }
-
+ private static final long serialVersionUID = 1L;
+
+ public double vmin;
+
+ public double vmax;
+
+ public Envelope1D() {
+
+ }
+
+ public Envelope1D(double _vmin, double _vmax) {
+ setCoords(_vmin, _vmax);
+ }
+
+ public Envelope1D(Envelope1D other) {
+ setCoords(other);
+ }
+
+ public void setCoords(double _vmin, double _vmax) {
+ vmin = _vmin;
+ vmax = _vmax;
+ normalize();
+ }
+
+ public void setCoords(Envelope1D other) {
+ setCoords(other.vmin, other.vmax);
+ }
+
+ public void normalize() {
+ if (NumberUtils.isNaN(vmin))
+ return;
+ if (vmin > vmax) {
+ double v = vmin;
+ vmin = vmax;
+ vmax = v;
+ }
+ if (NumberUtils.isNaN(vmax))// vmax can be NAN
+ {
+ setEmpty();
+ }
+ }
+
+ public void setEmpty() {
+ vmin = NumberUtils.NaN();
+ vmax = NumberUtils.NaN();
+ }
+
+ public boolean isEmpty() {
+ return NumberUtils.isNaN(vmin) || NumberUtils.isNaN(vmax);
+ }
+
+ public void setInfinite() {
+ vmin = NumberUtils.negativeInf();
+ vmax = NumberUtils.positiveInf();
+ }
+
+ public void merge(double v) {
+ if (isEmpty()) {
+ vmin = v;
+ vmax = v;
+ return;
+ }
+
+ // no need to check for NaN, because all comparisons with NaN are false.
+ mergeNE(v);
+ }
+
+ public void merge(Envelope1D other) {
+ if (other.isEmpty())
+ return;
+
+ if (isEmpty()) {
+ vmin = other.vmin;
+ vmax = other.vmax;
+ return;
+ }
+
+ if (vmin > other.vmin)
+ vmin = other.vmin;
+ if (vmax < other.vmax)
+ vmax = other.vmax;
+
+ if (vmin > vmax)
+ setEmpty();
+ }
+
+ public void mergeNE(double v) {
+ // Note, if v is NaN, vmin and vmax are unchanged
+ if (v < vmin)
+ vmin = v;
+ else if (v > vmax)
+ vmax = v;
+ }
+
+ public boolean contains(double v) {
+ // If vmin is NaN, return false. No need to check for isEmpty.
+ return v >= vmin && v <= vmax;
+ }
+
+ /**
+ * Returns True if the envelope contains the other envelope (boundary
+ * inclusive). Note: Will return false if either envelope is empty.
+ * @param other The other envelope.
+ * @return Return true if this contains the other.
+ */
+ public boolean contains(Envelope1D other)
+ {
+ return other.vmin >= vmin && other.vmax <= vmax;
+ }
+
+ public void intersect(Envelope1D other) {
+ if (isEmpty() || other.isEmpty()) {
+ setEmpty();
+ return;
+ }
+
+ if (vmin < other.vmin)
+ vmin = other.vmin;
+ if (vmax > other.vmax)
+ vmax = other.vmax;
+
+ if (vmin > vmax)
+ setEmpty();
+ }
+
+ public void inflate(double delta) {
+ if (isEmpty())
+ return;
+
+ vmin -= delta;
+ vmax += delta;
+ if (vmax < vmin)
+ setEmpty();
+ }
+
+ double _calculateToleranceFromEnvelope() {
+ if (isEmpty())
+ return NumberUtils.doubleEps() * 100.0; // GEOMTERYX_EPSFACTOR
+ // 100.0;
+ double r = Math.abs(vmin) + Math.abs(vmax) + 1;
+ return r * NumberUtils.doubleEps() * 100.0; // GEOMTERYX_EPSFACTOR
+ // 100.0;
+ }
+
+ void normalizeNoNaN_() {
+ if (vmin > vmax) {
+ double v = vmin;
+ vmin = vmax;
+ vmax = v;
+ }
+ }
+
+ void setCoordsNoNaN_(double vmin_, double vmax_) {
+ vmin = vmin_;
+ vmax = vmax_;
+ normalizeNoNaN_();
+ }
+
+ public double snapClip(double v) /* const */
+ {
+ return NumberUtils.snap(v, vmin, vmax);
+ }
+
+ public double getWidth() /* const */
+ {
+ return vmax - vmin;
+ }
+
+ public double getCenter() /* const */
+ {
+ return 0.5 * (vmin + vmax);
+ }
+
+ @Override
+ public boolean equals(Object _other)
+ {
+ if (_other == this)
+ return true;
+
+ if (!(_other instanceof Envelope1D))
+ return false;
+
+ Envelope1D other = (Envelope1D) _other;
+ if (isEmpty() && other.isEmpty())
+ return true;
+
+ if (vmin != other.vmin || vmax != other.vmax)
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ if (isEmpty()) {
+ return NumberUtils.hash(NumberUtils.TheNaN);
+ }
+
+ int hash = NumberUtils.hash(vmin);
+ hash = NumberUtils.hash(hash, vmax);
+ return hash;
+ }
+
}
diff --git a/src/main/java/com/esri/core/geometry/Envelope2D.java b/src/main/java/com/esri/core/geometry/Envelope2D.java
index 1d6172f5..5c8bebf5 100644
--- a/src/main/java/com/esri/core/geometry/Envelope2D.java
+++ b/src/main/java/com/esri/core/geometry/Envelope2D.java
@@ -34,49 +34,49 @@
* An axis parallel 2-dimensional rectangle.
*/
public final class Envelope2D implements Serializable {
- private static final long serialVersionUID = 1L;
-
- private final static int XLESSXMIN = 1;
- // private final int XGREATERXMAX = 2;
- private final static int YLESSYMIN = 4;
- // private final int YGREATERYMAX = 8;
- private final static int XMASK = 3;
- private final static int YMASK = 12;
-
- public double xmin;
-
- public double ymin;
-
- public double xmax;
-
- public double ymax;
-
- public static Envelope2D construct(double _xmin, double _ymin,
- double _xmax, double _ymax) {
- Envelope2D env = new Envelope2D();
- env.xmin = _xmin;
- env.ymin = _ymin;
- env.xmax = _xmax;
- env.ymax = _ymax;
- return env;
- }
-
- public static Envelope2D construct(Envelope2D other) {
- Envelope2D env = new Envelope2D();
- env.setCoords(other);
- return env;
- }
-
- public Envelope2D() {
- setEmpty();
- }
-
- public Envelope2D(double _xmin, double _ymin, double _xmax, double _ymax) {
- xmin = _xmin;
- ymin = _ymin;
- xmax = _xmax;
- ymax = _ymax;
- }
+ private static final long serialVersionUID = 1L;
+
+ private final static int XLESSXMIN = 1;
+ // private final int XGREATERXMAX = 2;
+ private final static int YLESSYMIN = 4;
+ // private final int YGREATERYMAX = 8;
+ private final static int XMASK = 3;
+ private final static int YMASK = 12;
+
+ public double xmin;
+
+ public double ymin;
+
+ public double xmax;
+
+ public double ymax;
+
+ public static Envelope2D construct(double _xmin, double _ymin,
+ double _xmax, double _ymax) {
+ Envelope2D env = new Envelope2D();
+ env.xmin = _xmin;
+ env.ymin = _ymin;
+ env.xmax = _xmax;
+ env.ymax = _ymax;
+ return env;
+ }
+
+ public static Envelope2D construct(Envelope2D other) {
+ Envelope2D env = new Envelope2D();
+ env.setCoords(other);
+ return env;
+ }
+
+ public Envelope2D() {
+ setEmpty();
+ }
+
+ public Envelope2D(double _xmin, double _ymin, double _xmax, double _ymax) {
+ xmin = _xmin;
+ ymin = _ymin;
+ xmax = _xmax;
+ ymax = _ymax;
+ }
public Envelope2D(Envelope2D other) {
setCoords(other);
@@ -86,7 +86,7 @@ public int estimateMemorySize()
{
return SIZE_OF_ENVELOPE2D;
}
-
+
public void setCoords(double _x, double _y) {
xmin = _x;
ymin = _y;
@@ -94,39 +94,39 @@ public void setCoords(double _x, double _y) {
ymax = _y;
}
- public void setCoords(double _xmin, double _ymin, double _xmax, double _ymax) {
- xmin = _xmin;
- ymin = _ymin;
- xmax = _xmax;
- ymax = _ymax;
- normalize();
- }
-
- public void setCoords(Point2D center, double width, double height) {
- xmin = center.x - width * 0.5;
- xmax = xmin + width;
- ymin = center.y - height * 0.5;
- ymax = ymin + height;
- normalize();
- }
-
- public void setCoords(Point2D pt) {
- xmin = pt.x;
- ymin = pt.y;
- xmax = pt.x;
- ymax = pt.y;
- }
-
- public void setCoords(Envelope2D envSrc) {
- setCoords(envSrc.xmin, envSrc.ymin, envSrc.xmax, envSrc.ymax);
- }
-
- public Envelope2D getInflated(double dx, double dy) {
- Envelope2D env = new Envelope2D();
- env.setCoords(this.xmin, this.ymin, this.xmax, this.ymax);
- env.inflate(dx, dy);
- return env;
- }
+ public void setCoords(double _xmin, double _ymin, double _xmax, double _ymax) {
+ xmin = _xmin;
+ ymin = _ymin;
+ xmax = _xmax;
+ ymax = _ymax;
+ normalize();
+ }
+
+ public void setCoords(Point2D center, double width, double height) {
+ xmin = center.x - width * 0.5;
+ xmax = xmin + width;
+ ymin = center.y - height * 0.5;
+ ymax = ymin + height;
+ normalize();
+ }
+
+ public void setCoords(Point2D pt) {
+ xmin = pt.x;
+ ymin = pt.y;
+ xmax = pt.x;
+ ymax = pt.y;
+ }
+
+ public void setCoords(Envelope2D envSrc) {
+ setCoords(envSrc.xmin, envSrc.ymin, envSrc.xmax, envSrc.ymax);
+ }
+
+ public Envelope2D getInflated(double dx, double dy) {
+ Envelope2D env = new Envelope2D();
+ env.setCoords(this.xmin, this.ymin, this.xmax, this.ymax);
+ env.inflate(dx, dy);
+ return env;
+ }
/**
* Sets the envelope from the array of points. The envelope will be set to
@@ -139,62 +139,62 @@ public void setFromPoints(Point2D[] points) {
return;
}
- Point2D pt = points[0];
- setCoords(pt.x, pt.y);
- for (int i = 1; i < points.length; i++) {
- Point2D pt2d = points[i];
- mergeNE(pt2d.x, pt2d.y);
- }
- }
-
- public void setEmpty() {
- xmin = NumberUtils.TheNaN;
- ymin = NumberUtils.TheNaN;
- xmax = NumberUtils.TheNaN;
- ymax = NumberUtils.TheNaN;
- }
-
- public void setInfinite() {
- xmin = NumberUtils.negativeInf();
- xmax = NumberUtils.positiveInf();
- ymin = NumberUtils.negativeInf();
- ymax = NumberUtils.positiveInf();
- }
-
- public boolean isEmpty() {
- return NumberUtils.isNaN(xmin) || NumberUtils.isNaN(ymin) || NumberUtils.isNaN(xmax) || NumberUtils.isNaN(ymax);
- }
-
- public void setCoords(Envelope1D xinterval, Envelope1D yinterval) {
- if (xinterval.isEmpty() || yinterval.isEmpty()) {
- setEmpty();
- return;
- }
-
- xmin = xinterval.vmin;
- xmax = xinterval.vmax;
- ymin = yinterval.vmin;
- ymax = yinterval.vmax;
- }
-
- public void merge(double x, double y) {
- if (isEmpty()) {
- xmin = x;
- ymin = y;
- xmax = x;
- ymax = y;
- } else {
- if (xmin > x)
- xmin = x;
- else if (xmax < x)
- xmax = x;
-
- if (ymin > y)
- ymin = y;
- else if (ymax < y)
- ymax = y;
- }
- }
+ Point2D pt = points[0];
+ setCoords(pt.x, pt.y);
+ for (int i = 1; i < points.length; i++) {
+ Point2D pt2d = points[i];
+ mergeNE(pt2d.x, pt2d.y);
+ }
+ }
+
+ public void setEmpty() {
+ xmin = NumberUtils.TheNaN;
+ ymin = NumberUtils.TheNaN;
+ xmax = NumberUtils.TheNaN;
+ ymax = NumberUtils.TheNaN;
+ }
+
+ public void setInfinite() {
+ xmin = NumberUtils.negativeInf();
+ xmax = NumberUtils.positiveInf();
+ ymin = NumberUtils.negativeInf();
+ ymax = NumberUtils.positiveInf();
+ }
+
+ public boolean isEmpty() {
+ return NumberUtils.isNaN(xmin) || NumberUtils.isNaN(ymin) || NumberUtils.isNaN(xmax) || NumberUtils.isNaN(ymax);
+ }
+
+ public void setCoords(Envelope1D xinterval, Envelope1D yinterval) {
+ if (xinterval.isEmpty() || yinterval.isEmpty()) {
+ setEmpty();
+ return;
+ }
+
+ xmin = xinterval.vmin;
+ xmax = xinterval.vmax;
+ ymin = yinterval.vmin;
+ ymax = yinterval.vmax;
+ }
+
+ public void merge(double x, double y) {
+ if (isEmpty()) {
+ xmin = x;
+ ymin = y;
+ xmax = x;
+ ymax = y;
+ } else {
+ if (xmin > x)
+ xmin = x;
+ else if (xmax < x)
+ xmax = x;
+
+ if (ymin > y)
+ ymin = y;
+ else if (ymax < y)
+ ymax = y;
+ }
+ }
/**
* Merges a point with this envelope without checking if the envelope is
@@ -208,56 +208,56 @@ public void mergeNE(double x, double y) {
else if (xmax < x)
xmax = x;
- if (ymin > y)
- ymin = y;
- else if (ymax < y)
- ymax = y;
- }
-
- public void merge(Point2D pt) {
- merge(pt.x, pt.y);
- }
-
- public void merge(Point3D pt) {
- merge(pt.x, pt.y);
- }
-
- public void merge(Envelope2D other) {
- if (other.isEmpty())
- return;
-
- merge(other.xmin, other.ymin);
- merge(other.xmax, other.ymax);
- }
-
- public void inflate(double dx, double dy) {
- if (isEmpty())
- return;
- xmin -= dx;
- xmax += dx;
- ymin -= dy;
- ymax += dy;
- if (xmin > xmax || ymin > ymax)
- setEmpty();
- }
-
- public void scale(double f) {
- if (f < 0.0)
- setEmpty();
-
- if (isEmpty())
- return;
-
- xmin *= f;
- xmax *= f;
- ymin *= f;
- ymax *= f;
- }
-
- public void zoom(double factorX, double factorY) {
- if (!isEmpty())
- setCoords(getCenter(), factorX * getWidth(), factorY * getHeight());
- }
+ if (ymin > y)
+ ymin = y;
+ else if (ymax < y)
+ ymax = y;
+ }
+
+ public void merge(Point2D pt) {
+ merge(pt.x, pt.y);
+ }
+
+ public void merge(Point3D pt) {
+ merge(pt.x, pt.y);
+ }
+
+ public void merge(Envelope2D other) {
+ if (other.isEmpty())
+ return;
+
+ merge(other.xmin, other.ymin);
+ merge(other.xmax, other.ymax);
+ }
+
+ public void inflate(double dx, double dy) {
+ if (isEmpty())
+ return;
+ xmin -= dx;
+ xmax += dx;
+ ymin -= dy;
+ ymax += dy;
+ if (xmin > xmax || ymin > ymax)
+ setEmpty();
+ }
+
+ public void scale(double f) {
+ if (f < 0.0)
+ setEmpty();
+
+ if (isEmpty())
+ return;
+
+ xmin *= f;
+ xmax *= f;
+ ymin *= f;
+ ymax *= f;
+ }
+
+ public void zoom(double factorX, double factorY) {
+ if (!isEmpty())
+ setCoords(getCenter(), factorX * getWidth(), factorY * getHeight());
+ }
/**
* Checks if this envelope intersects the other.
@@ -312,7 +312,7 @@ public boolean isIntersecting(double xmin_, double ymin_, double xmax_, double y
// projections
// overlap
}
-
+
/**
* Intersects this envelope with the other and stores result in this
* envelope.
@@ -321,58 +321,62 @@ public boolean isIntersecting(double xmin_, double ymin_, double xmax_, double y
* envelope to empty state and returns False.
*/
public boolean intersect(Envelope2D other) {
- if (isEmpty() || other.isEmpty())
+ if (isEmpty() || other.isEmpty()) {
+ setEmpty();
return false;
+ }
+
+ if (other.xmin > xmin)
+ xmin = other.xmin;
- if (other.xmin > xmin)
- xmin = other.xmin;
-
- if (other.xmax < xmax)
- xmax = other.xmax;
-
- if (other.ymin > ymin)
- ymin = other.ymin;
-
- if (other.ymax < ymax)
- ymax = other.ymax;
-
- boolean bIntersecting = xmin <= xmax && ymin <= ymax;
-
- if (!bIntersecting)
- setEmpty();
-
- return bIntersecting;
- }
-
- /**
- * Queries a corner of the envelope.
- *
- * @param index Indicates a corner of the envelope.
- *
- * 0 means lower left or (xmin, ymin)
- *
- * 1 means upper left or (xmin, ymax)
- *
- * 2 means upper right or (xmax, ymax)
- *
- * 3 means lower right or (xmax, ymin)
- * @return Point at a corner of the envelope.
- */
- public Point2D queryCorner(int index) {
- switch (index) {
- case 0:
- return Point2D.construct(xmin, ymin);
- case 1:
- return Point2D.construct(xmin, ymax);
- case 2:
- return Point2D.construct(xmax, ymax);
- case 3:
- return Point2D.construct(xmax, ymin);
- default:
- throw new IndexOutOfBoundsException();
-
- }
- }
+ if (other.xmax < xmax)
+ xmax = other.xmax;
+
+ if (other.ymin > ymin)
+ ymin = other.ymin;
+
+ if (other.ymax < ymax)
+ ymax = other.ymax;
+
+ boolean bIntersecting = xmin <= xmax && ymin <= ymax;
+
+ if (!bIntersecting)
+ setEmpty();
+
+ return bIntersecting;
+ }
+
+ /**
+ * Queries a corner of the envelope.
+ *
+ * @param index
+ * Indicates a corner of the envelope.
+ *
+ * 0 means lower left or (xmin, ymin)
+ *
+ * 1 means upper left or (xmin, ymax)
+ *
+ * 2 means upper right or (xmax, ymax)
+ *
+ * 3 means lower right or (xmax, ymin)
+ * @return Point at a corner of the envelope.
+ *
+ */
+ public Point2D queryCorner(int index) {
+ switch (index) {
+ case 0:
+ return Point2D.construct(xmin, ymin);
+ case 1:
+ return Point2D.construct(xmin, ymax);
+ case 2:
+ return Point2D.construct(xmax, ymax);
+ case 3:
+ return Point2D.construct(xmax, ymin);
+ default:
+ throw new IndexOutOfBoundsException();
+
+ }
+ }
/**
* Queries corners into a given array. The array length must be at least
@@ -387,21 +391,21 @@ public void queryCorners(Point2D[] corners) {
else
corners[0] = new Point2D(xmin, ymin);
- if (corners[1] != null)
- corners[1].setCoords(xmin, ymax);
- else
- corners[1] = new Point2D(xmin, ymax);
+ if (corners[1] != null)
+ corners[1].setCoords(xmin, ymax);
+ else
+ corners[1] = new Point2D(xmin, ymax);
- if (corners[2] != null)
- corners[2].setCoords(xmax, ymax);
- else
- corners[2] = new Point2D(xmax, ymax);
+ if (corners[2] != null)
+ corners[2].setCoords(xmax, ymax);
+ else
+ corners[2] = new Point2D(xmax, ymax);
- if (corners[3] != null)
- corners[3].setCoords(xmax, ymin);
- else
- corners[3] = new Point2D(xmax, ymin);
- }
+ if (corners[3] != null)
+ corners[3].setCoords(xmax, ymin);
+ else
+ corners[3] = new Point2D(xmax, ymin);
+ }
/**
* Queries corners into a given array in reversed order. The array length
@@ -417,95 +421,95 @@ public void queryCornersReversed(Point2D[] corners) {
else
corners[0] = new Point2D(xmin, ymin);
- if (corners[1] != null)
- corners[1].setCoords(xmax, ymin);
- else
- corners[1] = new Point2D(xmax, ymin);
-
- if (corners[2] != null)
- corners[2].setCoords(xmax, ymax);
- else
- corners[2] = new Point2D(xmax, ymax);
-
- if (corners[3] != null)
- corners[3].setCoords(xmin, ymax);
- else
- corners[3] = new Point2D(xmin, ymax);
- }
-
- public double getArea() {
- if (isEmpty())
- return 0;
- return getWidth() * getHeight();
- }
-
- public double getLength() {
- if (isEmpty())
- return 0;
- return 2.0 * (getWidth() + getHeight());
- }
-
- public void setFromPoints(Point2D[] points, int count) {
- if (count == 0) {
- setEmpty();
- return;
- }
- xmin = points[0].x;
- ymin = points[0].y;
- xmax = xmin;
- ymax = ymin;
- for (int i = 1; i < count; i++) {
- Point2D pt = points[i];
- if (pt.x < xmin)
- xmin = pt.x;
- else if (pt.x > xmax)
- xmax = pt.x;
- if (pt.y < ymin)
- ymin = pt.y;
- else if (pt.y > ymax)
- ymax = pt.y;
- }
- }
-
- public void reaspect(double arWidth, double arHeight) {
- if (isEmpty())
- return;
- double newAspectRatio = arWidth / arHeight;
- double widthHalf = getWidth() * 0.5;
- double heightHalf = getHeight() * 0.5;
-
- double newWidthHalf = heightHalf * newAspectRatio;
- if (widthHalf <= newWidthHalf) {// preserve height, increase width
- double xc = getCenterX();
- xmin = xc - newWidthHalf;
- xmax = xc + newWidthHalf;
- } else {// preserve the width, increase height
- double newHeightHalf = widthHalf / newAspectRatio;
- double yc = getCenterY();
- ymin = yc - newHeightHalf;
- ymax = yc + newHeightHalf;
- }
-
- normalize();
- }
-
- public double getCenterX() {
- double cx = (xmax + xmin) / 2d;
- return cx;
- }
-
- public double getCenterY() {
- double cy = (ymax + ymin) / 2d;
- return cy;
- }
-
- public double getWidth() {
- return xmax - xmin;
- }
-
- public double getHeight() {
- return ymax - ymin;
- }
+ if (corners[1] != null)
+ corners[1].setCoords(xmax, ymin);
+ else
+ corners[1] = new Point2D(xmax, ymin);
+
+ if (corners[2] != null)
+ corners[2].setCoords(xmax, ymax);
+ else
+ corners[2] = new Point2D(xmax, ymax);
+
+ if (corners[3] != null)
+ corners[3].setCoords(xmin, ymax);
+ else
+ corners[3] = new Point2D(xmin, ymax);
+ }
+
+ public double getArea() {
+ if (isEmpty())
+ return 0;
+ return getWidth() * getHeight();
+ }
+
+ public double getLength() {
+ if (isEmpty())
+ return 0;
+ return 2.0 * (getWidth() + getHeight());
+ }
+
+ public void setFromPoints(Point2D[] points, int count) {
+ if (count == 0) {
+ setEmpty();
+ return;
+ }
+ xmin = points[0].x;
+ ymin = points[0].y;
+ xmax = xmin;
+ ymax = ymin;
+ for (int i = 1; i < count; i++) {
+ Point2D pt = points[i];
+ if (pt.x < xmin)
+ xmin = pt.x;
+ else if (pt.x > xmax)
+ xmax = pt.x;
+ if (pt.y < ymin)
+ ymin = pt.y;
+ else if (pt.y > ymax)
+ ymax = pt.y;
+ }
+ }
+
+ public void reaspect(double arWidth, double arHeight) {
+ if (isEmpty())
+ return;
+ double newAspectRatio = arWidth / arHeight;
+ double widthHalf = getWidth() * 0.5;
+ double heightHalf = getHeight() * 0.5;
+
+ double newWidthHalf = heightHalf * newAspectRatio;
+ if (widthHalf <= newWidthHalf) {// preserve height, increase width
+ double xc = getCenterX();
+ xmin = xc - newWidthHalf;
+ xmax = xc + newWidthHalf;
+ } else {// preserve the width, increase height
+ double newHeightHalf = widthHalf / newAspectRatio;
+ double yc = getCenterY();
+ ymin = yc - newHeightHalf;
+ ymax = yc + newHeightHalf;
+ }
+
+ normalize();
+ }
+
+ public double getCenterX() {
+ double cx = (xmax + xmin) / 2d;
+ return cx;
+ }
+
+ public double getCenterY() {
+ double cy = (ymax + ymin) / 2d;
+ return cy;
+ }
+
+ public double getWidth() {
+ return xmax - xmin;
+ }
+
+ public double getHeight() {
+ return ymax - ymin;
+ }
/**
* Moves the Envelope by given distance.
@@ -521,50 +525,50 @@ public void move(double dx, double dy) {
ymax += dy;
}
- public void centerAt(double x, double y) {
- move(x - getCenterX(), y - getCenterY());
- }
+ public void centerAt(double x, double y) {
+ move(x - getCenterX(), y - getCenterY());
+ }
- void centerAt(Point2D pt) {
- centerAt(pt.x, pt.y);
- }
+ void centerAt(Point2D pt) {
+ centerAt(pt.x, pt.y);
+ }
- public void offset(double dx, double dy) {
- xmin += dx;// NaN remains NaN
- xmax += dx;
- ymin += dy;
- ymax += dy;
- }
+ public void offset(double dx, double dy) {
+ xmin += dx;// NaN remains NaN
+ xmax += dx;
+ ymin += dy;
+ ymax += dy;
+ }
- public void normalize() {
- if (isEmpty())
- return;
+ public void normalize() {
+ if (isEmpty())
+ return;
- double min = Math.min(xmin, xmax);
- double max = Math.max(xmin, xmax);
- xmin = min;
- xmax = max;
- min = Math.min(ymin, ymax);
- max = Math.max(ymin, ymax);
- ymin = min;
- ymax = max;
- }
+ double min = Math.min(xmin, xmax);
+ double max = Math.max(xmin, xmax);
+ xmin = min;
+ xmax = max;
+ min = Math.min(ymin, ymax);
+ max = Math.max(ymin, ymax);
+ ymin = min;
+ ymax = max;
+ }
- public void queryLowerLeft(Point2D pt) {
- pt.setCoords(xmin, ymin);
- }
+ public void queryLowerLeft(Point2D pt) {
+ pt.setCoords(xmin, ymin);
+ }
- public void queryLowerRight(Point2D pt) {
- pt.setCoords(xmax, ymin);
- }
+ public void queryLowerRight(Point2D pt) {
+ pt.setCoords(xmax, ymin);
+ }
- public void queryUpperLeft(Point2D pt) {
- pt.setCoords(xmin, ymax);
- }
+ public void queryUpperLeft(Point2D pt) {
+ pt.setCoords(xmin, ymax);
+ }
- public void queryUpperRight(Point2D pt) {
- pt.setCoords(xmax, ymax);
- }
+ public void queryUpperRight(Point2D pt) {
+ pt.setCoords(xmax, ymax);
+ }
/**
* Returns True if this envelope is valid (empty, or has xmin less or equal
@@ -575,60 +579,60 @@ public boolean isValid() {
return isEmpty() || (xmin <= xmax && ymin <= ymax);
}
- /**
- * Gets the center point of the envelope. The Center Point occurs at: ((XMin
- * + XMax) / 2, (YMin + YMax) / 2).
- *
- * @return the center point
- */
- public Point2D getCenter() {
- return new Point2D((xmax + xmin) / 2d, (ymax + ymin) / 2d);
- }
-
- public void queryCenter(Point2D center) {
- center.x = (xmax + xmin) / 2d;
- center.y = (ymax + ymin) / 2d;
- }
-
- public void centerAt(Point c) {
- double cx = (xmax - xmin) / 2d;
- double cy = (ymax - ymin) / 2d;
-
- xmin = c.getX() - cx;
- xmax = c.getX() + cx;
- ymin = c.getY() - cy;
- ymax = c.getY() + cy;
- }
-
- public Point2D getLowerLeft() {
- return new Point2D(xmin, ymin);
- }
-
- public Point2D getUpperLeft() {
- return new Point2D(xmin, ymax);
- }
-
- public Point2D getLowerRight() {
- return new Point2D(xmax, ymin);
- }
-
- public Point2D getUpperRight() {
- return new Point2D(xmax, ymax);
- }
-
- public boolean contains(Point p) {
- return contains(p.getX(), p.getY());
- }
-
- public boolean contains(Point2D p) {
- return contains(p.x, p.y);
- }
-
- public boolean contains(double x, double y) {
- // Note: This will return False, if envelope is empty, thus no need to
- // call is_empty().
- return x >= xmin && x <= xmax && y >= ymin && y <= ymax;
- }
+ /**
+ * Gets the center point of the envelope. The Center Point occurs at: ((XMin
+ * + XMax) / 2, (YMin + YMax) / 2).
+ *
+ * @return the center point
+ */
+ public Point2D getCenter() {
+ return new Point2D((xmax + xmin) / 2d, (ymax + ymin) / 2d);
+ }
+
+ public void queryCenter(Point2D center) {
+ center.x = (xmax + xmin) / 2d;
+ center.y = (ymax + ymin) / 2d;
+ }
+
+ public void centerAt(Point c) {
+ double cx = (xmax - xmin) / 2d;
+ double cy = (ymax - ymin) / 2d;
+
+ xmin = c.getX() - cx;
+ xmax = c.getX() + cx;
+ ymin = c.getY() - cy;
+ ymax = c.getY() + cy;
+ }
+
+ public Point2D getLowerLeft() {
+ return new Point2D(xmin, ymin);
+ }
+
+ public Point2D getUpperLeft() {
+ return new Point2D(xmin, ymax);
+ }
+
+ public Point2D getLowerRight() {
+ return new Point2D(xmax, ymin);
+ }
+
+ public Point2D getUpperRight() {
+ return new Point2D(xmax, ymax);
+ }
+
+ public boolean contains(Point p) {
+ return contains(p.getX(), p.getY());
+ }
+
+ public boolean contains(Point2D p) {
+ return contains(p.x, p.y);
+ }
+
+ public boolean contains(double x, double y) {
+ // Note: This will return False, if envelope is empty, thus no need to
+ // call is_empty().
+ return x >= xmin && x <= xmax && y >= ymin && y <= ymax;
+ }
/**
* Returns True if the envelope contains the other envelope (boundary
@@ -654,12 +658,12 @@ public boolean containsExclusive(double x, double y) {
return x > xmin && x < xmax && y > ymin && y < ymax;
}
- /**
- * Returns True if the envelope contains the point (boundary exclusive).
- */
- public boolean containsExclusive(Point2D pt) {
- return containsExclusive(pt.x, pt.y);
- }
+ /**
+ * Returns True if the envelope contains the point (boundary exclusive).
+ */
+ public boolean containsExclusive(Point2D pt) {
+ return containsExclusive(pt.x, pt.y);
+ }
/**
* Returns True if the envelope contains the other envelope (boundary
@@ -674,271 +678,262 @@ boolean containsExclusive(Envelope2D other) {
&& other.ymax < ymax;
}
- @Override
- public boolean equals(Object _other) {
- if (_other == this)
- return true;
+ @Override
+ public boolean equals(Object _other) {
+ if (_other == this)
+ return true;
+
+ if (!(_other instanceof Envelope2D))
+ return false;
+
+ Envelope2D other = (Envelope2D) _other;
+ if (isEmpty() && other.isEmpty())
+ return true;
+
+ if (xmin != other.xmin || ymin != other.ymin || xmax != other.xmax
+ || ymax != other.ymax)
+ return false;
+
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ if (isEmpty()) {
+ return NumberUtils.hash(NumberUtils.TheNaN);
+ }
+
+ int hash = NumberUtils.hash(xmin);
+ hash = NumberUtils.hash(hash, xmax);
+ hash = NumberUtils.hash(hash, ymin);
+ hash = NumberUtils.hash(hash, ymax);
+
+ return hash;
+ }
+
+ Point2D _snapToBoundary(Point2D pt) {
+ Point2D p = new Point2D();
+ p.setCoords(pt);
+ if (p._isNan())
+ return p;
+
+ if (isEmpty()) {
+ p._setNan();
+ return p;
+ }
+
+ if (p.x < xmin)
+ p.x = xmin;
+ else if (p.x > xmax)
+ p.x = xmax;
+
+ if (p.y < ymin)
+ p.y = ymin;
+ else if (p.y > ymax)
+ p.y = ymax;
+
+ if (!p.equals(pt))
+ return p;
+
+ // p is inside envelope
+ Point2D center = getCenter();
+ double deltax = p.x < center.x ? p.x - xmin : xmax - p.x;
+ double deltay = p.y < center.y ? p.y - ymin : ymax - p.y;
+
+ if (deltax < deltay)
+ p.x = p.x < center.x ? xmin : xmax;
+ else
+ p.y = p.y < center.y ? ymin : ymax;
+
+ return p;
+ }
- if (!(_other instanceof Envelope2D))
- return false;
+ // Calculates distance of point from lower left corner of envelope,
+ // moving clockwise along the envelope boundary.
+ // The input point is assumed to lie exactly on envelope boundary
+ // If this is not the case then a projection to the nearest position on the
+ // envelope boundary is performed.
+ // (If the user knows that the input point does most likely not lie on the
+ // boundary,
+ // it is more efficient to perform ProjectToBoundary before using this
+ // function).
+ double _boundaryDistance(Point2D pt) {
+ if (isEmpty())
+ return NumberUtils.NaN();
- Envelope2D other = (Envelope2D) _other;
- if (isEmpty() && other.isEmpty())
- return true;
+ if (pt.x == xmin)
+ return pt.y - ymin;
- if (xmin != other.xmin || ymin != other.ymin || xmax != other.xmax
- || ymax != other.ymax)
- return false;
+ double height = ymax - ymin;
+ double width = xmax - xmin;
- return true;
- }
+ if (pt.y == ymax)
+ return height + pt.x - xmin;
- @Override
- public int hashCode() {
+ if (pt.x == xmax)
+ return height + width + ymax - pt.y;
- long bits = Double.doubleToLongBits(xmin);
- int hc = (int) (bits ^ (bits >>> 32));
+ if (pt.y == ymin)
+ return height * 2.0 + width + xmax - pt.x;
- int hash = NumberUtils.hash(hc);
+ return _boundaryDistance(_snapToBoundary(pt));
+ }
- bits = Double.doubleToLongBits(xmax);
- hc = (int) (bits ^ (bits >>> 32));
- hash = NumberUtils.hash(hash, hc);
+ // returns 0,..3 depending on which side pt lies.
+ int _envelopeSide(Point2D pt) {
- bits = Double.doubleToLongBits(ymin);
- hc = (int) (bits ^ (bits >>> 32));
- hash = NumberUtils.hash(hash, hc);
+ if (isEmpty())
+ return -1;
- bits = Double.doubleToLongBits(ymax);
- hc = (int) (bits ^ (bits >>> 32));
- hash = NumberUtils.hash(hash, hc);
+ double boundaryDist = _boundaryDistance(pt);
+ double height = ymax - ymin;
+ double width = xmax - xmin;
- return hash;
- }
+ if (boundaryDist < height)
+ return 0;
- Point2D _snapToBoundary(Point2D pt) {
- Point2D p = new Point2D();
- p.setCoords(pt);
- if (p._isNan())
- return p;
-
- if (isEmpty()) {
- p._setNan();
- return p;
- }
+ if ((boundaryDist -= height) < width)
+ return 1;
- if (p.x < xmin)
- p.x = xmin;
- else if (p.x > xmax)
- p.x = xmax;
-
- if (p.y < ymin)
- p.y = ymin;
- else if (p.y > ymax)
- p.y = ymax;
+ return boundaryDist - width < height ? 2 : 3;
+ }
- if (!p.equals(pt))
- return p;
+ double _calculateToleranceFromEnvelope() {
+ if (isEmpty())
+ return NumberUtils.doubleEps() * 100.0; // GEOMTERYX_EPSFACTOR
+ // 100.0;
+ double r = Math.abs(xmin) + Math.abs(xmax) + Math.abs(ymin)
+ + Math.abs(ymax) + 1;
+ return r * NumberUtils.doubleEps() * 100.0; // GEOMTERYX_EPSFACTOR
+ // 100.0;
+ }
- // p is inside envelope
- Point2D center = getCenter();
- double deltax = p.x < center.x ? p.x - xmin : xmax - p.x;
- double deltay = p.y < center.y ? p.y - ymin : ymax - p.y;
-
- if (deltax < deltay)
- p.x = p.x < center.x ? xmin : xmax;
- else
- p.y = p.y < center.y ? ymin : ymax;
-
- return p;
- }
-
- // Calculates distance of point from lower left corner of envelope,
- // moving clockwise along the envelope boundary.
- // The input point is assumed to lie exactly on envelope boundary
- // If this is not the case then a projection to the nearest position on the
- // envelope boundary is performed.
- // (If the user knows that the input point does most likely not lie on the
- // boundary,
- // it is more efficient to perform ProjectToBoundary before using this
- // function).
- double _boundaryDistance(Point2D pt) {
- if (isEmpty())
- return NumberUtils.NaN();
-
- if (pt.x == xmin)
- return pt.y - ymin;
-
- double height = ymax - ymin;
- double width = xmax - xmin;
-
- if (pt.y == ymax)
- return height + pt.x - xmin;
-
- if (pt.x == xmax)
- return height + width + ymax - pt.y;
-
- if (pt.y == ymin)
- return height * 2.0 + width + xmax - pt.x;
-
- return _boundaryDistance(_snapToBoundary(pt));
- }
-
- // returns 0,..3 depending on which side pt lies.
- int _envelopeSide(Point2D pt) {
-
- if (isEmpty())
- return -1;
-
- double boundaryDist = _boundaryDistance(pt);
- double height = ymax - ymin;
- double width = xmax - xmin;
-
- if (boundaryDist < height)
- return 0;
-
- if ((boundaryDist -= height) < width)
- return 1;
-
- return boundaryDist - width < height ? 2 : 3;
- }
-
- double _calculateToleranceFromEnvelope() {
- if (isEmpty())
- return NumberUtils.doubleEps() * 100.0; // GEOMTERYX_EPSFACTOR
- // 100.0;
- double r = Math.abs(xmin) + Math.abs(xmax) + Math.abs(ymin)
- + Math.abs(ymax) + 1;
- return r * NumberUtils.doubleEps() * 100.0; // GEOMTERYX_EPSFACTOR
- // 100.0;
- }
-
- public int clipLine(Point2D p1, Point2D p2)
- // Modified Cohen-Sutherland Line-Clipping Algorithm
- // returns:
- // 0 - the segment is outside of the clipping window
- // 1 - p1 was modified
- // 2 - p2 was modified
- // 3 - p1 and p2 were modified
- // 4 - the segment is complitely inside of the clipping window
- {
- int c1 = _clipCode(p1), c2 = _clipCode(p2);
-
- if ((c1 & c2) != 0)// (c1 & c2)
- return 0;
-
- if ((c1 | c2) == 0)// (!(c1 | c2))
- return 4;
-
- final int res = ((c1 != 0) ? 1 : 0) | ((c2 != 0) ? 2 : 0);// (c1 ? 1 :
- // 0) | (c2
- // ? 2 : 0);
-
- do {
- double dx = p2.x - p1.x, dy = p2.y - p1.y;
-
- boolean bDX = dx > dy;
-
- if (bDX) {
- if ((c1 & XMASK) != 0)// (c1 & XMASK)
- {
- if ((c1 & XLESSXMIN) != 0)// (c1 & XLESSXMIN)
- {
- p1.y += dy * (xmin - p1.x) / dx;
- p1.x = xmin;
- } else {
- p1.y += dy * (xmax - p1.x) / dx;
- p1.x = xmax;
- }
-
- c1 = _clipCode(p1);
- } else if ((c2 & XMASK) != 0)// (c2 & XMASK)
- {
- if ((c2 & XLESSXMIN) != 0) {
- p2.y += dy * (xmin - p2.x) / dx;
- p2.x = xmin;
- } else {
- p2.y += dy * (xmax - p2.x) / dx;
- p2.x = xmax;
- }
-
- c2 = _clipCode(p2);
- } else if (c1 != 0)// (c1)
- {
- if ((c1 & YLESSYMIN) != 0)// (c1 & YLESSYMIN)
- {
- p1.x += dx * (ymin - p1.y) / dy;
- p1.y = ymin;
- } else {
- p1.x += dx * (ymax - p1.y) / dy;
- p1.y = ymax;
- }
-
- c1 = _clipCode(p1);
- } else {
- if ((c2 & YLESSYMIN) != 0)// (c2 & YLESSYMIN)
- {
- p2.x += dx * (ymin - p2.y) / dy;
- p2.y = ymin;
- } else {
- p2.x += dx * (ymax - p2.y) / dy;
- p2.y = ymax;
- }
-
- c2 = _clipCode(p2);
- }
- } else {
- if ((c1 & YMASK) != 0)// (c1 & YMASK)
- {
- if ((c1 & YLESSYMIN) != 0)// (c1 & YLESSYMIN)
- {
- p1.x += dx * (ymin - p1.y) / dy;
- p1.y = ymin;
- } else {
- p1.x += dx * (ymax - p1.y) / dy;
- p1.y = ymax;
- }
-
- c1 = _clipCode(p1);
- } else if ((c2 & YMASK) != 0)// (c2 & YMASK)
- {
- if ((c2 & YLESSYMIN) != 0) // (c2 & YLESSYMIN)
- {
- p2.x += dx * (ymin - p2.y) / dy;
- p2.y = ymin;
- } else {
- p2.x += dx * (ymax - p2.y) / dy;
- p2.y = ymax;
- }
-
- c2 = _clipCode(p2);
- } else if (c1 != 0)// (c1)
- {
- if ((c1 & XLESSXMIN) != 0)// (c1 & XLESSXMIN)
- {
- p1.y += dy * (xmin - p1.x) / dx;
- p1.x = xmin;
- } else {
- p1.y += dy * (xmax - p1.x) / dx;
- p1.x = xmax;
- }
-
- c1 = _clipCode(p1);
- } else {
- if ((c2 & XLESSXMIN) != 0)// (c2 & XLESSXMIN)
- {
- p2.y += dy * (xmin - p2.x) / dx;
- p2.x = xmin;
- } else {
- p2.y += dy * (xmax - p2.x) / dx;
- p2.x = xmax;
- }
-
- c2 = _clipCode(p2);
- }
+ public int clipLine(Point2D p1, Point2D p2)
+ // Modified Cohen-Sutherland Line-Clipping Algorithm
+ // returns:
+ // 0 - the segment is outside of the clipping window
+ // 1 - p1 was modified
+ // 2 - p2 was modified
+ // 3 - p1 and p2 were modified
+ // 4 - the segment is complitely inside of the clipping window
+ {
+ int c1 = _clipCode(p1), c2 = _clipCode(p2);
+
+ if ((c1 & c2) != 0)// (c1 & c2)
+ return 0;
+
+ if ((c1 | c2) == 0)// (!(c1 | c2))
+ return 4;
+
+ final int res = ((c1 != 0) ? 1 : 0) | ((c2 != 0) ? 2 : 0);// (c1 ? 1 :
+ // 0) | (c2
+ // ? 2 : 0);
+
+ do {
+ double dx = p2.x - p1.x, dy = p2.y - p1.y;
+
+ boolean bDX = dx > dy;
+
+ if (bDX) {
+ if ((c1 & XMASK) != 0)// (c1 & XMASK)
+ {
+ if ((c1 & XLESSXMIN) != 0)// (c1 & XLESSXMIN)
+ {
+ p1.y += dy * (xmin - p1.x) / dx;
+ p1.x = xmin;
+ } else {
+ p1.y += dy * (xmax - p1.x) / dx;
+ p1.x = xmax;
+ }
+
+ c1 = _clipCode(p1);
+ } else if ((c2 & XMASK) != 0)// (c2 & XMASK)
+ {
+ if ((c2 & XLESSXMIN) != 0) {
+ p2.y += dy * (xmin - p2.x) / dx;
+ p2.x = xmin;
+ } else {
+ p2.y += dy * (xmax - p2.x) / dx;
+ p2.x = xmax;
+ }
+
+ c2 = _clipCode(p2);
+ } else if (c1 != 0)// (c1)
+ {
+ if ((c1 & YLESSYMIN) != 0)// (c1 & YLESSYMIN)
+ {
+ p1.x += dx * (ymin - p1.y) / dy;
+ p1.y = ymin;
+ } else {
+ p1.x += dx * (ymax - p1.y) / dy;
+ p1.y = ymax;
+ }
+
+ c1 = _clipCode(p1);
+ } else {
+ if ((c2 & YLESSYMIN) != 0)// (c2 & YLESSYMIN)
+ {
+ p2.x += dx * (ymin - p2.y) / dy;
+ p2.y = ymin;
+ } else {
+ p2.x += dx * (ymax - p2.y) / dy;
+ p2.y = ymax;
+ }
+
+ c2 = _clipCode(p2);
+ }
+ } else {
+ if ((c1 & YMASK) != 0)// (c1 & YMASK)
+ {
+ if ((c1 & YLESSYMIN) != 0)// (c1 & YLESSYMIN)
+ {
+ p1.x += dx * (ymin - p1.y) / dy;
+ p1.y = ymin;
+ } else {
+ p1.x += dx * (ymax - p1.y) / dy;
+ p1.y = ymax;
+ }
+
+ c1 = _clipCode(p1);
+ } else if ((c2 & YMASK) != 0)// (c2 & YMASK)
+ {
+ if ((c2 & YLESSYMIN) != 0) // (c2 & YLESSYMIN)
+ {
+ p2.x += dx * (ymin - p2.y) / dy;
+ p2.y = ymin;
+ } else {
+ p2.x += dx * (ymax - p2.y) / dy;
+ p2.y = ymax;
+ }
+
+ c2 = _clipCode(p2);
+ } else if (c1 != 0)// (c1)
+ {
+ if ((c1 & XLESSXMIN) != 0)// (c1 & XLESSXMIN)
+ {
+ p1.y += dy * (xmin - p1.x) / dx;
+ p1.x = xmin;
+ } else {
+ p1.y += dy * (xmax - p1.x) / dx;
+ p1.x = xmax;
+ }
+
+ c1 = _clipCode(p1);
+ } else {
+ if ((c2 & XLESSXMIN) != 0)// (c2 & XLESSXMIN)
+ {
+ p2.y += dy * (xmin - p2.x) / dx;
+ p2.x = xmin;
+ } else {
+ p2.y += dy * (xmax - p2.x) / dx;
+ p2.x = xmax;
+ }
+
+ c2 = _clipCode(p2);
+ }
/*
- * if (c1) //original code. Faster, but less robust numerically.
+ * if (c1) //original code. Faster, but less robust numerically.
* ( //The Cohen-Sutherland Line-Clipping Algorithm) { if (c1 &
* XLESSXMIN) { p1.y += dy * (xmin - p1.x) / dx; p1.x = xmin; }
* else if (c1 & XGREATERXMAX) { p1.y += dy * (xmax - p1.x) /
@@ -956,140 +951,140 @@ public int clipLine(Point2D p1, Point2D p2)
*
* c2 = _clipCode(p2, ClipRect); }
*/
- }
-
- if ((c1 & c2) != 0)// (c1 & c2)
- return 0;
-
- } while ((c1 | c2) != 0);// (c1 | c2);
-
- return res;
- }
-
- int _clipCode(Point2D p)// returns a code from the Cohen-Sutherland (0000 is
- // boundary inclusive)
- {
- int left = (p.x < xmin) ? 1 : 0;
- int right = (p.x > xmax) ? 1 : 0;
- int bottom = (p.y < ymin) ? 1 : 0;
- int top = (p.y > ymax) ? 1 : 0;
- return left | right << 1 | bottom << 2 | top << 3;
- }
-
- // Clips and optionally extends line within envelope; modifies point 'from',
- // 'to'.
- // Algorithm: Liang-Barsky parametric line-clipping (Foley, vanDam, Feiner,
- // Hughes, second edition, 117-124)
- // lineExtension: 0 no line eExtension, 1 extend line at from point, 2
- // extend line at endpoint, 3 extend line at both ends
- // boundaryDistances can be NULLPTR.
- // returns:
- // 0 - the segment is outside of the clipping window
- // 1 - p1 was modified
- // 2 - p2 was modified
- // 3 - p1 and p2 were modified
- // 4 - the segment is complitely inside of the clipping window
- int clipLine(Point2D p0, Point2D p1, int lineExtension, double[] segParams,
- double[] boundaryDistances) {
- if (boundaryDistances != null) {
- boundaryDistances[0] = -1.0;
- boundaryDistances[1] = -1.0;
- }
-
- double[] tOld = new double[2];// LOCALREFCLASS1(ArrayOf(double), int,
- // tOld, 2);
- int modified = 0;
-
- Point2D delta = new Point2D(p1.x - p0.x, p1.y - p0.y);
-
- if (delta.x == 0.0 && delta.y == 0.0) // input line degenerates to a
- // point
- {
- segParams[0] = 0.0;
- segParams[1] = 0.0;
- return contains(p0) ? 4 : 0;
- }
-
- segParams[0] = ((lineExtension & 1) != 0) ? NumberUtils.negativeInf()
- : 0.0;
- segParams[1] = ((lineExtension & 2) != 0) ? NumberUtils.positiveInf()
- : 1.0;
- tOld[0] = segParams[0];
- tOld[1] = segParams[1];
-
- if (clipLineAuxiliary(delta.x, xmin - p0.x, segParams)
- && clipLineAuxiliary(-delta.x, p0.x - xmax, segParams)
- && clipLineAuxiliary(delta.y, ymin - p0.y, segParams)
- && clipLineAuxiliary(-delta.y, p0.y - ymax, segParams)) {
- if (segParams[1] < tOld[1]) {
- p1.scaleAdd(segParams[1], delta, p0);
- _snapToBoundary(p1); // needed for accuracy
- modified |= 2;
-
- if (boundaryDistances != null)
- boundaryDistances[1] = _boundaryDistance(p1);
- }
- if (segParams[0] > tOld[0]) {
- p0.scaleAdd(segParams[0], delta, p0);
- _snapToBoundary(p0); // needed for accuracy
- modified |= 1;
-
- if (boundaryDistances != null)
- boundaryDistances[0] = _boundaryDistance(p0);
- }
- }
-
- return modified;
- }
-
- boolean clipLineAuxiliary(double denominator, double numerator,
- double[] segParams) {
- double t = numerator / denominator;
- if (denominator > 0.0) {
- if (t > segParams[1])
- return false;
-
- if (t > segParams[0]) {
- segParams[0] = t;
- return true;
- }
- } else if (denominator < 0.0) {
- if (t < segParams[0])
- return false;
-
- if (t < segParams[1]) {
- segParams[1] = t;
- return true;
- }
- } else
- return numerator <= 0.0;
-
- return true;
- }
-
- /**
- * Returns True, envelope is degenerate (Width or Height are less than
- * tolerance). Note: this returns False for Empty envelope.
- */
- public boolean isDegenerate(double tolerance) {
- return !isEmpty()
- && (getWidth() <= tolerance || getHeight() <= tolerance);
- }
-
- Point2D _snapClip(Point2D pt)// clips the point if it is outside, then snaps
- // it to the boundary.
- {
- double x = NumberUtils.snap(pt.x, xmin, xmax);
- double y = NumberUtils.snap(pt.y, ymin, ymax);
- return new Point2D(x, y);
- }
-
- public boolean isPointOnBoundary(Point2D pt, double tolerance) {
- return Math.abs(pt.x - xmin) <= tolerance
- || Math.abs(pt.x - xmax) <= tolerance
- || Math.abs(pt.y - ymin) <= tolerance
- || Math.abs(pt.y - ymax) <= tolerance;
- }
+ }
+
+ if ((c1 & c2) != 0)// (c1 & c2)
+ return 0;
+
+ } while ((c1 | c2) != 0);// (c1 | c2);
+
+ return res;
+ }
+
+ int _clipCode(Point2D p)// returns a code from the Cohen-Sutherland (0000 is
+ // boundary inclusive)
+ {
+ int left = (p.x < xmin) ? 1 : 0;
+ int right = (p.x > xmax) ? 1 : 0;
+ int bottom = (p.y < ymin) ? 1 : 0;
+ int top = (p.y > ymax) ? 1 : 0;
+ return left | right << 1 | bottom << 2 | top << 3;
+ }
+
+ // Clips and optionally extends line within envelope; modifies point 'from',
+ // 'to'.
+ // Algorithm: Liang-Barsky parametric line-clipping (Foley, vanDam, Feiner,
+ // Hughes, second edition, 117-124)
+ // lineExtension: 0 no line eExtension, 1 extend line at from point, 2
+ // extend line at endpoint, 3 extend line at both ends
+ // boundaryDistances can be NULLPTR.
+ // returns:
+ // 0 - the segment is outside of the clipping window
+ // 1 - p1 was modified
+ // 2 - p2 was modified
+ // 3 - p1 and p2 were modified
+ // 4 - the segment is complitely inside of the clipping window
+ int clipLine(Point2D p0, Point2D p1, int lineExtension, double[] segParams,
+ double[] boundaryDistances) {
+ if (boundaryDistances != null) {
+ boundaryDistances[0] = -1.0;
+ boundaryDistances[1] = -1.0;
+ }
+
+ double[] tOld = new double[2];// LOCALREFCLASS1(ArrayOf(double), int,
+ // tOld, 2);
+ int modified = 0;
+
+ Point2D delta = new Point2D(p1.x - p0.x, p1.y - p0.y);
+
+ if (delta.x == 0.0 && delta.y == 0.0) // input line degenerates to a
+ // point
+ {
+ segParams[0] = 0.0;
+ segParams[1] = 0.0;
+ return contains(p0) ? 4 : 0;
+ }
+
+ segParams[0] = ((lineExtension & 1) != 0) ? NumberUtils.negativeInf()
+ : 0.0;
+ segParams[1] = ((lineExtension & 2) != 0) ? NumberUtils.positiveInf()
+ : 1.0;
+ tOld[0] = segParams[0];
+ tOld[1] = segParams[1];
+
+ if (clipLineAuxiliary(delta.x, xmin - p0.x, segParams)
+ && clipLineAuxiliary(-delta.x, p0.x - xmax, segParams)
+ && clipLineAuxiliary(delta.y, ymin - p0.y, segParams)
+ && clipLineAuxiliary(-delta.y, p0.y - ymax, segParams)) {
+ if (segParams[1] < tOld[1]) {
+ p1.scaleAdd(segParams[1], delta, p0);
+ _snapToBoundary(p1); // needed for accuracy
+ modified |= 2;
+
+ if (boundaryDistances != null)
+ boundaryDistances[1] = _boundaryDistance(p1);
+ }
+ if (segParams[0] > tOld[0]) {
+ p0.scaleAdd(segParams[0], delta, p0);
+ _snapToBoundary(p0); // needed for accuracy
+ modified |= 1;
+
+ if (boundaryDistances != null)
+ boundaryDistances[0] = _boundaryDistance(p0);
+ }
+ }
+
+ return modified;
+ }
+
+ boolean clipLineAuxiliary(double denominator, double numerator,
+ double[] segParams) {
+ double t = numerator / denominator;
+ if (denominator > 0.0) {
+ if (t > segParams[1])
+ return false;
+
+ if (t > segParams[0]) {
+ segParams[0] = t;
+ return true;
+ }
+ } else if (denominator < 0.0) {
+ if (t < segParams[0])
+ return false;
+
+ if (t < segParams[1]) {
+ segParams[1] = t;
+ return true;
+ }
+ } else
+ return numerator <= 0.0;
+
+ return true;
+ }
+
+ /**
+ * Returns True, envelope is degenerate (Width or Height are less than
+ * tolerance). Note: this returns False for Empty envelope.
+ */
+ public boolean isDegenerate(double tolerance) {
+ return !isEmpty()
+ && (getWidth() <= tolerance || getHeight() <= tolerance);
+ }
+
+ Point2D _snapClip(Point2D pt)// clips the point if it is outside, then snaps
+ // it to the boundary.
+ {
+ double x = NumberUtils.snap(pt.x, xmin, xmax);
+ double y = NumberUtils.snap(pt.y, ymin, ymax);
+ return new Point2D(x, y);
+ }
+
+ public boolean isPointOnBoundary(Point2D pt, double tolerance) {
+ return Math.abs(pt.x - xmin) <= tolerance
+ || Math.abs(pt.x - xmax) <= tolerance
+ || Math.abs(pt.y - ymin) <= tolerance
+ || Math.abs(pt.y - ymax) <= tolerance;
+ }
/**
* Calculates minimum distance from this envelope to the other.
@@ -1125,24 +1120,24 @@ public double sqrDistance(Envelope2D other)
double dy = 0;
double nn;
- nn = xmin - other.xmax;
- if (nn > dx)
- dx = nn;
+ nn = xmin - other.xmax;
+ if (nn > dx)
+ dx = nn;
- nn = ymin - other.ymax;
- if (nn > dy)
- dy = nn;
+ nn = ymin - other.ymax;
+ if (nn > dy)
+ dy = nn;
- nn = other.xmin - xmax;
- if (nn > dx)
- dx = nn;
+ nn = other.xmin - xmax;
+ if (nn > dx)
+ dx = nn;
- nn = other.ymin - ymax;
- if (nn > dy)
- dy = nn;
+ nn = other.ymin - ymax;
+ if (nn > dy)
+ dy = nn;
- return dx * dx + dy * dy;
- }
+ return dx * dx + dy * dy;
+ }
/**
* Calculates minimum squared distance from this envelope to the other.
@@ -1159,48 +1154,48 @@ public double sqrDistance(double xmin_, double ymin_, double xmax_, double ymax_
double dy = 0;
double nn;
- nn = xmin - xmax_;
- if (nn > dx)
- dx = nn;
-
- nn = ymin - ymax_;
- if (nn > dy)
- dy = nn;
-
- nn = xmin_ - xmax;
- if (nn > dx)
- dx = nn;
-
- nn = ymin_ - ymax;
- if (nn > dy)
- dy = nn;
-
- return dx * dx + dy * dy;
- }
-
- /**
- * Returns squared max distance between two bounding boxes. This is furthest distance between points on the two envelopes.
- *
- * @param other The bounding box to calculate the max distance two.
- * @return Squared distance value.
- */
- public double sqrMaxDistance(Envelope2D other) {
- if (isEmpty() || other.isEmpty())
- return NumberUtils.TheNaN;
-
- double dist = 0;
- Point2D[] points = new Point2D[4];
- queryCorners(points);
- Point2D[] points_o = new Point2D[4];
- other.queryCorners(points_o);
- for (int i = 0; i < 4; i++) {
- for (int j = 0; j < 4; j++) {
- double d = Point2D.sqrDistance(points[i], points_o[j]);
- if (d > dist) {
- dist = d;
- }
- }
- }
+ nn = xmin - xmax_;
+ if (nn > dx)
+ dx = nn;
+
+ nn = ymin - ymax_;
+ if (nn > dy)
+ dy = nn;
+
+ nn = xmin_ - xmax;
+ if (nn > dx)
+ dx = nn;
+
+ nn = ymin_ - ymax;
+ if (nn > dy)
+ dy = nn;
+
+ return dx * dx + dy * dy;
+ }
+
+ /**
+ *Returns squared max distance between two bounding boxes. This is furthest distance between points on the two envelopes.
+ *
+ *@param other The bounding box to calculate the max distance two.
+ *@return Squared distance value.
+ */
+ public double sqrMaxDistance(Envelope2D other) {
+ if (isEmpty() || other.isEmpty())
+ return NumberUtils.TheNaN;
+
+ double dist = 0;
+ Point2D[] points = new Point2D[4];
+ queryCorners(points);
+ Point2D[] points_o = new Point2D[4];
+ other.queryCorners(points_o);
+ for (int i = 0; i < 4; i++) {
+ for (int j = 0; j < 4; j++) {
+ double d = Point2D.sqrDistance(points[i], points_o[j]);
+ if (d > dist) {
+ dist = d;
+ }
+ }
+ }
return dist;
}
@@ -1217,51 +1212,51 @@ public double sqrDistance(Point2D pt2D)
double dy = 0;
double nn;
- nn = xmin - pt2D.x;
- if (nn > dx)
- dx = nn;
-
- nn = ymin - pt2D.y;
- if (nn > dy)
- dy = nn;
-
- nn = pt2D.x - xmax;
- if (nn > dx)
- dx = nn;
-
- nn = pt2D.y - ymax;
- if (nn > dy)
- dy = nn;
-
- return dx * dx + dy * dy;
- }
-
- public void queryIntervalX(Envelope1D env1D) {
- if (isEmpty()) {
- env1D.setEmpty();
- } else {
- env1D.setCoords(xmin, xmax);
- }
- }
-
- public void queryIntervalY(Envelope1D env1D) {
- if (isEmpty()) {
- env1D.setEmpty();
- } else {
- env1D.setCoords(ymin, ymax);
- }
- }
-
- private void writeObject(java.io.ObjectOutputStream out) throws IOException {
- out.defaultWriteObject();
- }
-
- private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
- in.defaultReadObject();
- }
-
- private void readObjectNoData() throws ObjectStreamException {
- setEmpty();
- }
+ nn = xmin - pt2D.x;
+ if (nn > dx)
+ dx = nn;
+
+ nn = ymin - pt2D.y;
+ if (nn > dy)
+ dy = nn;
+
+ nn = pt2D.x - xmax;
+ if (nn > dx)
+ dx = nn;
+
+ nn = pt2D.y - ymax;
+ if (nn > dy)
+ dy = nn;
+
+ return dx * dx + dy * dy;
+ }
+
+ public void queryIntervalX(Envelope1D env1D)
+ {
+ if (isEmpty()) {
+ env1D.setEmpty();
+ } else {
+ env1D.setCoords(xmin, xmax);
+ }
+ }
+
+ public void queryIntervalY(Envelope1D env1D)
+ {
+ if (isEmpty()) {
+ env1D.setEmpty();
+ } else {
+ env1D.setCoords(ymin, ymax);
+ }
+ }
+
+ private void writeObject(java.io.ObjectOutputStream out) throws IOException {
+ out.defaultWriteObject();
+ }
+ private void readObject(java.io.ObjectInputStream in) throws IOException, ClassNotFoundException {
+ in.defaultReadObject();
+ }
+ private void readObjectNoData() throws ObjectStreamException {
+ setEmpty();
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/Envelope2DIntersectorImpl.java b/src/main/java/com/esri/core/geometry/Envelope2DIntersectorImpl.java
index 2974be49..2941fcb6 100644
--- a/src/main/java/com/esri/core/geometry/Envelope2DIntersectorImpl.java
+++ b/src/main/java/com/esri/core/geometry/Envelope2DIntersectorImpl.java
@@ -26,898 +26,898 @@
import java.util.ArrayList;
class Envelope2DIntersectorImpl {
- /*
- * Constructor for Envelope_2D_intersector.
- */
- Envelope2DIntersectorImpl() {
- m_function = -1;
- m_tolerance = 0.0;
- reset_();
- }
-
- void startConstruction() {
- reset_();
- m_b_add_red_red = true;
-
- if (m_envelopes_red == null) {
- m_elements_red = new AttributeStreamOfInt32(0);
- m_envelopes_red = new ArrayList
- * Returns 0 for point and multipoint.
- *
- * Returns 1 for lines and polylines.
- *
- * Returns 2 for polygons and envelopes
- *
- * Returns 3 for objects with volume
- *
- * @return Returns the integer value of the dimension of geometry.
- */
- public abstract int getDimension();
+ }
+
+ /**
+ * Returns the geometry type.
+ *
+ * @return Returns the geometry type.
+ */
+ public abstract Geometry.Type getType();
+
+ /**
+ * Returns the topological dimension of the geometry object based on the
+ * geometry's type.
+ *
+ * Returns 0 for point and multipoint.
+ *
+ * Returns 1 for lines and polylines.
+ *
+ * Returns 2 for polygons and envelopes
+ *
+ * Returns 3 for objects with volume
+ *
+ * @return Returns the integer value of the dimension of geometry.
+ */
+ public abstract int getDimension();
/**
* Returns an estimate of this object size in bytes.
@@ -182,10 +184,10 @@ public void assignVertexDescription(VertexDescription src) {
if (src == m_description)
return;
- _assignVertexDescriptionImpl(src);
- }
+ _assignVertexDescriptionImpl(src);
+ }
- protected abstract void _assignVertexDescriptionImpl(VertexDescription src);
+ protected abstract void _assignVertexDescriptionImpl(VertexDescription src);
/**
* Merges the new VertexDescription by adding missing attributes from the
@@ -198,13 +200,13 @@ public void mergeVertexDescription(VertexDescription src) {
if (src == m_description)
return;
- // check if we need to do anything (if the src has same attributes)
- VertexDescription newdescription = VertexDescriptionDesignerImpl.getMergedVertexDescription(m_description, src);
- if (newdescription == m_description)
- return;
+ // check if we need to do anything (if the src has same attributes)
+ VertexDescription newdescription = VertexDescriptionDesignerImpl.getMergedVertexDescription(m_description, src);
+ if (newdescription == m_description)
+ return;
- _assignVertexDescriptionImpl(newdescription);
- }
+ _assignVertexDescriptionImpl(newdescription);
+ }
/**
* A shortcut for getDescription().hasAttribute()
@@ -217,14 +219,14 @@ public boolean hasAttribute(int semantics) {
/**
* Adds a new attribute to the Geometry.
- *
+ *
* @param semantics The VertexDescription.Semantics to add.
*/
public void addAttribute(int semantics) {
_touch();
if (m_description.hasAttribute(semantics))
return;
-
+
VertexDescription newvd = VertexDescriptionDesignerImpl.getMergedVertexDescription(m_description, semantics);
_assignVertexDescriptionImpl(newvd);
}
@@ -241,17 +243,17 @@ public void dropAttribute(int semantics) {
if (!m_description.hasAttribute(semantics))
return;
- VertexDescription newvd = VertexDescriptionDesignerImpl.removeSemanticsFromVertexDescription(m_description, semantics);
- _assignVertexDescriptionImpl(newvd);
- }
+ VertexDescription newvd = VertexDescriptionDesignerImpl.removeSemanticsFromVertexDescription(m_description, semantics);
+ _assignVertexDescriptionImpl(newvd);
+ }
- /**
- * Drops all attributes from the Geometry with exception of POSITON.
- */
- public void dropAllAttributes() {
- assignVertexDescription(VertexDescriptionDesignerImpl
- .getDefaultDescriptor2D());
- }
+ /**
+ * Drops all attributes from the Geometry with exception of POSITON.
+ */
+ public void dropAllAttributes() {
+ assignVertexDescription(VertexDescriptionDesignerImpl
+ .getDefaultDescriptor2D());
+ }
/**
* Returns the min and max attribute values at the ordinate of the Geometry.
@@ -261,12 +263,13 @@ public void dropAllAttributes() {
*/
public abstract Envelope1D queryInterval(int semantics, int ordinate);
- /**
- * Returns the axis aligned bounding box of the geometry.
- *
- * @param env The envelope to return the result in.
- */
- public abstract void queryEnvelope(Envelope env);
+ /**
+ * Returns the axis aligned bounding box of the geometry.
+ *
+ * @param env
+ * The envelope to return the result in.
+ */
+ public abstract void queryEnvelope(Envelope env);
/**
* Returns tight bbox of the Geometry in X, Y plane.
@@ -304,33 +307,35 @@ void queryLooseEnvelope3D(Envelope3D env) {
queryEnvelope3D(env);
}
- /**
- * IsEmpty returns TRUE when the Geometry object does not contain geometric
- * information beyond its original initialization state.
- *
- * @return boolean Returns TRUE if this geometry is empty.
- */
- public abstract boolean isEmpty();
+ /**
+ * IsEmpty returns TRUE when the Geometry object does not contain geometric
+ * information beyond its original initialization state.
+ *
+ * @return boolean Returns TRUE if this geometry is empty.
+ */
+ public abstract boolean isEmpty();
- /**
- * Returns the geometry to its original initialization state by releasing
- * all data referenced by the geometry.
- */
- public abstract void setEmpty();
+ /**
+ * Returns the geometry to its original initialization state by releasing
+ * all data referenced by the geometry.
+ */
+ public abstract void setEmpty();
- /**
- * Applies 2D affine transformation in XY plane.
- *
- * @param transform The affine transformation to be applied to this geometry.
- */
- public abstract void applyTransformation(Transformation2D transform);
+ /**
+ * Applies 2D affine transformation in XY plane.
+ *
+ * @param transform
+ * The affine transformation to be applied to this geometry.
+ */
+ public abstract void applyTransformation(Transformation2D transform);
- /**
- * Applies 3D affine transformation. Adds Z attribute if it is missing.
- *
- * @param transform The affine transformation to be applied to this geometry.
- */
- abstract void applyTransformation(Transformation3D transform);
+ /**
+ * Applies 3D affine transformation. Adds Z attribute if it is missing.
+ *
+ * @param transform
+ * The affine transformation to be applied to this geometry.
+ */
+ abstract void applyTransformation(Transformation3D transform);
/**
* Creates an instance of an empty geometry of the same type.
@@ -347,183 +352,190 @@ void queryLooseEnvelope3D(Envelope3D env) {
*/
public abstract void copyTo(Geometry dst);
- /**
- * Calculates the area of the geometry. If the spatial reference is a
- * Geographic Coordinate System (WGS84) then the 2D area calculation is
- * defined in angular units.
- *
- * @return A double value representing the 2D area of the geometry.
- */
- public double calculateArea2D() {
- return 0;
- }
-
- /**
- * Calculates the length of the geometry. If the spatial reference is a
- * Geographic Coordinate System (a system where coordinates are defined
- * using angular units such as longitude and latitude) then the 2D distance
- * calculation is returned in angular units. In cases where length must be
- * calculated on a Geographic Coordinate System consider the using the
- * geodeticLength method on the {@link GeometryEngine}
- *
- * @return A double value representing the 2D length of the geometry.
- */
- public double calculateLength2D() {
- return 0;
- }
-
- protected Object _getImpl() {
- throw new RuntimeException("invalid call");
- }
-
- /**
- * Adds the Z attribute to this Geometry
- */
- void addZ() {
- addAttribute(VertexDescription.Semantics.Z);
- }
-
- /**
- * Returns true if this Geometry has the Z attribute
- *
- * @return true if this Geometry has the Z attribute
- */
- public boolean hasZ() {
- return hasAttribute(VertexDescription.Semantics.Z);
- }
-
- /**
- * Adds the M attribute to this Geometry
- */
- public void addM() {
- addAttribute(VertexDescription.Semantics.M);
- }
-
- /**
- * Returns true if this Geometry has an M attribute
- *
- * @return true if this Geometry has an M attribute
- */
- public boolean hasM() {
- return hasAttribute(VertexDescription.Semantics.M);
- }
-
- /**
- * Adds the ID attribute to this Geometry
- */
- public void addID() {
- addAttribute(VertexDescription.Semantics.ID);
- }
-
- /**
- * Returns true if this Geometry has an ID attribute
- *
- * @return true if this Geometry has an ID attribute
- */
- public boolean hasID() {
- return hasAttribute(VertexDescription.Semantics.ID);
- }
-
- /**
- * Returns this geometry's dimension.
- *
- * Returns 0 for point and multipoint.
- *
- * Returns 1 for lines and polylines.
- *
- * Returns 2 for polygons and envelopes
- *
- * Returns 3 for objects with volume
- *
- * @param type The integer value from geometry enumeration. You can use the
- * method {@link Type#value()} to get at the integer value.
- * @return The integer dimension of this geometry.
- */
- public static int getDimensionFromType(int type) {
- return (((type & (0x40 | 0x80)) >> 6) + 1) >> 1;
- }
-
- /**
- * Indicates if the integer value of the enumeration is a point type
- * (dimension 0).
- *
- * @param type The integer value from geometry enumeration. You can use the
- * method {@link Type#value()} to get at the integer value.
- * @return TRUE if the geometry is a point.
- */
- public static boolean isPoint(int type) {
- return (type & 0x20) != 0;
- }
-
- /**
- * Indicates if the integer value of the enumeration is linear (dimension
- * 1).
- *
- * @param type The integer value from geometry enumeration. You can use the
- * method {@link Type#value()} to get at the integer value.
- * @return TRUE if the geometry is a line.
- */
- public static boolean isLinear(int type) {
- return (type & 0x40) != 0;
- }
-
- /**
- * Indicates if the integer value of the enumeration is an area (dimension
- * 2).
- *
- * @param type The integer value from geometry enumeration. You can use the
- * method {@link Type#value()} to get at the integer value.
- * @return TRUE if the geometry is a polygon.
- */
- public static boolean isArea(int type) {
- return (type & 0x80) != 0;
- }
-
- /**
- * Indicates if the integer value of the enumeration is a segment.
- *
- * @param type The integer value from geometry enumeration. You can use the
- * method {@link Type#value()} to get at the integer value.
- * @return TRUE if the geometry is a segment.
- */
- public static boolean isSegment(int type) {
- return (type & 0x100) != 0;
- }
-
- /**
- * Indicates if the integer value of the enumeration is a multivertex (ie,
- * multipoint, line, or area).
- *
- * @param type The integer value from geometry enumeration. You can use the
- * method {@link Type#value()} to get at the integer value.
- * @return TRUE if the geometry has multiple vertices.
- */
- public static boolean isMultiVertex(int type) {
- return (type & 0x200) != 0;
- }
-
- /**
- * Indicates if the integer value of the enumeration is a multipath (ie,
- * line or area).
- *
- * @param type The integer value from geometry enumeration. You can use the
- * method {@link Type#value()} to get at the integer value.
- * @return TRUE if the geometry is a multipath.
- */
- public static boolean isMultiPath(int type) {
- return (type & 0x400) != 0;
- }
-
- /**
- * Creates a copy of the geometry.
- *
- * @return Returns a copy of this geometry.
- */
- public Geometry copy() {
- Geometry geom = createInstance();
- this.copyTo(geom);
- return geom;
- }
+ /**
+ * Calculates the area of the geometry. If the spatial reference is a
+ * Geographic Coordinate System (WGS84) then the 2D area calculation is
+ * defined in angular units.
+ *
+ * @return A double value representing the 2D area of the geometry.
+ */
+ public double calculateArea2D() {
+ return 0;
+ }
+
+ /**
+ * Calculates the length of the geometry. If the spatial reference is a
+ * Geographic Coordinate System (a system where coordinates are defined
+ * using angular units such as longitude and latitude) then the 2D distance
+ * calculation is returned in angular units. In cases where length must be
+ * calculated on a Geographic Coordinate System consider the using the
+ * geodeticLength method on the {@link GeometryEngine}
+ *
+ * @return A double value representing the 2D length of the geometry.
+ */
+ public double calculateLength2D() {
+ return 0;
+ }
+
+ protected Object _getImpl() {
+ throw new RuntimeException("invalid call");
+ }
+
+ /**
+ * Adds the Z attribute to this Geometry
+ */
+ void addZ() {
+ addAttribute(VertexDescription.Semantics.Z);
+ }
+
+ /**
+ * Returns true if this Geometry has the Z attribute
+ *
+ * @return true if this Geometry has the Z attribute
+ */
+ public boolean hasZ() {
+ return hasAttribute(VertexDescription.Semantics.Z);
+ }
+
+ /**
+ * Adds the M attribute to this Geometry
+ */
+ public void addM() {
+ addAttribute(VertexDescription.Semantics.M);
+ }
+
+ /**
+ * Returns true if this Geometry has an M attribute
+ *
+ * @return true if this Geometry has an M attribute
+ */
+ public boolean hasM() {
+ return hasAttribute(VertexDescription.Semantics.M);
+ }
+
+ /**
+ * Adds the ID attribute to this Geometry
+ */
+ public void addID() {
+ addAttribute(VertexDescription.Semantics.ID);
+ }
+
+ /**
+ * Returns true if this Geometry has an ID attribute
+ *
+ * @return true if this Geometry has an ID attribute
+ */
+ public boolean hasID() {
+ return hasAttribute(VertexDescription.Semantics.ID);
+ }
+
+ /**
+ * Returns this geometry's dimension.
+ *
+ * Returns 0 for point and multipoint.
+ *
+ * Returns 1 for lines and polylines.
+ *
+ * Returns 2 for polygons and envelopes
+ *
+ * Returns 3 for objects with volume
+ *
+ * @param type
+ * The integer value from geometry enumeration. You can use the
+ * method {@link Type#value()} to get at the integer value.
+ * @return The integer dimension of this geometry.
+ */
+ public static int getDimensionFromType(int type) {
+ return (((type & (0x40 | 0x80)) >> 6) + 1) >> 1;
+ }
+
+ /**
+ * Indicates if the integer value of the enumeration is a point type
+ * (dimension 0).
+ *
+ * @param type
+ * The integer value from geometry enumeration. You can use the
+ * method {@link Type#value()} to get at the integer value.
+ * @return TRUE if the geometry is a point (a Point or a Multipoint).
+ */
+ public static boolean isPoint(int type) {
+ return (type & 0x20) != 0;
+ }
+
+ /**
+ * Indicates if the integer value of the enumeration is linear (dimension
+ * 1).
+ *
+ * @param type
+ * The integer value from geometry enumeration. You can use the
+ * method {@link Type#value()} to get at the integer value.
+ * @return TRUE if the geometry is a line.
+ */
+ public static boolean isLinear(int type) {
+ return (type & 0x40) != 0;
+ }
+
+ /**
+ * Indicates if the integer value of the enumeration is an area (dimension
+ * 2).
+ *
+ * @param type
+ * The integer value from geometry enumeration. You can use the
+ * method {@link Type#value()} to get at the integer value.
+ * @return TRUE if the geometry is a polygon.
+ */
+ public static boolean isArea(int type) {
+ return (type & 0x80) != 0;
+ }
+
+ /**
+ * Indicates if the integer value of the enumeration is a segment.
+ *
+ * @param type
+ * The integer value from geometry enumeration. You can use the
+ * method {@link Type#value()} to get at the integer value.
+ * @return TRUE if the geometry is a segment.
+ */
+ public static boolean isSegment(int type) {
+ return (type & 0x100) != 0;
+ }
+
+ /**
+ * Indicates if the integer value of the enumeration is a multivertex (ie,
+ * multipoint, line, or area).
+ *
+ * @param type
+ * The integer value from geometry enumeration. You can use the
+ * method {@link Type#value()} to get at the integer value.
+ * @return TRUE if the geometry has multiple vertices.
+ */
+ public static boolean isMultiVertex(int type) {
+ return (type & 0x200) != 0;
+ }
+
+ /**
+ * Indicates if the integer value of the enumeration is a multipath (ie,
+ * line or area).
+ *
+ * @param type
+ * The integer value from geometry enumeration. You can use the
+ * method {@link Type#value()} to get at the integer value.
+ * @return TRUE if the geometry is a multipath.
+ */
+ public static boolean isMultiPath(int type) {
+ return (type & 0x400) != 0;
+ }
+
+ /**
+ * Creates a copy of the geometry.
+ *
+ * @return Returns a copy of this geometry.
+ */
+ public Geometry copy() {
+ Geometry geom = createInstance();
+ this.copyTo(geom);
+ return geom;
+ }
/**
* Returns boundary of this geometry.
@@ -544,86 +556,91 @@ public Geometry copy() {
*/
public abstract void replaceNaNs(int semantics, double value);
- static Geometry _clone(Geometry src) {
- Geometry geom = src.createInstance();
- src.copyTo(geom);
- return geom;
- }
-
- /**
- * The stateFlag value changes with changes applied to this geometry. This
- * allows the user to keep track of the geometry's state.
- *
- * @return The state of the geometry.
- */
- public int getStateFlag() {
- m_touchFlag &= 0x7FFFFFFF;
- return m_touchFlag;
- }
-
- // Called whenever geometry changes
- synchronized void _touch() {
- if (m_touchFlag >= 0) {
- m_touchFlag += 0x80000001;
- }
- }
-
- /**
- * Describes the degree of acceleration of the geometry.
- * Acceleration usually builds a raster and a quadtree.
- */
- static public enum GeometryAccelerationDegree {
- /**
- * mild acceleration, takes least amount of memory. (64x64x2 bit raster)
- */
- enumMild,
- /**
- * medium acceleration, takes more memory and takes more time to accelerate, but may work faster.
- * (256x256x2 bit raster and a quad tree for segments)
- */
- enumMedium,
- /**
- * high acceleration, takes even more memory and may take
- * longest time to accelerate, but may work faster than the
- * other two.
- * (1024x1024x2 bit raster and a quad tree for segments)
- */
- enumHot
- }
-
- Object writeReplace() throws ObjectStreamException {
- Type gt = getType();
- if (gt == Geometry.Type.Point) {
- PtSrlzr pt = new PtSrlzr();
- pt.setGeometryByValue((Point) this);
- return pt;
- } else if (gt == Geometry.Type.Envelope) {
- EnvSrlzr e = new EnvSrlzr();
- e.setGeometryByValue((Envelope) this);
- return e;
- } else if (gt == Geometry.Type.Line) {
- LnSrlzr ln = new LnSrlzr();
- ln.setGeometryByValue((Line) this);
- return ln;
- }
+ static Geometry _clone(Geometry src) {
+ Geometry geom = src.createInstance();
+ src.copyTo(geom);
+ return geom;
+ }
- GenericGeometrySerializer geomSerializer = new GenericGeometrySerializer();
- geomSerializer.setGeometryByValue(this);
- return geomSerializer;
- }
-
- /**
- * The output of this method can be only used for debugging. It is subject to change without notice.
- */
- @Override
- public String toString() {
- String snippet = OperatorExportToWkt.local().execute(0, this, null);
- if (snippet.length() > 200) {
- return snippet.substring(0, 197) + "... (" + snippet.length() + " characters)";
- } else {
- return snippet;
- }
- }
+ /**
+ * The stateFlag value changes with changes applied to this geometry. This
+ * allows the user to keep track of the geometry's state.
+ *
+ * @return The state of the geometry.
+ */
+ public int getStateFlag() {
+ m_touchFlag &= 0x7FFFFFFF;
+ return m_touchFlag;
+ }
+
+ // Called whenever geometry changes
+ synchronized void _touch() {
+ if (m_touchFlag >= 0) {
+ m_touchFlag += 0x80000001;
+ }
+ }
+
+ /**
+ * Describes the degree of acceleration of the geometry.
+ * Acceleration usually builds a raster and a quadtree.
+ */
+ static public enum GeometryAccelerationDegree {
+ /**
+ * mild acceleration, takes least amount of memory. (64x64x2 bit raster)
+ */
+ enumMild,
+ /**
+ * medium acceleration, takes more memory and takes more time to accelerate, but may work faster.
+ * (256x256x2 bit raster and a quad tree for segments)
+ */
+ enumMedium,
+ /**
+ *high acceleration, takes even more memory and may take
+ *longest time to accelerate, but may work faster than the
+ *other two.
+ *(1024x1024x2 bit raster and a quad tree for segments)
+ */
+ enumHot
+ }
+
+ Object writeReplace() throws ObjectStreamException {
+ Type gt = getType();
+ if (gt == Geometry.Type.Point)
+ {
+ PtSrlzr pt = new PtSrlzr();
+ pt.setGeometryByValue((Point)this);
+ return pt;
+ }
+ else if (gt == Geometry.Type.Envelope)
+ {
+ EnvSrlzr e = new EnvSrlzr();
+ e.setGeometryByValue((Envelope)this);
+ return e;
+ }
+ else if (gt == Geometry.Type.Line)
+ {
+ LnSrlzr ln = new LnSrlzr();
+ ln.setGeometryByValue((Line)this);
+ return ln;
+ }
+
+ GenericGeometrySerializer geomSerializer = new GenericGeometrySerializer();
+ geomSerializer.setGeometryByValue(this);
+ return geomSerializer;
+ }
+
+ /**
+ * The output of this method can be only used for debugging. It is subject to change without notice.
+ */
+ @Override
+ public String toString() {
+ String snippet = OperatorExportToWkt.local().execute(0, this, null);
+ if (snippet.length() > 200) {
+ return snippet.substring(0, 197) + "... (" + snippet.length() + " characters)";
+ } else {
+ return snippet;
+ }
+ }
/**
* Returns count of geometry vertices: 1 for Point, 4 for Envelope,
@@ -637,32 +654,32 @@ public static int vertex_count(Geometry geom) {
if (Geometry.isMultiVertex(gt.value()))
return ((MultiVertexGeometry) geom).getPointCount();
- if (geom.isEmpty())
- return 0;
+ if (geom.isEmpty())
+ return 0;
- if (gt == Geometry.Type.Envelope)
- return 4;
+ if (gt == Geometry.Type.Envelope)
+ return 4;
- if (gt == Geometry.Type.Point)
- return 1;
+ if (gt == Geometry.Type.Point)
+ return 1;
- if (Geometry.isSegment(gt.value()))
- return 2;
+ if (Geometry.isSegment(gt.value()))
+ return 2;
- throw new GeometryException("missing type");
- }
+ throw new GeometryException("missing type");
+ }
- protected SimpleStateEnum getSimpleState() {
- if (getType() != Type.Polygon && getType() != Type.Polyline && getType() != Type.MultiPoint) {
- return SimpleStateEnum.STRONG_SIMPLE;
- } else {
- if (((MultiVertexGeometryImpl)this._getImpl())._hasDirtyFlag(MultiVertexGeometryImpl.DirtyFlags.IsStrongSimple)) {
- return SimpleStateEnum.STRONG_SIMPLE;
- } else if (((MultiVertexGeometryImpl)this._getImpl())._hasDirtyFlag(MultiVertexGeometryImpl.DirtyFlags.IsWeakSimple)) {
- return SimpleStateEnum.WEAK_SIMPLE;
- }
- return SimpleStateEnum.SIMPLE_UNKNOWN;
- }
- }
+ protected SimpleStateEnum getSimpleState() {
+ if (getType() != Type.Polygon && getType() != Type.Polyline && getType() != Type.MultiPoint) {
+ return SimpleStateEnum.STRONG_SIMPLE;
+ } else {
+ if (((MultiVertexGeometryImpl) this._getImpl())._hasDirtyFlag(MultiVertexGeometryImpl.DirtyFlags.IsStrongSimple)) {
+ return SimpleStateEnum.STRONG_SIMPLE;
+ } else if (((MultiVertexGeometryImpl) this._getImpl())._hasDirtyFlag(MultiVertexGeometryImpl.DirtyFlags.IsWeakSimple)) {
+ return SimpleStateEnum.WEAK_SIMPLE;
+ }
+ return SimpleStateEnum.SIMPLE_UNKNOWN;
+ }
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/GeometryAccelerators.java b/src/main/java/com/esri/core/geometry/GeometryAccelerators.java
index 4aca3b1d..90d699d0 100644
--- a/src/main/java/com/esri/core/geometry/GeometryAccelerators.java
+++ b/src/main/java/com/esri/core/geometry/GeometryAccelerators.java
@@ -23,59 +23,55 @@
*/
package com.esri.core.geometry;
-import java.util.ArrayList;
-
class GeometryAccelerators {
- private RasterizedGeometry2D m_rasterizedGeometry;
- private QuadTreeImpl m_quad_tree;
+ private RasterizedGeometry2D m_rasterizedGeometry;
+ private QuadTreeImpl m_quad_tree;
private QuadTreeImpl m_quad_tree_for_paths;
- public RasterizedGeometry2D getRasterizedGeometry() {
- return m_rasterizedGeometry;
- }
+ public RasterizedGeometry2D getRasterizedGeometry() {
+ return m_rasterizedGeometry;
+ }
- public QuadTreeImpl getQuadTree() {
- return m_quad_tree;
- }
+ public QuadTreeImpl getQuadTree() {
+ return m_quad_tree;
+ }
- public QuadTreeImpl getQuadTreeForPaths() {
- return m_quad_tree_for_paths;
- }
+ public QuadTreeImpl getQuadTreeForPaths() {
+ return m_quad_tree_for_paths;
+ }
- void _setRasterizedGeometry(RasterizedGeometry2D rg) {
- m_rasterizedGeometry = rg;
- }
+ void _setRasterizedGeometry(RasterizedGeometry2D rg) {
+ m_rasterizedGeometry = rg;
+ }
- void _setQuadTree(QuadTreeImpl quad_tree) {
- m_quad_tree = quad_tree;
- }
+ void _setQuadTree(QuadTreeImpl quad_tree) {
+ m_quad_tree = quad_tree;
+ }
- void _setQuadTreeForPaths(QuadTreeImpl quad_tree) {
- m_quad_tree_for_paths = quad_tree;
- }
+ void _setQuadTreeForPaths(QuadTreeImpl quad_tree) { m_quad_tree_for_paths = quad_tree; }
- static boolean canUseRasterizedGeometry(Geometry geom) {
- if (geom.isEmpty()
- || !(geom.getType() == Geometry.Type.Polyline || geom.getType() == Geometry.Type.Polygon)) {
- return false;
- }
+ static boolean canUseRasterizedGeometry(Geometry geom) {
+ if (geom.isEmpty()
+ || !(geom.getType() == Geometry.Type.Polyline || geom.getType() == Geometry.Type.Polygon)) {
+ return false;
+ }
- return true;
- }
+ return true;
+ }
- static boolean canUseQuadTree(Geometry geom) {
- if (geom.isEmpty()
- || !(geom.getType() == Geometry.Type.Polyline || geom.getType() == Geometry.Type.Polygon)) {
- return false;
- }
+ static boolean canUseQuadTree(Geometry geom) {
+ if (geom.isEmpty()
+ || !(geom.getType() == Geometry.Type.Polyline || geom.getType() == Geometry.Type.Polygon)) {
+ return false;
+ }
- if (((MultiVertexGeometry) geom).getPointCount() < 20) {
- return false;
- }
+ if (((MultiVertexGeometry) geom).getPointCount() < 20) {
+ return false;
+ }
- return true;
- }
+ return true;
+ }
static boolean canUseQuadTreeForPaths(Geometry geom) {
if (geom.isEmpty() || !(geom.getType() == Geometry.Type.Polyline || geom.getType() == Geometry.Type.Polygon))
@@ -86,4 +82,11 @@ static boolean canUseQuadTreeForPaths(Geometry geom) {
return true;
}
+
+ public long estimateMemorySize()
+ {
+ return (m_rasterizedGeometry != null ? m_rasterizedGeometry.estimateMemorySize() : 0) +
+ (m_quad_tree != null ? m_quad_tree.estimateMemorySize() : 0) +
+ (m_quad_tree_for_paths != null ? m_quad_tree_for_paths.estimateMemorySize() : 0);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/GeometryCursor.java b/src/main/java/com/esri/core/geometry/GeometryCursor.java
index ab127471..725fc08b 100644
--- a/src/main/java/com/esri/core/geometry/GeometryCursor.java
+++ b/src/main/java/com/esri/core/geometry/GeometryCursor.java
@@ -29,45 +29,49 @@
* An abstract Geometry Cursor class.
*/
public abstract class GeometryCursor implements Iterator
- * Returns an ID associated with the current Geometry. The ID is passed along and is returned by some operators to preserve relationship between the input and output geometry classes.
- * It is not always possible to preserve an ID during an operation.
- */
- public long getGeometryID() {
- return m_inputGeoms.getGeometryID();
- }
+ /**
+ * Returns the ID of the current geometry. The ID is propagated across the operations (when possible).
+ *
+ * Returns an ID associated with the current Geometry. The ID is passed along and is returned by some operators to preserve relationship between the input and output geometry classes.
+ * It is not always possible to preserve an ID during an operation.
+ */
+ public long getGeometryID() {
+ return m_inputGeoms.getGeometryID();
+ }
- public SimpleStateEnum getSimpleState() { return m_inputGeoms.getSimpleState(); }
+ public SimpleStateEnum getSimpleState() {
+ return m_inputGeoms.getSimpleState();
+ }
- public String getFeatureID() { return m_inputGeoms.getFeatureID(); }
+ public String getFeatureID() {
+ return m_inputGeoms.getFeatureID();
+ }
- /**
- * Executes a unit of work on the cursor.
- *
- * @return Returns true, if there is a geometry ready to be pulled using next().
- *
- * This method is to be used together with the tick() method on the ListeningGeometryCursor.
- * Call tock() for each tick() on the ListeningGeometryCursor.
- */
- public boolean tock() {
- return true;
- }
+ /**
+ * Executes a unit of work on the cursor.
+ *
+ * @return Returns true, if there is a geometry ready to be pulled using next().
+ *
+ * This method is to be used together with the tick() method on the ListeningGeometryCursor.
+ * Call tock() for each tick() on the ListeningGeometryCursor.
+ */
+ public boolean tock() {
+ return true;
+ }
- public boolean hasNext() {
- return m_inputGeoms != null && m_inputGeoms.hasNext();
- }
+ public boolean hasNext() {
+ return m_inputGeoms != null && m_inputGeoms.hasNext();
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/GeometryCursorAppend.java b/src/main/java/com/esri/core/geometry/GeometryCursorAppend.java
index 2228ddf4..37965ed6 100644
--- a/src/main/java/com/esri/core/geometry/GeometryCursorAppend.java
+++ b/src/main/java/com/esri/core/geometry/GeometryCursorAppend.java
@@ -25,31 +25,33 @@
public class GeometryCursorAppend extends GeometryCursor {
- private GeometryCursor m_cur1;
- private GeometryCursor m_cur2;
- private GeometryCursor m_cur;
-
- public GeometryCursorAppend(GeometryCursor cur1, GeometryCursor cur2) {
- m_cur1 = cur1;
- m_cur2 = cur2;
- m_cur = m_cur1;
- }
-
- @Override
- public boolean hasNext() { return m_cur != null && m_cur.hasNext(); }
-
- @Override
- public Geometry next() {
- Geometry g = m_cur.next();
- if (g == null && m_cur != m_cur2) {
- m_cur = m_cur2;
- return m_cur.next();
- }
- return g;
- }
-
- @Override
- public long getGeometryID() {
- return m_cur.getGeometryID();
- }
+ private GeometryCursor m_cur1;
+ private GeometryCursor m_cur2;
+ private GeometryCursor m_cur;
+
+ public GeometryCursorAppend(GeometryCursor cur1, GeometryCursor cur2) {
+ m_cur1 = cur1;
+ m_cur2 = cur2;
+ m_cur = m_cur1;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return m_cur != null && m_cur.hasNext();
+ }
+
+ @Override
+ public Geometry next() {
+ Geometry g = m_cur.next();
+ if (g == null && m_cur != m_cur2) {
+ m_cur = m_cur2;
+ return m_cur.next();
+ }
+ return g;
+ }
+
+ @Override
+ public long getGeometryID() {
+ return m_cur.getGeometryID();
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/GeometryEngine.java b/src/main/java/com/esri/core/geometry/GeometryEngine.java
index 188ac0eb..fc9855a3 100644
--- a/src/main/java/com/esri/core/geometry/GeometryEngine.java
+++ b/src/main/java/com/esri/core/geometry/GeometryEngine.java
@@ -39,801 +39,796 @@
*/
public class GeometryEngine {
- private static OperatorFactoryLocal factory = OperatorFactoryLocal
- .getInstance();
-
-
- /**
- * Imports the MapGeometry from its JSON representation. M and Z values are
- * not imported from JSON representation.
- *
- * See OperatorImportFromJson.
- *
- * @param json The JSON representation of the geometry (with spatial
- * reference).
- * @return The MapGeometry instance containing the imported geometry and its
- * spatial reference.
- */
- public static MapGeometry jsonToGeometry(JsonParser json) {
- MapGeometry geom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, new JsonParserReader(json));
- return geom;
- }
+ private static OperatorFactoryLocal factory = OperatorFactoryLocal
+ .getInstance();
+
+
+ /**
+ * Imports the MapGeometry from its JSON representation. M and Z values are
+ * not imported from JSON representation.
+ *
+ * See OperatorImportFromJson.
+ *
+ * @param json The JSON representation of the geometry (with spatial
+ * reference).
+ * @return The MapGeometry instance containing the imported geometry and its
+ * spatial reference.
+ */
+ public static MapGeometry jsonToGeometry(JsonParser json) {
+ MapGeometry geom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, new JsonParserReader(json));
+ return geom;
+ }
/**
* Imports the MapGeometry from its JSON representation. M and Z values are
* not imported from JSON representation.
- *
+ *
* See OperatorImportFromJson.
- *
- * @param json
- * The JSON representation of the geometry (with spatial
- * reference).
+ *
+ * @param json The JSON representation of the geometry (with spatial
+ * reference).
* @return The MapGeometry instance containing the imported geometry and its
- * spatial reference.
+ * spatial reference.
*/
public static MapGeometry jsonToGeometry(JsonReader json) {
MapGeometry geom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, json);
return geom;
}
-
+
/**
* Imports the MapGeometry from its JSON representation. M and Z values are
* not imported from JSON representation.
- *
+ *
* See OperatorImportFromJson.
- *
- * @param json
- * The JSON representation of the geometry (with spatial
- * reference).
+ *
+ * @param json The JSON representation of the geometry (with spatial
+ * reference).
* @return The MapGeometry instance containing the imported geometry and its
- * spatial reference.
+ * spatial reference.
*/
public static MapGeometry jsonToGeometry(String json) {
MapGeometry geom = OperatorImportFromJson.local().execute(Geometry.Type.Unknown, json);
return geom;
}
-
+
/**
* Exports the specified geometry instance to it's JSON representation.
- *
+ *
* See OperatorExportToJson.
- *
- * @see GeometryEngine#geometryToJson(SpatialReference spatialiReference,
- * Geometry geometry)
- * @param wkid
- * The spatial reference Well Known ID to be used for the JSON
- * representation.
- * @param geometry
- * The geometry to be exported to JSON.
+ *
+ * @param wkid The spatial reference Well Known ID to be used for the JSON
+ * representation.
+ * @param geometry The geometry to be exported to JSON.
* @return The JSON representation of the specified Geometry.
+ * @see GeometryEngine#geometryToJson(SpatialReference spatialiReference,
+ * Geometry geometry)
*/
public static String geometryToJson(int wkid, Geometry geometry) {
return GeometryEngine.geometryToJson(
wkid > 0 ? SpatialReference.create(wkid) : null, geometry);
}
- /**
- * Exports the specified geometry instance to it's JSON representation. M
- * and Z values are not imported from JSON representation.
- *
- * See OperatorExportToJson.
- *
- * @param spatialReference The spatial reference of associated object.
- * @param geometry The geometry.
- * @return The JSON representation of the specified geometry.
- */
- public static String geometryToJson(SpatialReference spatialReference,
- Geometry geometry) {
- OperatorExportToJson exporter = (OperatorExportToJson) factory
- .getOperator(Operator.Type.ExportToJson);
+ /**
+ * Exports the specified geometry instance to it's JSON representation. M
+ * and Z values are not imported from JSON representation.
+ *
+ * See OperatorExportToJson.
+ *
+ * @param spatialReference The spatial reference of associated object.
+ * @param geometry The geometry.
+ * @return The JSON representation of the specified geometry.
+ */
+ public static String geometryToJson(SpatialReference spatialReference,
+ Geometry geometry) {
+ OperatorExportToJson exporter = (OperatorExportToJson) factory
+ .getOperator(Operator.Type.ExportToJson);
- return exporter.execute(spatialReference, geometry);
- }
+ return exporter.execute(spatialReference, geometry);
+ }
- public static String geometryToGeoJson(Geometry geometry) {
- OperatorExportToGeoJson exporter = (OperatorExportToGeoJson) factory
- .getOperator(Operator.Type.ExportToGeoJson);
+ public static String geometryToGeoJson(Geometry geometry) {
+ OperatorExportToGeoJson exporter = (OperatorExportToGeoJson) factory
+ .getOperator(Operator.Type.ExportToGeoJson);
- return exporter.execute(geometry);
- }
+ return exporter.execute(geometry);
+ }
/**
* Imports the MapGeometry from its JSON representation. M and Z values are
* not imported from JSON representation.
- *
+ *
* See OperatorImportFromJson.
- *
- * @param json
- * The JSON representation of the geometry (with spatial
- * reference).
+ *
+ * @param json The JSON representation of the geometry (with spatial
+ * reference).
* @return The MapGeometry instance containing the imported geometry and its
- * spatial reference.
+ * spatial reference.
*/
public static MapGeometry geoJsonToGeometry(String json, int importFlags, Geometry.Type type) {
MapGeometry geom = OperatorImportFromGeoJson.local().execute(importFlags, type, json, null);
return geom;
}
- /**
- * Exports the specified geometry instance to its GeoJSON representation.
- *
- * See OperatorExportToGeoJson.
- *
- * @param wkid The spatial reference Well Known ID to be used for the GeoJSON
- * representation.
- * @param geometry The geometry to be exported to GeoJSON.
- * @return The GeoJSON representation of the specified geometry.
- * @see GeometryEngine#geometryToGeoJson(SpatialReference spatialReference,
- * Geometry geometry)
- */
- public static String geometryToGeoJson(int wkid, Geometry geometry) {
- return GeometryEngine.geometryToGeoJson(wkid > 0 ? SpatialReference.create(wkid) : null, geometry);
- }
-
- /**
- * Exports the specified geometry instance to it's JSON representation.
- *
- * See OperatorImportFromGeoJson.
- *
- * @param spatialReference The spatial reference of associated object.
- * @param geometry The geometry.
- * @return The GeoJSON representation of the specified geometry.
- */
- public static String geometryToGeoJson(SpatialReference spatialReference, Geometry geometry) {
- OperatorExportToGeoJson exporter = (OperatorExportToGeoJson) factory.getOperator(Operator.Type.ExportToGeoJson);
-
- return exporter.execute(spatialReference, geometry);
- }
-
- /**
- * Imports geometry from the ESRI shape file format.
- *
- * See OperatorImportFromESRIShape.
- *
- * @param esriShapeBuffer The buffer containing geometry in the ESRI shape file format.
- * @param geometryType The required type of the Geometry to be imported. Use
- * Geometry.Type.Unknown if the geometry type needs to be
- * determined from the buffer content.
- * @return The geometry or null if the buffer contains null shape.
- * @throws GeometryException when the geometryType is not Geometry.Type.Unknown and the
- * buffer contains geometry that cannot be converted to the
- * given geometryType. or the buffer is corrupt. Another
- * exception possible is IllegalArgumentsException.
- */
- public static Geometry geometryFromEsriShape(byte[] esriShapeBuffer, Geometry.Type geometryType) {
- OperatorImportFromESRIShape op = (OperatorImportFromESRIShape) factory.getOperator(Operator.Type.ImportFromESRIShape);
- return op.execute(ShapeImportFlags.ShapeImportNonTrusted,
- geometryType,
- ByteBuffer.wrap(esriShapeBuffer).order(ByteOrder.LITTLE_ENDIAN));
- }
-
- /**
- * Exports geometry to the ESRI shape file format.
- *
- * See OperatorExportToESRIShape.
- *
- * @param geometry The geometry to export. (null value is not allowed)
- * @return Array containing the exported ESRI shape file.
- */
- public static byte[] geometryToEsriShape(Geometry geometry) {
- if (geometry == null)
- throw new IllegalArgumentException();
- OperatorExportToESRIShape op = (OperatorExportToESRIShape) factory
- .getOperator(Operator.Type.ExportToESRIShape);
- return op.execute(0, geometry).array();
- }
+ /**
+ * Exports the specified geometry instance to its GeoJSON representation.
+ *
+ * See OperatorExportToGeoJson.
+ *
+ * @param wkid The spatial reference Well Known ID to be used for the GeoJSON
+ * representation.
+ * @param geometry The geometry to be exported to GeoJSON.
+ * @return The GeoJSON representation of the specified geometry.
+ * @see GeometryEngine#geometryToGeoJson(SpatialReference spatialReference,
+ * Geometry geometry)
+ */
+ public static String geometryToGeoJson(int wkid, Geometry geometry) {
+ return GeometryEngine.geometryToGeoJson(wkid > 0 ? SpatialReference.create(wkid) : null, geometry);
+ }
+
+ /**
+ * Exports the specified geometry instance to it's JSON representation.
+ *
+ * See OperatorImportFromGeoJson.
+ *
+ * @param spatialReference The spatial reference of associated object.
+ * @param geometry The geometry.
+ * @return The GeoJSON representation of the specified geometry.
+ */
+ public static String geometryToGeoJson(SpatialReference spatialReference, Geometry geometry) {
+ OperatorExportToGeoJson exporter = (OperatorExportToGeoJson) factory.getOperator(Operator.Type.ExportToGeoJson);
+
+ return exporter.execute(spatialReference, geometry);
+ }
+
+ /**
+ * Imports geometry from the ESRI shape file format.
+ *
+ * See OperatorImportFromESRIShape.
+ *
+ * @param esriShapeBuffer The buffer containing geometry in the ESRI shape file format.
+ * @param geometryType The required type of the Geometry to be imported. Use
+ * Geometry.Type.Unknown if the geometry type needs to be
+ * determined from the buffer content.
+ * @return The geometry or null if the buffer contains null shape.
+ * @throws GeometryException when the geometryType is not Geometry.Type.Unknown and the
+ * buffer contains geometry that cannot be converted to the
+ * given geometryType. or the buffer is corrupt. Another
+ * exception possible is IllegalArgumentsException.
+ */
+ public static Geometry geometryFromEsriShape(byte[] esriShapeBuffer, Geometry.Type geometryType) {
+ OperatorImportFromESRIShape op = (OperatorImportFromESRIShape) factory.getOperator(Operator.Type.ImportFromESRIShape);
+ return op.execute(ShapeImportFlags.ShapeImportNonTrusted,
+ geometryType,
+ ByteBuffer.wrap(esriShapeBuffer).order(ByteOrder.LITTLE_ENDIAN));
+ }
+
+ /**
+ * Exports geometry to the ESRI shape file format.
+ *
+ * See OperatorExportToESRIShape.
+ *
+ * @param geometry The geometry to export. (null value is not allowed)
+ * @return Array containing the exported ESRI shape file.
+ */
+ public static byte[] geometryToEsriShape(Geometry geometry) {
+ if (geometry == null)
+ throw new IllegalArgumentException();
+ OperatorExportToESRIShape op = (OperatorExportToESRIShape) factory
+ .getOperator(Operator.Type.ExportToESRIShape);
+ return op.execute(0, geometry).array();
+ }
/**
* Imports a geometry from a WKT string.
- *
+ *
* See OperatorImportFromWkt.
- *
- * @param wkt The string containing the geometry in WKT format.
- * @param importFlags Use the {@link WktImportFlags} interface.
+ *
+ * @param wkt The string containing the geometry in WKT format.
+ * @param importFlags Use the {@link WktImportFlags} interface.
* @param geometryType The required type of the Geometry to be imported. Use Geometry.Type.Unknown if the geometry type needs to be determined from the WKT context.
* @return The geometry.
- * @throws GeometryException when the geometryType is not Geometry.Type.Unknown and the WKT contains a geometry that cannot be converted to the given geometryType.
+ * @throws GeometryException when the geometryType is not Geometry.Type.Unknown and the WKT contains a geometry that cannot be converted to the given geometryType.
* @throws IllegalArgumentException if an error is found while parsing the WKT string.
*/
public static Geometry geometryFromWkt(String wkt, int importFlags,
- Geometry.Type geometryType) {
+ Geometry.Type geometryType) {
OperatorImportFromWkt op = (OperatorImportFromWkt) factory
.getOperator(Operator.Type.ImportFromWkt);
return op.execute(importFlags, geometryType, wkt, null);
}
- /**
- * Exports a geometry to a string in WKT format.
- *
- * See OperatorExportToWkt.
- *
- * @param geometry The geometry to export. (null value is not allowed)
- * @param exportFlags Use the {@link WktExportFlags} interface.
- * @return A String containing the exported geometry in WKT format.
- */
- public static String geometryToWkt(Geometry geometry, int exportFlags) {
- OperatorExportToWkt op = (OperatorExportToWkt) factory
- .getOperator(Operator.Type.ExportToWkt);
- return op.execute(exportFlags, geometry, null);
- }
-
- /**
- * Constructs a new geometry by union an array of geometries. All inputs
- * must be of the same type of geometries and share one spatial reference.
- *
- * See OperatorUnion.
- *
- * @param geometries The geometries to union.
- * @param spatialReference The spatial reference of the geometries.
- * @return The geometry object representing the resultant union.
- */
- public static Geometry union(Geometry[] geometries, SpatialReference spatialReference) {
- OperatorUnion op = (OperatorUnion) factory.getOperator(Operator.Type.Union);
-
- SimpleGeometryCursor inputGeometries = new SimpleGeometryCursor(geometries);
- GeometryCursor result = op.execute(inputGeometries, spatialReference, null);
- return result.next();
- }
-
- /**
- * Creates the difference of two geometries. The dimension of geometry2 has
- * to be equal to or greater than that of geometry1.
- *
- * See OperatorDifference.
- *
- * @param geometry1 The geometry being subtracted.
- * @param substractor The geometry object to subtract from.
- * @param spatialReference The spatial reference of the geometries.
- * @return The geometry of the differences.
- */
- public static Geometry difference(Geometry geometry1, Geometry substractor,
- SpatialReference spatialReference) {
- OperatorDifference op = (OperatorDifference) factory.getOperator(Operator.Type.Difference);
- Geometry result = op.execute(geometry1, substractor, spatialReference,null);
- return result;
- }
-
- /**
- * Creates the symmetric difference of two geometries.
- *
- * See OperatorSymmetricDifference.
- *
- * @param leftGeometry is one of the Geometry instances in the XOR operation.
- * @param rightGeometry is one of the Geometry instances in the XOR operation.
- * @param spatialReference The spatial reference of the geometries.
- * @return Returns the result of the symmetric difference.
- */
- public static Geometry symmetricDifference(Geometry leftGeometry,
- Geometry rightGeometry, SpatialReference spatialReference) {
- OperatorSymmetricDifference op = (OperatorSymmetricDifference) factory
- .getOperator(Operator.Type.SymmetricDifference);
- Geometry result = op.execute(leftGeometry, rightGeometry,
- spatialReference, null);
- return result;
- }
-
- /**
- * Indicates if two geometries are equal.
- *
- * See OperatorEquals.
- *
- * @param geometry1 Geometry.
- * @param geometry2 Geometry.
- * @param spatialReference The spatial reference of the geometries.
- * @return TRUE if both geometry objects are equal.
- */
- public static boolean equals(Geometry geometry1, Geometry geometry2,
- SpatialReference spatialReference) {
- OperatorEquals op = (OperatorEquals) factory
- .getOperator(Operator.Type.Equals);
- boolean result = op.execute(geometry1, geometry2, spatialReference,
- null);
- return result;
- }
-
- /**
- * See OperatorDisjoint.
- */
- public static boolean disjoint(Geometry geometry1, Geometry geometry2,
- SpatialReference spatialReference) {
- OperatorDisjoint op = (OperatorDisjoint) factory
- .getOperator(Operator.Type.Disjoint);
- boolean result = op.execute(geometry1, geometry2, spatialReference,
- null);
- return result;
- }
-
- /**
- * Constructs the set-theoretic intersection between an array of geometries
- * and another geometry.
- *
- * See OperatorIntersection (also for dimension specific intersection).
- *
- * @param inputGeometries An array of geometry objects.
- * @param geometry The geometry object.
- * @return Any array of geometry objects showing the intersection.
- */
- static Geometry[] intersect(Geometry[] inputGeometries, Geometry geometry,
- SpatialReference spatialReference) {
- OperatorIntersection op = (OperatorIntersection) factory
- .getOperator(Operator.Type.Intersection);
- SimpleGeometryCursor inputGeometriesCursor = new SimpleGeometryCursor(
- inputGeometries);
- SimpleGeometryCursor intersectorCursor = new SimpleGeometryCursor(
- geometry);
- GeometryCursor result = op.execute(inputGeometriesCursor,
- intersectorCursor, spatialReference, null);
-
- ArrayList
- * See OperatorIntersection.
- *
- * @param geometry1 The first geometry.
- * @param intersector The geometry to intersect the first geometry.
- * @param spatialReference The spatial reference of the geometries.
- * @return The geometry created through intersection.
- */
- public static Geometry intersect(Geometry geometry1, Geometry intersector,
- SpatialReference spatialReference) {
- OperatorIntersection op = (OperatorIntersection) factory.getOperator(Operator.Type.Intersection);
- Geometry result = op.execute(geometry1, intersector, spatialReference,null);
- return result;
- }
-
- /**
- * Indicates if one geometry is within another geometry.
- *
- * See OperatorWithin.
- *
- * @param geometry1 The base geometry that is tested for within relationship to
- * the other geometry.
- * @param geometry2 The comparison geometry that is tested for the contains
- * relationship to the other geometry.
- * @param spatialReference The spatial reference of the geometries.
- * @return TRUE if the first geometry is within the other geometry.
- */
- public static boolean within(Geometry geometry1, Geometry geometry2,
- SpatialReference spatialReference) {
- OperatorWithin op = (OperatorWithin) factory
- .getOperator(Operator.Type.Within);
- boolean result = op.execute(geometry1, geometry2, spatialReference,
- null);
- return result;
- }
-
- /**
- * Indicates if one geometry contains another geometry.
- *
- * See OperatorContains.
- *
- * @param geometry1 The geometry that is tested for the contains relationship to
- * the other geometry..
- * @param geometry2 The geometry that is tested for within relationship to the
- * other geometry.
- * @param spatialReference The spatial reference of the geometries.
- * @return TRUE if geometry1 contains geometry2.
- */
- public static boolean contains(Geometry geometry1, Geometry geometry2,
- SpatialReference spatialReference) {
- OperatorContains op = (OperatorContains) factory
- .getOperator(Operator.Type.Contains);
- boolean result = op.execute(geometry1, geometry2, spatialReference,
- null);
- return result;
- }
-
- /**
- * Indicates if one geometry crosses another geometry.
- *
- * See OperatorCrosses.
- *
- * @param geometry1 The geometry to cross.
- * @param geometry2 The geometry being crossed.
- * @param spatialReference The spatial reference of the geometries.
- * @return TRUE if geometry1 crosses geometry2.
- */
- public static boolean crosses(Geometry geometry1, Geometry geometry2,
- SpatialReference spatialReference) {
- OperatorCrosses op = (OperatorCrosses) factory
- .getOperator(Operator.Type.Crosses);
- boolean result = op.execute(geometry1, geometry2, spatialReference,
- null);
- return result;
- }
-
- /**
- * Indicates if one geometry touches another geometry.
- *
- * See OperatorTouches.
- *
- * @param geometry1 The geometry to touch.
- * @param geometry2 The geometry to be touched.
- * @param spatialReference The spatial reference of the geometries.
- * @return TRUE if geometry1 touches geometry2.
- */
- public static boolean touches(Geometry geometry1, Geometry geometry2,
- SpatialReference spatialReference) {
- OperatorTouches op = (OperatorTouches) factory
- .getOperator(Operator.Type.Touches);
- boolean result = op.execute(geometry1, geometry2, spatialReference,
- null);
- return result;
- }
-
- /**
- * Indicates if one geometry overlaps another geometry.
- *
- * See OperatorOverlaps.
- *
- * @param geometry1 The geometry to overlap.
- * @param geometry2 The geometry to be overlapped.
- * @param spatialReference The spatial reference of the geometries.
- * @return TRUE if geometry1 overlaps geometry2.
- */
- public static boolean overlaps(Geometry geometry1, Geometry geometry2,
- SpatialReference spatialReference) {
- OperatorOverlaps op = (OperatorOverlaps) factory
- .getOperator(Operator.Type.Overlaps);
- boolean result = op.execute(geometry1, geometry2, spatialReference,
- null);
- return result;
- }
-
- /**
- * Indicates if the given relation holds for the two geometries.
- *
- * See OperatorRelate.
- *
- * @param geometry1 The first geometry for the relation.
- * @param geometry2 The second geometry for the relation.
- * @param spatialReference The spatial reference of the geometries.
- * @param relation The DE-9IM relation.
- * @return TRUE if the given relation holds between geometry1 and geometry2.
- */
- public static boolean relate(Geometry geometry1, Geometry geometry2,
- SpatialReference spatialReference, String relation) {
- OperatorRelate op = (OperatorRelate) factory
- .getOperator(Operator.Type.Relate);
- boolean result = op.execute(geometry1, geometry2, spatialReference,
- relation, null);
- return result;
- }
-
- /**
- * Calculates the 2D planar distance between two geometries.
- *
- * See OperatorDistance.
- *
- * @param geometry1 Geometry.
- * @param geometry2 Geometry.
- * @param spatialReference The spatial reference of the geometries. This parameter is not
- * used and can be null.
- * @return The distance between the two geometries.
- */
- public static double distance(Geometry geometry1, Geometry geometry2,
- SpatialReference spatialReference) {
- OperatorDistance op = (OperatorDistance) factory
- .getOperator(Operator.Type.Distance);
- double result = op.execute(geometry1, geometry2, null);
- return result;
- }
-
- /**
- * Calculates the clipped geometry from a target geometry using an envelope.
- *
- * See OperatorClip.
- *
- * @param geometry The geometry to be clipped.
- * @param envelope The envelope used to clip.
- * @param spatialReference The spatial reference of the geometries.
- * @return The geometry created by clipping.
- */
- public static Geometry clip(Geometry geometry, Envelope envelope,
- SpatialReference spatialReference) {
- OperatorClip op = (OperatorClip) factory
- .getOperator(Operator.Type.Clip);
- Geometry result = op.execute(geometry, Envelope2D.construct(
- envelope.getXMin(), envelope.getYMin(), envelope.getXMax(),
- envelope.getYMax()), spatialReference, null);
- return result;
- }
-
- /**
- * Calculates the cut geometry from a target geometry using a polyline. For
- * Polylines, all left cuts will be grouped together in the first Geometry,
- * Right cuts and coincident cuts are grouped in the second Geometry, and
- * each undefined cut, along with any uncut parts, are output as separate
- * Polylines. For Polygons, all left cuts are grouped in the first Polygon,
- * all right cuts are in the second Polygon, and each undefined cut, along
- * with any left-over parts after cutting, are output as a separate Polygon.
- * If there were no cuts then the array will be empty. An undefined cut will
- * only be produced if a left cut or right cut was produced, and there was a
- * part left over after cutting or a cut is bounded to the left and right of
- * the cutter.
- *
- * See OperatorCut.
- *
- * @param cuttee The geometry to be cut.
- * @param cutter The polyline to cut the geometry.
- * @param spatialReference The spatial reference of the geometries.
- * @return An array of geometries created from cutting.
- */
- public static Geometry[] cut(Geometry cuttee, Polyline cutter,
- SpatialReference spatialReference) {
- if (cuttee == null || cutter == null)
- return null;
-
- OperatorCut op = (OperatorCut) factory.getOperator(Operator.Type.Cut);
- GeometryCursor cursor = op.execute(true, cuttee, cutter,
- spatialReference, null);
- ArrayList
- * See OperatorBuffer.
- *
- * @param geometries An array of geometries to be buffered.
- * @param spatialReference The spatial reference of the geometries.
- * @param distances The corresponding distances for the input geometries to be buffered.
- * @param toUnionResults TRUE if all geometries buffered at a given distance are to be unioned into a single polygon.
- * @return The buffer of the geometries.
- */
- public static Polygon[] buffer(Geometry[] geometries,
- SpatialReference spatialReference, double[] distances,
- boolean toUnionResults) {
- // initially assume distances are in unit of spatial reference
- double[] bufferDistances = distances;
-
- OperatorBuffer op = (OperatorBuffer) factory
- .getOperator(Operator.Type.Buffer);
-
- if (toUnionResults) {
- SimpleGeometryCursor inputGeometriesCursor = new SimpleGeometryCursor(
- geometries);
- GeometryCursor result = op.execute(inputGeometriesCursor,
- spatialReference, bufferDistances, toUnionResults, null);
-
- ArrayList
- * See OperatorBuffer
- *
- * @param geometry Geometry to be buffered.
- * @param spatialReference The spatial reference of the geometry.
- * @param distance The specified distance for buffer. Same units as the spatial reference.
- * @return The buffer polygon at the specified distances.
- */
- public static Polygon buffer(Geometry geometry,
- SpatialReference spatialReference, double distance) {
- double bufferDistance = distance;
-
- OperatorBuffer op = (OperatorBuffer) factory
- .getOperator(Operator.Type.Buffer);
- Geometry result = op.execute(geometry, spatialReference,
- bufferDistance, null);
- return (Polygon) result;
- }
-
- /**
- * Calculates the convex hull geometry.
- *
- * See OperatorConvexHull.
- *
- * @param geometry The input geometry.
- * @return Returns the convex hull.
- *
- * For a Point - returns the same point. For an Envelope -
- * returns the same envelope. For a MultiPoint - If the point
- * count is one, returns the same multipoint. If the point count
- * is two, returns a polyline of the points. Otherwise computes
- * and returns the convex hull polygon. For a Segment - returns a
- * polyline consisting of the segment. For a Polyline - If
- * consists of only one segment, returns the same polyline.
- * Otherwise computes and returns the convex hull polygon. For a
- * Polygon - If more than one path, or if the path isn't already
- * convex, computes and returns the convex hull polygon.
- * Otherwise returns the same polygon.
- */
- public static Geometry convexHull(Geometry geometry) {
- OperatorConvexHull op = (OperatorConvexHull) factory
- .getOperator(Operator.Type.ConvexHull);
- return op.execute(geometry, null);
- }
-
- /**
- * Calculates the convex hull.
- *
- * See OperatorConvexHull
- *
- * @param geometries The input geometry array.
- * @param b_merge Put true if you want the convex hull of all the geometries in
- * the array combined. Put false if you want the convex hull of
- * each geometry in the array individually.
- * @return Returns an array of convex hulls. If b_merge is true, the result
- * will be a one element array consisting of the merged convex hull.
- */
- public static Geometry[] convexHull(Geometry[] geometries, boolean b_merge) {
- OperatorConvexHull op = (OperatorConvexHull) factory
- .getOperator(Operator.Type.ConvexHull);
- SimpleGeometryCursor simple_cursor = new SimpleGeometryCursor(
- geometries);
- GeometryCursor cursor = op.execute(simple_cursor, b_merge, null);
-
- ArrayList
- * See OperatorProximity2D.
- *
- * @param inputPoint The point to find the nearest coordinate in the geometry for.
- * @param geometry The geometry to consider.
- * @return Proximity2DResult containing the nearest coordinate.
- */
- public static Proximity2DResult getNearestCoordinate(Geometry geometry,
- Point inputPoint, boolean bTestPolygonInterior) {
-
- OperatorProximity2D proximity = (OperatorProximity2D) factory
- .getOperator(com.esri.core.geometry.Operator.Type.Proximity2D);
- Proximity2DResult result = proximity.getNearestCoordinate(geometry,
- inputPoint, bTestPolygonInterior);
- return result;
- }
-
- /**
- * Finds nearest vertex on the geometry which is closed to the specified
- * point.
- *
- * See OperatorProximity2D.
- *
- * @param inputPoint The point to find the nearest vertex of the geometry for.
- * @param geometry The geometry to consider.
- * @return Proximity2DResult containing the nearest vertex.
- */
- public static Proximity2DResult getNearestVertex(Geometry geometry,
- Point inputPoint) {
- OperatorProximity2D proximity = (OperatorProximity2D) factory
- .getOperator(com.esri.core.geometry.Operator.Type.Proximity2D);
- Proximity2DResult result = proximity.getNearestVertex(geometry,
- inputPoint);
- return result;
- }
-
- /**
- * Finds all vertices in the given distance from the specified point, sorted
- * from the closest to the furthest.
- *
- * See OperatorProximity2D.
- *
- * @param inputPoint The point to start from.
- * @param geometry The geometry to consider.
- * @param searchRadius The search radius.
- * @param maxVertexCountToReturn The maximum number number of vertices to return.
- * @return Proximity2DResult containing the array of nearest vertices.
- */
- public static Proximity2DResult[] getNearestVertices(Geometry geometry,
- Point inputPoint, double searchRadius, int maxVertexCountToReturn) {
- OperatorProximity2D proximity = (OperatorProximity2D) factory
- .getOperator(com.esri.core.geometry.Operator.Type.Proximity2D);
-
- Proximity2DResult[] results = proximity.getNearestVertices(geometry,
- inputPoint, searchRadius, maxVertexCountToReturn);
-
- return results;
- }
-
- /**
- * Performs the simplify operation on the geometry.
- *
- * See OperatorSimplify and See OperatorSimplifyOGC.
- *
- * @param geometry The geometry to be simplified.
- * @param spatialReference The spatial reference of the geometry to be simplified.
- * @return The simplified geometry.
- */
- public static Geometry simplify(Geometry geometry,
- SpatialReference spatialReference) {
- OperatorSimplify op = (OperatorSimplify) factory
- .getOperator(Operator.Type.Simplify);
- Geometry result = op.execute(geometry, spatialReference, false, null);
- return result;
- }
-
- /**
- * Checks if the Geometry is simple.
- *
- * See OperatorSimplify.
- *
- * @param geometry The geometry to be checked.
- * @param spatialReference The spatial reference of the geometry.
- * @return TRUE if the geometry is simple.
- */
- static boolean isSimple(Geometry geometry, SpatialReference spatialReference) {
- OperatorSimplify op = (OperatorSimplify) factory
- .getOperator(Operator.Type.Simplify);
- boolean result = op.isSimpleAsFeature(geometry, spatialReference, null);
- return result;
- }
-
- /**
- * A geodesic distance is the shortest distance between any two points on the earth's surface when the earth's
- * surface is approximated by a spheroid. The function returns the shortest distance between two points on the
- * WGS84 spheroid.
- *
- * @param ptFrom The "from" point: long, lat in degrees.
- * @param ptTo The "to" point: long, lat in degrees.
- * @return The geodesic distance between two points in meters.
- */
- public static double geodesicDistanceOnWGS84(Point ptFrom, Point ptTo) {
- return SpatialReferenceImpl.geodesicDistanceOnWGS84Impl(ptFrom, ptTo);
- }
+ /**
+ * Exports a geometry to a string in WKT format.
+ *
+ * See OperatorExportToWkt.
+ *
+ * @param geometry The geometry to export. (null value is not allowed)
+ * @param exportFlags Use the {@link WktExportFlags} interface.
+ * @return A String containing the exported geometry in WKT format.
+ */
+ public static String geometryToWkt(Geometry geometry, int exportFlags) {
+ OperatorExportToWkt op = (OperatorExportToWkt) factory
+ .getOperator(Operator.Type.ExportToWkt);
+ return op.execute(exportFlags, geometry, null);
+ }
+
+ /**
+ * Constructs a new geometry by union an array of geometries. All inputs
+ * must be of the same type of geometries and share one spatial reference.
+ *
+ * See OperatorUnion.
+ *
+ * @param geometries The geometries to union.
+ * @param spatialReference The spatial reference of the geometries.
+ * @return The geometry object representing the resultant union.
+ */
+ public static Geometry union(Geometry[] geometries, SpatialReference spatialReference) {
+ OperatorUnion op = (OperatorUnion) factory.getOperator(Operator.Type.Union);
+
+ SimpleGeometryCursor inputGeometries = new SimpleGeometryCursor(geometries);
+ GeometryCursor result = op.execute(inputGeometries, spatialReference, null);
+ return result.next();
+ }
+
+ /**
+ * Creates the difference of two geometries. The dimension of geometry2 has
+ * to be equal to or greater than that of geometry1.
+ *
+ * See OperatorDifference.
+ *
+ * @param geometry1 The geometry being subtracted.
+ * @param substractor The geometry object to subtract from.
+ * @param spatialReference The spatial reference of the geometries.
+ * @return The geometry of the differences.
+ */
+ public static Geometry difference(Geometry geometry1, Geometry substractor,
+ SpatialReference spatialReference) {
+ OperatorDifference op = (OperatorDifference) factory.getOperator(Operator.Type.Difference);
+ Geometry result = op.execute(geometry1, substractor, spatialReference, null);
+ return result;
+ }
+
+ /**
+ * Creates the symmetric difference of two geometries.
+ *
+ * See OperatorSymmetricDifference.
+ *
+ * @param leftGeometry is one of the Geometry instances in the XOR operation.
+ * @param rightGeometry is one of the Geometry instances in the XOR operation.
+ * @param spatialReference The spatial reference of the geometries.
+ * @return Returns the result of the symmetric difference.
+ */
+ public static Geometry symmetricDifference(Geometry leftGeometry,
+ Geometry rightGeometry, SpatialReference spatialReference) {
+ OperatorSymmetricDifference op = (OperatorSymmetricDifference) factory
+ .getOperator(Operator.Type.SymmetricDifference);
+ Geometry result = op.execute(leftGeometry, rightGeometry,
+ spatialReference, null);
+ return result;
+ }
+
+ /**
+ * Indicates if two geometries are equal.
+ *
+ * See OperatorEquals.
+ *
+ * @param geometry1 Geometry.
+ * @param geometry2 Geometry.
+ * @param spatialReference The spatial reference of the geometries.
+ * @return TRUE if both geometry objects are equal.
+ */
+ public static boolean equals(Geometry geometry1, Geometry geometry2,
+ SpatialReference spatialReference) {
+ OperatorEquals op = (OperatorEquals) factory
+ .getOperator(Operator.Type.Equals);
+ boolean result = op.execute(geometry1, geometry2, spatialReference,
+ null);
+ return result;
+ }
+
+ /**
+ * See OperatorDisjoint.
+ */
+ public static boolean disjoint(Geometry geometry1, Geometry geometry2,
+ SpatialReference spatialReference) {
+ OperatorDisjoint op = (OperatorDisjoint) factory
+ .getOperator(Operator.Type.Disjoint);
+ boolean result = op.execute(geometry1, geometry2, spatialReference,
+ null);
+ return result;
+ }
+
+ /**
+ * Constructs the set-theoretic intersection between an array of geometries
+ * and another geometry.
+ *
+ * See OperatorIntersection (also for dimension specific intersection).
+ *
+ * @param inputGeometries An array of geometry objects.
+ * @param geometry The geometry object.
+ * @return Any array of geometry objects showing the intersection.
+ */
+ static Geometry[] intersect(Geometry[] inputGeometries, Geometry geometry,
+ SpatialReference spatialReference) {
+ OperatorIntersection op = (OperatorIntersection) factory
+ .getOperator(Operator.Type.Intersection);
+ SimpleGeometryCursor inputGeometriesCursor = new SimpleGeometryCursor(
+ inputGeometries);
+ SimpleGeometryCursor intersectorCursor = new SimpleGeometryCursor(
+ geometry);
+ GeometryCursor result = op.execute(inputGeometriesCursor,
+ intersectorCursor, spatialReference, null);
+
+ ArrayList
+ * See OperatorIntersection.
+ *
+ * @param geometry1 The first geometry.
+ * @param intersector The geometry to intersect the first geometry.
+ * @param spatialReference The spatial reference of the geometries.
+ * @return The geometry created through intersection.
+ */
+ public static Geometry intersect(Geometry geometry1, Geometry intersector,
+ SpatialReference spatialReference) {
+ OperatorIntersection op = (OperatorIntersection) factory.getOperator(Operator.Type.Intersection);
+ Geometry result = op.execute(geometry1, intersector, spatialReference, null);
+ return result;
+ }
+
+ /**
+ * Indicates if one geometry is within another geometry.
+ *
+ * See OperatorWithin.
+ *
+ * @param geometry1 The base geometry that is tested for within relationship to
+ * the other geometry.
+ * @param geometry2 The comparison geometry that is tested for the contains
+ * relationship to the other geometry.
+ * @param spatialReference The spatial reference of the geometries.
+ * @return TRUE if the first geometry is within the other geometry.
+ */
+ public static boolean within(Geometry geometry1, Geometry geometry2,
+ SpatialReference spatialReference) {
+ OperatorWithin op = (OperatorWithin) factory
+ .getOperator(Operator.Type.Within);
+ boolean result = op.execute(geometry1, geometry2, spatialReference,
+ null);
+ return result;
+ }
+
+ /**
+ * Indicates if one geometry contains another geometry.
+ *
+ * See OperatorContains.
+ *
+ * @param geometry1 The geometry that is tested for the contains relationship to
+ * the other geometry..
+ * @param geometry2 The geometry that is tested for within relationship to the
+ * other geometry.
+ * @param spatialReference The spatial reference of the geometries.
+ * @return TRUE if geometry1 contains geometry2.
+ */
+ public static boolean contains(Geometry geometry1, Geometry geometry2,
+ SpatialReference spatialReference) {
+ OperatorContains op = (OperatorContains) factory
+ .getOperator(Operator.Type.Contains);
+ boolean result = op.execute(geometry1, geometry2, spatialReference,
+ null);
+ return result;
+ }
+
+ /**
+ * Indicates if one geometry crosses another geometry.
+ *
+ * See OperatorCrosses.
+ *
+ * @param geometry1 The geometry to cross.
+ * @param geometry2 The geometry being crossed.
+ * @param spatialReference The spatial reference of the geometries.
+ * @return TRUE if geometry1 crosses geometry2.
+ */
+ public static boolean crosses(Geometry geometry1, Geometry geometry2,
+ SpatialReference spatialReference) {
+ OperatorCrosses op = (OperatorCrosses) factory
+ .getOperator(Operator.Type.Crosses);
+ boolean result = op.execute(geometry1, geometry2, spatialReference,
+ null);
+ return result;
+ }
+
+ /**
+ * Indicates if one geometry touches another geometry.
+ *
+ * See OperatorTouches.
+ *
+ * @param geometry1 The geometry to touch.
+ * @param geometry2 The geometry to be touched.
+ * @param spatialReference The spatial reference of the geometries.
+ * @return TRUE if geometry1 touches geometry2.
+ */
+ public static boolean touches(Geometry geometry1, Geometry geometry2,
+ SpatialReference spatialReference) {
+ OperatorTouches op = (OperatorTouches) factory
+ .getOperator(Operator.Type.Touches);
+ boolean result = op.execute(geometry1, geometry2, spatialReference,
+ null);
+ return result;
+ }
+
+ /**
+ * Indicates if one geometry overlaps another geometry.
+ *
+ * See OperatorOverlaps.
+ *
+ * @param geometry1 The geometry to overlap.
+ * @param geometry2 The geometry to be overlapped.
+ * @param spatialReference The spatial reference of the geometries.
+ * @return TRUE if geometry1 overlaps geometry2.
+ */
+ public static boolean overlaps(Geometry geometry1, Geometry geometry2,
+ SpatialReference spatialReference) {
+ OperatorOverlaps op = (OperatorOverlaps) factory
+ .getOperator(Operator.Type.Overlaps);
+ boolean result = op.execute(geometry1, geometry2, spatialReference,
+ null);
+ return result;
+ }
+
+ /**
+ * Indicates if the given relation holds for the two geometries.
+ *
+ * See OperatorRelate.
+ *
+ * @param geometry1 The first geometry for the relation.
+ * @param geometry2 The second geometry for the relation.
+ * @param spatialReference The spatial reference of the geometries.
+ * @param relation The DE-9IM relation.
+ * @return TRUE if the given relation holds between geometry1 and geometry2.
+ */
+ public static boolean relate(Geometry geometry1, Geometry geometry2,
+ SpatialReference spatialReference, String relation) {
+ OperatorRelate op = (OperatorRelate) factory
+ .getOperator(Operator.Type.Relate);
+ boolean result = op.execute(geometry1, geometry2, spatialReference,
+ relation, null);
+ return result;
+ }
+
+ /**
+ * Calculates the 2D planar distance between two geometries.
+ *
+ * See OperatorDistance.
+ *
+ * @param geometry1 Geometry.
+ * @param geometry2 Geometry.
+ * @param spatialReference The spatial reference of the geometries. This parameter is not
+ * used and can be null.
+ * @return The distance between the two geometries.
+ */
+ public static double distance(Geometry geometry1, Geometry geometry2,
+ SpatialReference spatialReference) {
+ OperatorDistance op = (OperatorDistance) factory
+ .getOperator(Operator.Type.Distance);
+ double result = op.execute(geometry1, geometry2, null);
+ return result;
+ }
+
+ /**
+ * Calculates the clipped geometry from a target geometry using an envelope.
+ *
+ * See OperatorClip.
+ *
+ * @param geometry The geometry to be clipped.
+ * @param envelope The envelope used to clip.
+ * @param spatialReference The spatial reference of the geometries.
+ * @return The geometry created by clipping.
+ */
+ public static Geometry clip(Geometry geometry, Envelope envelope,
+ SpatialReference spatialReference) {
+ OperatorClip op = (OperatorClip) factory
+ .getOperator(Operator.Type.Clip);
+ Geometry result = op.execute(geometry, Envelope2D.construct(
+ envelope.getXMin(), envelope.getYMin(), envelope.getXMax(),
+ envelope.getYMax()), spatialReference, null);
+ return result;
+ }
+
+ /**
+ * Calculates the cut geometry from a target geometry using a polyline. For
+ * Polylines, all left cuts will be grouped together in the first Geometry,
+ * Right cuts and coincident cuts are grouped in the second Geometry, and
+ * each undefined cut, along with any uncut parts, are output as separate
+ * Polylines. For Polygons, all left cuts are grouped in the first Polygon,
+ * all right cuts are in the second Polygon, and each undefined cut, along
+ * with any left-over parts after cutting, are output as a separate Polygon.
+ * If there were no cuts then the array will be empty. An undefined cut will
+ * only be produced if a left cut or right cut was produced, and there was a
+ * part left over after cutting or a cut is bounded to the left and right of
+ * the cutter.
+ *
+ * See OperatorCut.
+ *
+ * @param cuttee The geometry to be cut.
+ * @param cutter The polyline to cut the geometry.
+ * @param spatialReference The spatial reference of the geometries.
+ * @return An array of geometries created from cutting.
+ */
+ public static Geometry[] cut(Geometry cuttee, Polyline cutter,
+ SpatialReference spatialReference) {
+ if (cuttee == null || cutter == null)
+ return null;
+
+ OperatorCut op = (OperatorCut) factory.getOperator(Operator.Type.Cut);
+ GeometryCursor cursor = op.execute(true, cuttee, cutter,
+ spatialReference, null);
+ ArrayList
+ * See OperatorBuffer.
+ *
+ * @param geometries An array of geometries to be buffered.
+ * @param spatialReference The spatial reference of the geometries.
+ * @param distances The corresponding distances for the input geometries to be buffered.
+ * @param toUnionResults TRUE if all geometries buffered at a given distance are to be unioned into a single polygon.
+ * @return The buffer of the geometries.
+ */
+ public static Polygon[] buffer(Geometry[] geometries,
+ SpatialReference spatialReference, double[] distances,
+ boolean toUnionResults) {
+ // initially assume distances are in unit of spatial reference
+ double[] bufferDistances = distances;
+
+ OperatorBuffer op = (OperatorBuffer) factory
+ .getOperator(Operator.Type.Buffer);
+
+ if (toUnionResults) {
+ SimpleGeometryCursor inputGeometriesCursor = new SimpleGeometryCursor(
+ geometries);
+ GeometryCursor result = op.execute(inputGeometriesCursor,
+ spatialReference, bufferDistances, toUnionResults, null);
+
+ ArrayList
+ * See OperatorBuffer
+ *
+ * @param geometry Geometry to be buffered.
+ * @param spatialReference The spatial reference of the geometry.
+ * @param distance The specified distance for buffer. Same units as the spatial reference.
+ * @return The buffer polygon at the specified distances.
+ */
+ public static Polygon buffer(Geometry geometry,
+ SpatialReference spatialReference, double distance) {
+ double bufferDistance = distance;
+
+ OperatorBuffer op = (OperatorBuffer) factory
+ .getOperator(Operator.Type.Buffer);
+ Geometry result = op.execute(geometry, spatialReference,
+ bufferDistance, null);
+ return (Polygon) result;
+ }
+
+ /**
+ * Calculates the convex hull geometry.
+ *
+ * See OperatorConvexHull.
+ *
+ * @param geometry The input geometry.
+ * @return Returns the convex hull.
+ *
+ * For a Point - returns the same point. For an Envelope -
+ * returns the same envelope. For a MultiPoint - If the point
+ * count is one, returns the same multipoint. If the point count
+ * is two, returns a polyline of the points. Otherwise computes
+ * and returns the convex hull polygon. For a Segment - returns a
+ * polyline consisting of the segment. For a Polyline - If
+ * consists of only one segment, returns the same polyline.
+ * Otherwise computes and returns the convex hull polygon. For a
+ * Polygon - If more than one path, or if the path isn't already
+ * convex, computes and returns the convex hull polygon.
+ * Otherwise returns the same polygon.
+ */
+ public static Geometry convexHull(Geometry geometry) {
+ OperatorConvexHull op = (OperatorConvexHull) factory
+ .getOperator(Operator.Type.ConvexHull);
+ return op.execute(geometry, null);
+ }
+
+ /**
+ * Calculates the convex hull.
+ *
+ * See OperatorConvexHull
+ *
+ * @param geometries The input geometry array.
+ * @param b_merge Put true if you want the convex hull of all the geometries in
+ * the array combined. Put false if you want the convex hull of
+ * each geometry in the array individually.
+ * @return Returns an array of convex hulls. If b_merge is true, the result
+ * will be a one element array consisting of the merged convex hull.
+ */
+ public static Geometry[] convexHull(Geometry[] geometries, boolean b_merge) {
+ OperatorConvexHull op = (OperatorConvexHull) factory
+ .getOperator(Operator.Type.ConvexHull);
+ SimpleGeometryCursor simple_cursor = new SimpleGeometryCursor(
+ geometries);
+ GeometryCursor cursor = op.execute(simple_cursor, b_merge, null);
+
+ ArrayList
+ * See OperatorProximity2D.
+ *
+ * @param inputPoint The point to find the nearest coordinate in the geometry for.
+ * @param geometry The geometry to consider.
+ * @return Proximity2DResult containing the nearest coordinate.
+ */
+ public static Proximity2DResult getNearestCoordinate(Geometry geometry,
+ Point inputPoint, boolean bTestPolygonInterior) {
+
+ OperatorProximity2D proximity = (OperatorProximity2D) factory
+ .getOperator(com.esri.core.geometry.Operator.Type.Proximity2D);
+ Proximity2DResult result = proximity.getNearestCoordinate(geometry,
+ inputPoint, bTestPolygonInterior);
+ return result;
+ }
+
+ /**
+ * Finds nearest vertex on the geometry which is closed to the specified
+ * point.
+ *
+ * See OperatorProximity2D.
+ *
+ * @param inputPoint The point to find the nearest vertex of the geometry for.
+ * @param geometry The geometry to consider.
+ * @return Proximity2DResult containing the nearest vertex.
+ */
+ public static Proximity2DResult getNearestVertex(Geometry geometry,
+ Point inputPoint) {
+ OperatorProximity2D proximity = (OperatorProximity2D) factory
+ .getOperator(com.esri.core.geometry.Operator.Type.Proximity2D);
+ Proximity2DResult result = proximity.getNearestVertex(geometry,
+ inputPoint);
+ return result;
+ }
+
+ /**
+ * Finds all vertices in the given distance from the specified point, sorted
+ * from the closest to the furthest.
+ *
+ * See OperatorProximity2D.
+ *
+ * @param inputPoint The point to start from.
+ * @param geometry The geometry to consider.
+ * @param searchRadius The search radius.
+ * @param maxVertexCountToReturn The maximum number number of vertices to return.
+ * @return Proximity2DResult containing the array of nearest vertices.
+ */
+ public static Proximity2DResult[] getNearestVertices(Geometry geometry,
+ Point inputPoint, double searchRadius, int maxVertexCountToReturn) {
+ OperatorProximity2D proximity = (OperatorProximity2D) factory
+ .getOperator(com.esri.core.geometry.Operator.Type.Proximity2D);
+
+ Proximity2DResult[] results = proximity.getNearestVertices(geometry,
+ inputPoint, searchRadius, maxVertexCountToReturn);
+
+ return results;
+ }
+
+ /**
+ * Performs the simplify operation on the geometry.
+ *
+ * See OperatorSimplify and See OperatorSimplifyOGC.
+ *
+ * @param geometry The geometry to be simplified.
+ * @param spatialReference The spatial reference of the geometry to be simplified.
+ * @return The simplified geometry.
+ */
+ public static Geometry simplify(Geometry geometry,
+ SpatialReference spatialReference) {
+ OperatorSimplify op = (OperatorSimplify) factory
+ .getOperator(Operator.Type.Simplify);
+ Geometry result = op.execute(geometry, spatialReference, false, null);
+ return result;
+ }
+
+ /**
+ * Checks if the Geometry is simple.
+ *
+ * See OperatorSimplify.
+ *
+ * @param geometry The geometry to be checked.
+ * @param spatialReference The spatial reference of the geometry.
+ * @return TRUE if the geometry is simple.
+ */
+ static boolean isSimple(Geometry geometry, SpatialReference spatialReference) {
+ OperatorSimplify op = (OperatorSimplify) factory
+ .getOperator(Operator.Type.Simplify);
+ boolean result = op.isSimpleAsFeature(geometry, spatialReference, null);
+ return result;
+ }
+
+ /**
+ * A geodesic distance is the shortest distance between any two points on the earth's surface when the earth's
+ * surface is approximated by a spheroid. The function returns the shortest distance between two points on the
+ * WGS84 spheroid.
+ *
+ * @param ptFrom The "from" point: long, lat in degrees.
+ * @param ptTo The "to" point: long, lat in degrees.
+ * @return The geodesic distance between two points in meters.
+ */
+ public static double geodesicDistanceOnWGS84(Point ptFrom, Point ptTo) {
+ return SpatialReferenceImpl.geodesicDistanceOnWGS84Impl(ptFrom, ptTo);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/GeometryException.java b/src/main/java/com/esri/core/geometry/GeometryException.java
index 27c454fe..75498a73 100644
--- a/src/main/java/com/esri/core/geometry/GeometryException.java
+++ b/src/main/java/com/esri/core/geometry/GeometryException.java
@@ -30,18 +30,18 @@
*/
public class GeometryException extends RuntimeException {
- private static final long serialVersionUID = 1L;
-
- /**
- * Constructs a Geometry Exception with the given error string/message.
- *
- * @param str - The error string.
- */
- public GeometryException(String str) {
- super(str);
- }
-
- static GeometryException GeometryInternalError() {
- return new GeometryException("internal error");
- }
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs a Geometry Exception with the given error string/message.
+ *
+ * @param str - The error string.
+ */
+ public GeometryException(String str) {
+ super(str);
+ }
+
+ static GeometryException GeometryInternalError() {
+ return new GeometryException("internal error");
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/GeometrySerializer.java b/src/main/java/com/esri/core/geometry/GeometrySerializer.java
index 70f983f4..247a6746 100644
--- a/src/main/java/com/esri/core/geometry/GeometrySerializer.java
+++ b/src/main/java/com/esri/core/geometry/GeometrySerializer.java
@@ -30,89 +30,89 @@
//Left here for backward compatibility. Use GenericGeometrySerializer instead
@Deprecated
final class GeometrySerializer implements Serializable {
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 1L;
- static class BaseGeometryData implements Serializable {
- Geometry.Type geometryType;
- byte[] esriShape = null;
- }
+ static class BaseGeometryData implements Serializable {
+ Geometry.Type geometryType;
+ byte[] esriShape = null;
+ }
- static class MultiVertexData extends BaseGeometryData {
- int simpleFlag = 0;
- double tolerance = 0;
- }
+ static class MultiVertexData extends BaseGeometryData {
+ int simpleFlag = 0;
+ double tolerance = 0;
+ }
- static class MultiPathData extends MultiVertexData {
- boolean[] ogcFlags = null;
- }
+ static class MultiPathData extends MultiVertexData {
+ boolean[] ogcFlags = null;
+ }
- BaseGeometryData geometryData;
+ BaseGeometryData geometryData;
- Object readResolve() throws ObjectStreamException {
- Geometry geometry = null;
- try {
- geometry = GeometryEngine.geometryFromEsriShape(
- geometryData.esriShape, geometryData.geometryType);
- if (Geometry.isMultiVertex(geometry.getType().value())) {
- MultiVertexData mvd = (MultiVertexData) geometryData;
- MultiVertexGeometryImpl mvImpl = (MultiVertexGeometryImpl) geometry
- ._getImpl();
- if (!geometry.isEmpty()
- && Geometry.isMultiPath(geometry.getType().value())) {
- MultiPathData mpd = (MultiPathData) geometryData;
- MultiPathImpl mpImpl = (MultiPathImpl) geometry._getImpl();
- AttributeStreamOfInt8 pathFlags = mpImpl
- .getPathFlagsStreamRef();
- for (int i = 0, n = mpImpl.getPathCount(); i < n; i++) {
- if (mpd.ogcFlags[i])
- pathFlags.setBits(i,
- (byte) PathFlags.enumOGCStartPolygon);
- }
- }
- mvImpl.setIsSimple(mvd.simpleFlag, mvd.tolerance, false);
- }
+ Object readResolve() throws ObjectStreamException {
+ Geometry geometry = null;
+ try {
+ geometry = GeometryEngine.geometryFromEsriShape(
+ geometryData.esriShape, geometryData.geometryType);
+ if (Geometry.isMultiVertex(geometry.getType().value())) {
+ MultiVertexData mvd = (MultiVertexData) geometryData;
+ MultiVertexGeometryImpl mvImpl = (MultiVertexGeometryImpl) geometry
+ ._getImpl();
+ if (!geometry.isEmpty()
+ && Geometry.isMultiPath(geometry.getType().value())) {
+ MultiPathData mpd = (MultiPathData) geometryData;
+ MultiPathImpl mpImpl = (MultiPathImpl) geometry._getImpl();
+ AttributeStreamOfInt8 pathFlags = mpImpl
+ .getPathFlagsStreamRef();
+ for (int i = 0, n = mpImpl.getPathCount(); i < n; i++) {
+ if (mpd.ogcFlags[i])
+ pathFlags.setBits(i,
+ (byte) PathFlags.enumOGCStartPolygon);
+ }
+ }
+ mvImpl.setIsSimple(mvd.simpleFlag, mvd.tolerance, false);
+ }
- } catch (Exception ex) {
- throw new InvalidObjectException("Cannot read geometry from stream");
- }
- return geometry;
- }
+ } catch (Exception ex) {
+ throw new InvalidObjectException("Cannot read geometry from stream");
+ }
+ return geometry;
+ }
- public void setGeometryByValue(Geometry geometry)
- throws ObjectStreamException {
- try {
- if (Geometry.isMultiPath(geometry.getType().value())) {
- geometryData = new MultiPathData();
- } else if (Geometry.isMultiVertex(geometry.getType().value())) {
- geometryData = new MultiVertexData();
- } else {
- geometryData = new BaseGeometryData();
- }
- geometryData.esriShape = GeometryEngine
- .geometryToEsriShape(geometry);
- geometryData.geometryType = geometry.getType();
- if (Geometry.isMultiVertex(geometryData.geometryType.value())) {
- MultiVertexData mvd = (MultiVertexData) geometryData;
- MultiVertexGeometryImpl mvImpl = (MultiVertexGeometryImpl) geometry
- ._getImpl();
- mvd.tolerance = mvImpl.m_simpleTolerance;
- mvd.simpleFlag = mvImpl.getIsSimple(0);
- if (!geometry.isEmpty()
- && Geometry.isMultiPath(geometryData.geometryType
- .value())) {
- MultiPathData mpd = (MultiPathData) geometryData;
- MultiPathImpl mpImpl = (MultiPathImpl) geometry._getImpl();
- mpd.ogcFlags = new boolean[mpImpl.getPathCount()];
- AttributeStreamOfInt8 pathFlags = mpImpl
- .getPathFlagsStreamRef();
- for (int i = 0, n = mpImpl.getPathCount(); i < n; i++) {
- mpd.ogcFlags[i] = (pathFlags.read(i) & (byte) PathFlags.enumOGCStartPolygon) != 0;
- }
- }
+ public void setGeometryByValue(Geometry geometry)
+ throws ObjectStreamException {
+ try {
+ if (Geometry.isMultiPath(geometry.getType().value())) {
+ geometryData = new MultiPathData();
+ } else if (Geometry.isMultiVertex(geometry.getType().value())) {
+ geometryData = new MultiVertexData();
+ } else {
+ geometryData = new BaseGeometryData();
+ }
+ geometryData.esriShape = GeometryEngine
+ .geometryToEsriShape(geometry);
+ geometryData.geometryType = geometry.getType();
+ if (Geometry.isMultiVertex(geometryData.geometryType.value())) {
+ MultiVertexData mvd = (MultiVertexData) geometryData;
+ MultiVertexGeometryImpl mvImpl = (MultiVertexGeometryImpl) geometry
+ ._getImpl();
+ mvd.tolerance = mvImpl.m_simpleTolerance;
+ mvd.simpleFlag = mvImpl.getIsSimple(0);
+ if (!geometry.isEmpty()
+ && Geometry.isMultiPath(geometryData.geometryType
+ .value())) {
+ MultiPathData mpd = (MultiPathData) geometryData;
+ MultiPathImpl mpImpl = (MultiPathImpl) geometry._getImpl();
+ mpd.ogcFlags = new boolean[mpImpl.getPathCount()];
+ AttributeStreamOfInt8 pathFlags = mpImpl
+ .getPathFlagsStreamRef();
+ for (int i = 0, n = mpImpl.getPathCount(); i < n; i++) {
+ mpd.ogcFlags[i] = (pathFlags.read(i) & (byte) PathFlags.enumOGCStartPolygon) != 0;
+ }
+ }
- }
- } catch (Exception ex) {
- throw new InvalidObjectException("Cannot serialize this geometry");
- }
- }
+ }
+ } catch (Exception ex) {
+ throw new InvalidObjectException("Cannot serialize this geometry");
+ }
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/IndexHashTable.java b/src/main/java/com/esri/core/geometry/IndexHashTable.java
index 8ef6bfce..d95c9af4 100644
--- a/src/main/java/com/esri/core/geometry/IndexHashTable.java
+++ b/src/main/java/com/esri/core/geometry/IndexHashTable.java
@@ -26,252 +26,252 @@
import java.util.Arrays;
final class IndexHashTable {
- // The hash function abstract class that user need to define to use the
- // IndexHashTable.
- public static abstract class HashFunction {
- public abstract int getHash(int element);
-
- public abstract boolean equal(int element1, int element2);
-
- public abstract int getHash(Object elementDescriptor);
-
- public abstract boolean equal(Object elementDescriptor, int element);
- }
-
- int m_random;
- AttributeStreamOfInt32 m_hashBuckets;
- int[] m_bit_filter; //this is aimed to speedup the find
- //operation and allows to have less buckets.
- IndexMultiList m_lists;
- HashFunction m_hash;
-
- // Create hash table. size is the bin count in the table. The hashFunction
- // is the function to use.
- public IndexHashTable(int size, HashFunction hashFunction) {
- m_hashBuckets = new AttributeStreamOfInt32(size, nullNode());
- m_lists = new IndexMultiList();
- m_hash = hashFunction;
- m_bit_filter = new int[(size * 10 + 31) >> 5]; //10 times more bits than buckets
- }
-
- public void reserveElements(int capacity) {
- m_lists.reserveLists(Math.min(m_hashBuckets.size(), capacity));
- m_lists.reserveNodes(capacity);
- }
-
- // Adds new element to the hash table.
- public int addElement(int element, int hash) {
- int bit_bucket = hash % (m_bit_filter.length << 5);
- m_bit_filter[(bit_bucket >> 5)] |= (1 << (bit_bucket & 0x1F));
- int bucket = hash % m_hashBuckets.size();
- int list = m_hashBuckets.get(bucket);
- if (list == -1) {
- list = m_lists.createList();
- m_hashBuckets.set(bucket, list);
- }
- int node = m_lists.addElement(list, element);
- return node;
- }
-
- public int addElement(int element) {
- int hash = m_hash.getHash(element);
- int bit_bucket = hash % (m_bit_filter.length << 5);
- m_bit_filter[(bit_bucket >> 5)] |= (1 << (bit_bucket & 0x1F));
- int bucket = hash % m_hashBuckets.size();
- int list = m_hashBuckets.get(bucket);
- if (list == -1) {
- list = m_lists.createList();
- m_hashBuckets.set(bucket, list);
- }
- int node = m_lists.addElement(list, element);
- return node;
- }
-
- public void deleteElement(int element, int hash) {
- int bucket = hash % m_hashBuckets.size();
- int list = m_hashBuckets.get(bucket);
- if (list == -1)
- throw new IllegalArgumentException();
-
- int ptr = m_lists.getFirst(list);
- int prev = -1;
- while (ptr != -1) {
- int e = m_lists.getElement(ptr);
- int nextptr = m_lists.getNext(ptr);
- if (e == element) {
- m_lists.deleteElement(list, prev, ptr);
- if (m_lists.getFirst(list) == -1) {
- m_lists.deleteList(list);// do not keep empty lists
- m_hashBuckets.set(bucket, -1);
- }
- } else {
- prev = ptr;
- }
- ptr = nextptr;
- }
-
- }
-
- // Removes element from the hash table.
- public void deleteElement(int element) {
- int hash = m_hash.getHash(element);
- int bucket = hash % m_hashBuckets.size();
- int list = m_hashBuckets.get(bucket);
- if (list == -1)
- throw new IllegalArgumentException();
-
- int ptr = m_lists.getFirst(list);
- int prev = -1;
- while (ptr != -1) {
- int e = m_lists.getElement(ptr);
- int nextptr = m_lists.getNext(ptr);
- if (e == element) {
- m_lists.deleteElement(list, prev, ptr);
- if (m_lists.getFirst(list) == -1) {
- m_lists.deleteList(list);// do not keep empty lists
- m_hashBuckets.set(bucket, -1);
- }
- } else {
- prev = ptr;
- }
- ptr = nextptr;
- }
-
- }
-
- // Returns the first node in the hash table bucket defined by the given
- // hashValue.
- public int getFirstInBucket(int hashValue) {
- int bit_bucket = hashValue % (m_bit_filter.length << 5);
- if ((m_bit_filter[(bit_bucket >> 5)] & (1 << (bit_bucket & 0x1F))) == 0)
- return -1;
-
- int bucket = hashValue % m_hashBuckets.size();
- int list = m_hashBuckets.get(bucket);
- if (list == -1)
- return -1;
-
- return m_lists.getFirst(list);
-
- }
-
- // Returns next node in a bucket. Can be used together with GetFirstInBucket
- // only.
- public int getNextInBucket(int elementHandle) {
- return m_lists.getNext(elementHandle);
- }
-
- // Returns a node of the first element in the hash table, that is equal to
- // the given one.
- public int findNode(int element) {
- int hash = m_hash.getHash(element);
- int ptr = getFirstInBucket(hash);
- while (ptr != -1) {
- int e = m_lists.getElement(ptr);
- if (m_hash.equal(e, element)) {
- return ptr;
- }
- ptr = m_lists.getNext(ptr);
- }
-
- return -1;
-
- }
-
- // Returns a node to the first element in the hash table, that is equal to
- // the given element descriptor.
- public int findNode(Object elementDescriptor) {
- int hash = m_hash.getHash(elementDescriptor);
- int ptr = getFirstInBucket(hash);
- ;
- while (ptr != -1) {
- int e = m_lists.getElement(ptr);
- if (m_hash.equal(elementDescriptor, e)) {
- return ptr;
- }
- ptr = m_lists.getNext(ptr);
- }
-
- return -1;
-
- }
-
- // Gets next equal node.
- public int getNextNode(int elementHandle) {
- int element = m_lists.getElement(elementHandle);
- int ptr = m_lists.getNext(elementHandle);
- while (ptr != -1) {
- int e = m_lists.getElement(ptr);
- if (m_hash.equal(e, element)) {
- return ptr;
- }
- ptr = m_lists.getNext(ptr);
- }
-
- return -1;
-
- }
-
- // Removes a node.
- public void deleteNode(int node) {
- int element = getElement(node);
- int hash = m_hash.getHash(element);
- int bucket = hash % m_hashBuckets.size();
- int list = m_hashBuckets.get(bucket);
- if (list == -1)
- throw new IllegalArgumentException();
-
- int ptr = m_lists.getFirst(list);
- int prev = -1;
- while (ptr != -1) {
- if (ptr == node) {
- m_lists.deleteElement(list, prev, ptr);
- if (m_lists.getFirst(list) == -1) {
- m_lists.deleteList(list);// do not keep empty lists
- m_hashBuckets.set(bucket, -1);
- }
- return;
- }
- prev = ptr;
- ptr = m_lists.getNext(ptr);
- }
-
- throw new IllegalArgumentException();
-
- }
-
- // Returns a value of the element stored in the given node.
- public int getElement(int elementHandle) {
- return m_lists.getElement(elementHandle);
- }
-
- // Returns any existing element from the hash table. Throws if the table is
- // empty.
- public int getAnyElement() {
- return m_lists.getFirstElement(m_lists.getFirstList());
- }
-
- // Returns a node for any existing element from the hash table or NullNode
- // if the table is empty.
- public int getAnyNode() {
- return m_lists.getFirst(m_lists.getFirstList());
- }
-
- public static int nullNode() {
- return -1;
- }
-
- // Removes all elements from the hash table.
- public void clear() {
- Arrays.fill(m_bit_filter, 0);
- m_hashBuckets = new AttributeStreamOfInt32(m_hashBuckets.size(),
- nullNode());
- m_lists.clear();
-
- }
-
- // Returns the number of elements in the hash table
- public int size() {
- return m_lists.getNodeCount();
- }
+ // The hash function abstract class that user need to define to use the
+ // IndexHashTable.
+ public static abstract class HashFunction {
+ public abstract int getHash(int element);
+
+ public abstract boolean equal(int element1, int element2);
+
+ public abstract int getHash(Object elementDescriptor);
+
+ public abstract boolean equal(Object elementDescriptor, int element);
+ }
+
+ int m_random;
+ AttributeStreamOfInt32 m_hashBuckets;
+ int[] m_bit_filter; //this is aimed to speedup the find
+ //operation and allows to have less buckets.
+ IndexMultiList m_lists;
+ HashFunction m_hash;
+
+ // Create hash table. size is the bin count in the table. The hashFunction
+ // is the function to use.
+ public IndexHashTable(int size, HashFunction hashFunction) {
+ m_hashBuckets = new AttributeStreamOfInt32(size, nullNode());
+ m_lists = new IndexMultiList();
+ m_hash = hashFunction;
+ m_bit_filter = new int[(size * 10 + 31) >> 5]; //10 times more bits than buckets
+ }
+
+ public void reserveElements(int capacity) {
+ m_lists.reserveLists(Math.min(m_hashBuckets.size(), capacity));
+ m_lists.reserveNodes(capacity);
+ }
+
+ // Adds new element to the hash table.
+ public int addElement(int element, int hash) {
+ int bit_bucket = hash % (m_bit_filter.length << 5);
+ m_bit_filter[(bit_bucket >> 5)] |= (1 << (bit_bucket & 0x1F));
+ int bucket = hash % m_hashBuckets.size();
+ int list = m_hashBuckets.get(bucket);
+ if (list == -1) {
+ list = m_lists.createList();
+ m_hashBuckets.set(bucket, list);
+ }
+ int node = m_lists.addElement(list, element);
+ return node;
+ }
+
+ public int addElement(int element) {
+ int hash = m_hash.getHash(element);
+ int bit_bucket = hash % (m_bit_filter.length << 5);
+ m_bit_filter[(bit_bucket >> 5)] |= (1 << (bit_bucket & 0x1F));
+ int bucket = hash % m_hashBuckets.size();
+ int list = m_hashBuckets.get(bucket);
+ if (list == -1) {
+ list = m_lists.createList();
+ m_hashBuckets.set(bucket, list);
+ }
+ int node = m_lists.addElement(list, element);
+ return node;
+ }
+
+ public void deleteElement(int element, int hash) {
+ int bucket = hash % m_hashBuckets.size();
+ int list = m_hashBuckets.get(bucket);
+ if (list == -1)
+ throw new IllegalArgumentException();
+
+ int ptr = m_lists.getFirst(list);
+ int prev = -1;
+ while (ptr != -1) {
+ int e = m_lists.getElement(ptr);
+ int nextptr = m_lists.getNext(ptr);
+ if (e == element) {
+ m_lists.deleteElement(list, prev, ptr);
+ if (m_lists.getFirst(list) == -1) {
+ m_lists.deleteList(list);// do not keep empty lists
+ m_hashBuckets.set(bucket, -1);
+ }
+ } else {
+ prev = ptr;
+ }
+ ptr = nextptr;
+ }
+
+ }
+
+ // Removes element from the hash table.
+ public void deleteElement(int element) {
+ int hash = m_hash.getHash(element);
+ int bucket = hash % m_hashBuckets.size();
+ int list = m_hashBuckets.get(bucket);
+ if (list == -1)
+ throw new IllegalArgumentException();
+
+ int ptr = m_lists.getFirst(list);
+ int prev = -1;
+ while (ptr != -1) {
+ int e = m_lists.getElement(ptr);
+ int nextptr = m_lists.getNext(ptr);
+ if (e == element) {
+ m_lists.deleteElement(list, prev, ptr);
+ if (m_lists.getFirst(list) == -1) {
+ m_lists.deleteList(list);// do not keep empty lists
+ m_hashBuckets.set(bucket, -1);
+ }
+ } else {
+ prev = ptr;
+ }
+ ptr = nextptr;
+ }
+
+ }
+
+ // Returns the first node in the hash table bucket defined by the given
+ // hashValue.
+ public int getFirstInBucket(int hashValue) {
+ int bit_bucket = hashValue % (m_bit_filter.length << 5);
+ if ((m_bit_filter[(bit_bucket >> 5)] & (1 << (bit_bucket & 0x1F))) == 0)
+ return -1;
+
+ int bucket = hashValue % m_hashBuckets.size();
+ int list = m_hashBuckets.get(bucket);
+ if (list == -1)
+ return -1;
+
+ return m_lists.getFirst(list);
+
+ }
+
+ // Returns next node in a bucket. Can be used together with GetFirstInBucket
+ // only.
+ public int getNextInBucket(int elementHandle) {
+ return m_lists.getNext(elementHandle);
+ }
+
+ // Returns a node of the first element in the hash table, that is equal to
+ // the given one.
+ public int findNode(int element) {
+ int hash = m_hash.getHash(element);
+ int ptr = getFirstInBucket(hash);
+ while (ptr != -1) {
+ int e = m_lists.getElement(ptr);
+ if (m_hash.equal(e, element)) {
+ return ptr;
+ }
+ ptr = m_lists.getNext(ptr);
+ }
+
+ return -1;
+
+ }
+
+ // Returns a node to the first element in the hash table, that is equal to
+ // the given element descriptor.
+ public int findNode(Object elementDescriptor) {
+ int hash = m_hash.getHash(elementDescriptor);
+ int ptr = getFirstInBucket(hash);
+ ;
+ while (ptr != -1) {
+ int e = m_lists.getElement(ptr);
+ if (m_hash.equal(elementDescriptor, e)) {
+ return ptr;
+ }
+ ptr = m_lists.getNext(ptr);
+ }
+
+ return -1;
+
+ }
+
+ // Gets next equal node.
+ public int getNextNode(int elementHandle) {
+ int element = m_lists.getElement(elementHandle);
+ int ptr = m_lists.getNext(elementHandle);
+ while (ptr != -1) {
+ int e = m_lists.getElement(ptr);
+ if (m_hash.equal(e, element)) {
+ return ptr;
+ }
+ ptr = m_lists.getNext(ptr);
+ }
+
+ return -1;
+
+ }
+
+ // Removes a node.
+ public void deleteNode(int node) {
+ int element = getElement(node);
+ int hash = m_hash.getHash(element);
+ int bucket = hash % m_hashBuckets.size();
+ int list = m_hashBuckets.get(bucket);
+ if (list == -1)
+ throw new IllegalArgumentException();
+
+ int ptr = m_lists.getFirst(list);
+ int prev = -1;
+ while (ptr != -1) {
+ if (ptr == node) {
+ m_lists.deleteElement(list, prev, ptr);
+ if (m_lists.getFirst(list) == -1) {
+ m_lists.deleteList(list);// do not keep empty lists
+ m_hashBuckets.set(bucket, -1);
+ }
+ return;
+ }
+ prev = ptr;
+ ptr = m_lists.getNext(ptr);
+ }
+
+ throw new IllegalArgumentException();
+
+ }
+
+ // Returns a value of the element stored in the given node.
+ public int getElement(int elementHandle) {
+ return m_lists.getElement(elementHandle);
+ }
+
+ // Returns any existing element from the hash table. Throws if the table is
+ // empty.
+ public int getAnyElement() {
+ return m_lists.getFirstElement(m_lists.getFirstList());
+ }
+
+ // Returns a node for any existing element from the hash table or NullNode
+ // if the table is empty.
+ public int getAnyNode() {
+ return m_lists.getFirst(m_lists.getFirstList());
+ }
+
+ public static int nullNode() {
+ return -1;
+ }
+
+ // Removes all elements from the hash table.
+ public void clear() {
+ Arrays.fill(m_bit_filter, 0);
+ m_hashBuckets = new AttributeStreamOfInt32(m_hashBuckets.size(),
+ nullNode());
+ m_lists.clear();
+
+ }
+
+ // Returns the number of elements in the hash table
+ public int size() {
+ return m_lists.getNodeCount();
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/IndexMultiDCList.java b/src/main/java/com/esri/core/geometry/IndexMultiDCList.java
index 4b4afeae..0e75999a 100644
--- a/src/main/java/com/esri/core/geometry/IndexMultiDCList.java
+++ b/src/main/java/com/esri/core/geometry/IndexMultiDCList.java
@@ -25,286 +25,286 @@
class IndexMultiDCList {
- StridedIndexTypeCollection m_list_nodes; // stores lists and list elements.
- // Each list element is Index,
- // Prev, next.
- StridedIndexTypeCollection m_lists; // stores lists. Each list is Head,
- // Tail, PrevList, NextList, NodeCount,
- // ListData.
- int m_list_of_lists;
- boolean m_b_store_list_index_with_node;
-
- void freeNode_(int node) {
- m_list_nodes.deleteElement(node);
- }
-
- int newNode_() {
- int node = m_list_nodes.newElement();
- return node;
- }
-
- void freeList_(int list) {
- m_lists.deleteElement(list);
- }
-
- int newList_() {
- int list = m_lists.newElement();
- return list;
- }
-
- void setPrev_(int node, int prev) {
- m_list_nodes.setField(node, 1, prev);
- }
-
- void setNext_(int node, int next) {
- m_list_nodes.setField(node, 2, next);
- }
-
- void setData_(int node, int data) {
- m_list_nodes.setField(node, 0, data);
- }
-
- void setList_(int node, int list) {
- m_list_nodes.setField(node, 3, list);
- }
-
- void setListSize_(int list, int newsize) {
- m_lists.setField(list, 4, newsize);
- }
-
- void setNextList_(int list, int next) {
- m_lists.setField(list, 3, next);
- }
-
- void setPrevList_(int list, int prev) {
- m_lists.setField(list, 2, prev);
- }
-
- // Same as Index_multi_dc_list(true).
- IndexMultiDCList() {
- m_list_nodes = new StridedIndexTypeCollection(3);
- m_lists = new StridedIndexTypeCollection(6);
- m_b_store_list_index_with_node = false;
- m_list_of_lists = nullNode();
- }
-
- // When bStoreListIndexWithNode is true, the each node stores a pointer to
- // the list. Otherwise it does not.
- // The get_list() method cannot be used if bStoreListIndexWithNode is false.
- IndexMultiDCList(boolean b_store_list_index_with_node) {
- m_list_nodes = new StridedIndexTypeCollection(3);
- m_lists = new StridedIndexTypeCollection(6);
- m_b_store_list_index_with_node = false;
- m_list_of_lists = nullNode();
- }
-
- // Creates new list and returns it's handle.
- // listData is user's info associated with the list
- int createList(int listData) {
- int list = newList_();
- // m_lists.set_field(list, 0, null_node());//head
- // m_lists.set_field(list, 1, null_node());//tail
- // m_lists.set_field(list, 2, null_node());//prev list
- m_lists.setField(list, 3, m_list_of_lists); // next list
- m_lists.setField(list, 4, 0);// node count in the list
- m_lists.setField(list, 5, listData);
- if (m_list_of_lists != nullNode())
- setPrevList_(m_list_of_lists, list);
-
- m_list_of_lists = list;
- return list;
- }
-
- // Deletes a list and returns the index of the next list.
- int deleteList(int list) {
- clear(list);
- int prevList = m_lists.getField(list, 2);
- int nextList = m_lists.getField(list, 3);
- if (prevList != nullNode())
- setNextList_(prevList, nextList);
- else
- m_list_of_lists = nextList;
-
- if (nextList != nullNode())
- setPrevList_(nextList, prevList);
-
- freeList_(list);
- return nextList;
- }
-
- // Reserves memory for the given number of lists.
- void reserveLists(int listCount) {
- m_lists.setCapacity(listCount);
- }
-
- // returns user's data associated with the list
- int getListData(int list) {
- return m_lists.getField(list, 5);
- }
-
- // returns the list associated with the node_index. Do not use if list is
- // created with bStoreListIndexWithNode == false.
- int getList(int node_index) {
- assert (m_b_store_list_index_with_node);
- return m_list_nodes.getField(node_index, 3);
- }
-
- // sets the user data to the list
- void setListData(int list, int data) {
- m_lists.setField(list, 5, data);
- }
-
- // Adds element to a given list. The element is added to the end. Returns
- // the new
- int addElement(int list, int data) {
- return insertElement(list, -1, data);
- }
-
- // Inserts a new node before the given one .
- int insertElement(int list, int beforeNode, int data) {
- int node = newNode_();
- int prev = -1;
- if (beforeNode != nullNode()) {
- prev = getPrev(beforeNode);
- setPrev_(beforeNode, node);
- }
-
- setNext_(node, beforeNode);
- if (prev != nullNode())
- setNext_(prev, node);
-
- int head = m_lists.getField(list, 0);
-
- if (beforeNode == head)
- m_lists.setField(list, 0, node);
- if (beforeNode == nullNode()) {
- int tail = m_lists.getField(list, 1);
- setPrev_(node, tail);
- if (tail != -1)
- setNext_(tail, node);
-
- m_lists.setField(list, 1, node);
- }
-
- setData(node, data);
- setListSize_(list, getListSize(list) + 1);
-
- if (m_b_store_list_index_with_node)
- setList_(node, list);
-
- return node;
- }
-
- // Deletes a node from a list. Returns the next node after the deleted one.
- int deleteElement(int list, int node) {
- int prev = getPrev(node);
- int next = getNext(node);
- if (prev != nullNode())
- setNext_(prev, next);
- else
- m_lists.setField(list, 0, next);// change head
- if (next != nullNode())
- setPrev_(next, prev);
- else
- m_lists.setField(list, 1, prev);// change tail
-
- freeNode_(node);
- setListSize_(list, getListSize(list) - 1);
- return next;
- }
-
- // Reserves memory for the given number of nodes.
- void reserveNodes(int nodeCount) {
- m_list_nodes.setCapacity(nodeCount);
- }
-
- // Returns the data from the given list node.
- int getData(int node_index) {
- return m_list_nodes.getField(node_index, 0);
- }
-
- // Sets the data to the given list node.
- void setData(int node_index, int element) {
- m_list_nodes.setField(node_index, 0, element);
- }
-
- // Returns index of next node for the give node.
- int getNext(int node_index) {
- return m_list_nodes.getField(node_index, 2);
- }
-
- // Returns index of previous node for the give node.
- int getPrev(int node_index) {
- return m_list_nodes.getField(node_index, 1);
- }
-
- // Returns the first node in the list
- int getFirst(int list) {
- return m_lists.getField(list, 0);
- }
-
- // Returns the last node in the list
- int getLast(int list) {
- return m_lists.getField(list, 1);
- }
-
- // Check if the node is Null (does not exist)
- static int nullNode() {
- return -1;
- }
-
- // Clears all nodes and removes all lists.
- void clear() {
- for (int list = getFirstList(); list != -1; ) {
- list = deleteList(list);
- }
- }
-
- // Clears all nodes from the list.
- void clear(int list) {
- int last = getLast(list);
- while (last != nullNode()) {
- int n = last;
- last = getPrev(n);
- freeNode_(n);
- }
- m_lists.setField(list, 0, -1);
- m_lists.setField(list, 1, -1);
- setListSize_(list, 0);
- }
-
- // Returns True if the given list is empty.
- boolean isEmpty(int list) {
- return m_lists.getField(list, 0) == -1;
- }
-
- // Returns True if the multilist is empty
- boolean isEmpty() {
- return m_list_nodes.size() == 0;
- }
-
- // Returns node count in all lists
- int getNodeCount() {
- return m_list_nodes.size();
- }
-
- // returns the number of lists
- int getListCount() {
- return m_lists.size();
- }
-
- // Returns the node count in the given list
- int getListSize(int list) {
- return m_lists.getField(list, 4);
- }
-
- // returns the first list
- int getFirstList() {
- return m_list_of_lists;
- }
-
- // returns the next list
- int getNextList(int list) {
- return m_lists.getField(list, 3);
- }
+ StridedIndexTypeCollection m_list_nodes; // stores lists and list elements.
+ // Each list element is Index,
+ // Prev, next.
+ StridedIndexTypeCollection m_lists; // stores lists. Each list is Head,
+ // Tail, PrevList, NextList, NodeCount,
+ // ListData.
+ int m_list_of_lists;
+ boolean m_b_store_list_index_with_node;
+
+ void freeNode_(int node) {
+ m_list_nodes.deleteElement(node);
+ }
+
+ int newNode_() {
+ int node = m_list_nodes.newElement();
+ return node;
+ }
+
+ void freeList_(int list) {
+ m_lists.deleteElement(list);
+ }
+
+ int newList_() {
+ int list = m_lists.newElement();
+ return list;
+ }
+
+ void setPrev_(int node, int prev) {
+ m_list_nodes.setField(node, 1, prev);
+ }
+
+ void setNext_(int node, int next) {
+ m_list_nodes.setField(node, 2, next);
+ }
+
+ void setData_(int node, int data) {
+ m_list_nodes.setField(node, 0, data);
+ }
+
+ void setList_(int node, int list) {
+ m_list_nodes.setField(node, 3, list);
+ }
+
+ void setListSize_(int list, int newsize) {
+ m_lists.setField(list, 4, newsize);
+ }
+
+ void setNextList_(int list, int next) {
+ m_lists.setField(list, 3, next);
+ }
+
+ void setPrevList_(int list, int prev) {
+ m_lists.setField(list, 2, prev);
+ }
+
+ // Same as Index_multi_dc_list(true).
+ IndexMultiDCList() {
+ m_list_nodes = new StridedIndexTypeCollection(3);
+ m_lists = new StridedIndexTypeCollection(6);
+ m_b_store_list_index_with_node = false;
+ m_list_of_lists = nullNode();
+ }
+
+ // When bStoreListIndexWithNode is true, the each node stores a pointer to
+ // the list. Otherwise it does not.
+ // The get_list() method cannot be used if bStoreListIndexWithNode is false.
+ IndexMultiDCList(boolean b_store_list_index_with_node) {
+ m_list_nodes = new StridedIndexTypeCollection(3);
+ m_lists = new StridedIndexTypeCollection(6);
+ m_b_store_list_index_with_node = false;
+ m_list_of_lists = nullNode();
+ }
+
+ // Creates new list and returns it's handle.
+ // listData is user's info associated with the list
+ int createList(int listData) {
+ int list = newList_();
+ // m_lists.set_field(list, 0, null_node());//head
+ // m_lists.set_field(list, 1, null_node());//tail
+ // m_lists.set_field(list, 2, null_node());//prev list
+ m_lists.setField(list, 3, m_list_of_lists); // next list
+ m_lists.setField(list, 4, 0);// node count in the list
+ m_lists.setField(list, 5, listData);
+ if (m_list_of_lists != nullNode())
+ setPrevList_(m_list_of_lists, list);
+
+ m_list_of_lists = list;
+ return list;
+ }
+
+ // Deletes a list and returns the index of the next list.
+ int deleteList(int list) {
+ clear(list);
+ int prevList = m_lists.getField(list, 2);
+ int nextList = m_lists.getField(list, 3);
+ if (prevList != nullNode())
+ setNextList_(prevList, nextList);
+ else
+ m_list_of_lists = nextList;
+
+ if (nextList != nullNode())
+ setPrevList_(nextList, prevList);
+
+ freeList_(list);
+ return nextList;
+ }
+
+ // Reserves memory for the given number of lists.
+ void reserveLists(int listCount) {
+ m_lists.setCapacity(listCount);
+ }
+
+ // returns user's data associated with the list
+ int getListData(int list) {
+ return m_lists.getField(list, 5);
+ }
+
+ // returns the list associated with the node_index. Do not use if list is
+ // created with bStoreListIndexWithNode == false.
+ int getList(int node_index) {
+ assert (m_b_store_list_index_with_node);
+ return m_list_nodes.getField(node_index, 3);
+ }
+
+ // sets the user data to the list
+ void setListData(int list, int data) {
+ m_lists.setField(list, 5, data);
+ }
+
+ // Adds element to a given list. The element is added to the end. Returns
+ // the new
+ int addElement(int list, int data) {
+ return insertElement(list, -1, data);
+ }
+
+ // Inserts a new node before the given one .
+ int insertElement(int list, int beforeNode, int data) {
+ int node = newNode_();
+ int prev = -1;
+ if (beforeNode != nullNode()) {
+ prev = getPrev(beforeNode);
+ setPrev_(beforeNode, node);
+ }
+
+ setNext_(node, beforeNode);
+ if (prev != nullNode())
+ setNext_(prev, node);
+
+ int head = m_lists.getField(list, 0);
+
+ if (beforeNode == head)
+ m_lists.setField(list, 0, node);
+ if (beforeNode == nullNode()) {
+ int tail = m_lists.getField(list, 1);
+ setPrev_(node, tail);
+ if (tail != -1)
+ setNext_(tail, node);
+
+ m_lists.setField(list, 1, node);
+ }
+
+ setData(node, data);
+ setListSize_(list, getListSize(list) + 1);
+
+ if (m_b_store_list_index_with_node)
+ setList_(node, list);
+
+ return node;
+ }
+
+ // Deletes a node from a list. Returns the next node after the deleted one.
+ int deleteElement(int list, int node) {
+ int prev = getPrev(node);
+ int next = getNext(node);
+ if (prev != nullNode())
+ setNext_(prev, next);
+ else
+ m_lists.setField(list, 0, next);// change head
+ if (next != nullNode())
+ setPrev_(next, prev);
+ else
+ m_lists.setField(list, 1, prev);// change tail
+
+ freeNode_(node);
+ setListSize_(list, getListSize(list) - 1);
+ return next;
+ }
+
+ // Reserves memory for the given number of nodes.
+ void reserveNodes(int nodeCount) {
+ m_list_nodes.setCapacity(nodeCount);
+ }
+
+ // Returns the data from the given list node.
+ int getData(int node_index) {
+ return m_list_nodes.getField(node_index, 0);
+ }
+
+ // Sets the data to the given list node.
+ void setData(int node_index, int element) {
+ m_list_nodes.setField(node_index, 0, element);
+ }
+
+ // Returns index of next node for the give node.
+ int getNext(int node_index) {
+ return m_list_nodes.getField(node_index, 2);
+ }
+
+ // Returns index of previous node for the give node.
+ int getPrev(int node_index) {
+ return m_list_nodes.getField(node_index, 1);
+ }
+
+ // Returns the first node in the list
+ int getFirst(int list) {
+ return m_lists.getField(list, 0);
+ }
+
+ // Returns the last node in the list
+ int getLast(int list) {
+ return m_lists.getField(list, 1);
+ }
+
+ // Check if the node is Null (does not exist)
+ static int nullNode() {
+ return -1;
+ }
+
+ // Clears all nodes and removes all lists.
+ void clear() {
+ for (int list = getFirstList(); list != -1; ) {
+ list = deleteList(list);
+ }
+ }
+
+ // Clears all nodes from the list.
+ void clear(int list) {
+ int last = getLast(list);
+ while (last != nullNode()) {
+ int n = last;
+ last = getPrev(n);
+ freeNode_(n);
+ }
+ m_lists.setField(list, 0, -1);
+ m_lists.setField(list, 1, -1);
+ setListSize_(list, 0);
+ }
+
+ // Returns True if the given list is empty.
+ boolean isEmpty(int list) {
+ return m_lists.getField(list, 0) == -1;
+ }
+
+ // Returns True if the multilist is empty
+ boolean isEmpty() {
+ return m_list_nodes.size() == 0;
+ }
+
+ // Returns node count in all lists
+ int getNodeCount() {
+ return m_list_nodes.size();
+ }
+
+ // returns the number of lists
+ int getListCount() {
+ return m_lists.size();
+ }
+
+ // Returns the node count in the given list
+ int getListSize(int list) {
+ return m_lists.getField(list, 4);
+ }
+
+ // returns the first list
+ int getFirstList() {
+ return m_list_of_lists;
+ }
+
+ // returns the next list
+ int getNextList(int list) {
+ return m_lists.getField(list, 3);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/IndexMultiList.java b/src/main/java/com/esri/core/geometry/IndexMultiList.java
index 88c19f1c..5a881481 100644
--- a/src/main/java/com/esri/core/geometry/IndexMultiList.java
+++ b/src/main/java/com/esri/core/geometry/IndexMultiList.java
@@ -25,242 +25,242 @@
class IndexMultiList {
- StridedIndexTypeCollection m_listNodes; // stores lists and list elements.
- // Each list element is Index, next.
- StridedIndexTypeCollection m_lists; // stores lists. Each list is Head,
- // Tail, [PrevList, NextList].
- int m_list_of_lists;
- boolean m_b_allow_navigation_between_lists;// when False, get_first_list,
- // get_next_list return -1.
-
- void freeNode_(int node) {
- m_listNodes.deleteElement(node);
- }
-
- int newNode_() {
- int node = m_listNodes.newElement();
- return node;
- }
-
- void freeList_(int list) {
- m_lists.deleteElement(list);
- }
-
- int newList_() {
- int list = m_lists.newElement();
- return list;
- }
-
- // Same as Index_multi_list(true);
- IndexMultiList() {
- m_listNodes = new StridedIndexTypeCollection(2);
- m_lists = new StridedIndexTypeCollection(4);
- m_list_of_lists = nullNode();
- m_b_allow_navigation_between_lists = true;
- }
-
- // When b_allow_navigation_between_lists is False, the get_first_list and
- // get_next_list do not work.
- // There will be two Index_type elements per list and two Index_type
- // elements per list element
- // When b_allow_navigation_between_lists is True, the get_first_list and
- // get_next_list will work.
- // There will be four Index_type elements per list and two Index_type
- // elements per list element
- IndexMultiList(boolean b_allow_navigation_between_lists) {
- m_listNodes = new StridedIndexTypeCollection(2);
- m_lists = new StridedIndexTypeCollection(
- b_allow_navigation_between_lists ? 4 : 2);
- m_list_of_lists = nullNode();
- m_b_allow_navigation_between_lists = b_allow_navigation_between_lists;
- }
-
- // Creates new list and returns it's handle.
- int createList() {
- int node = newList_();
- if (m_b_allow_navigation_between_lists) {
- m_lists.setField(node, 3, m_list_of_lists);
- if (m_list_of_lists != nullNode())
- m_lists.setField(m_list_of_lists, 2, node);
- m_list_of_lists = node;
- }
-
- return node;
- }
-
- // Deletes a list.
- void deleteList(int list) {
- int ptr = getFirst(list);
- while (ptr != nullNode()) {
- int p = ptr;
- ptr = getNext(ptr);
- freeNode_(p);
- }
-
- if (m_b_allow_navigation_between_lists) {
- int prevList = m_lists.getField(list, 2);
- int nextList = m_lists.getField(list, 3);
- if (prevList != nullNode())
- m_lists.setField(prevList, 3, nextList);
- else
- m_list_of_lists = nextList;
-
- if (nextList != nullNode())
- m_lists.setField(nextList, 2, prevList);
- }
-
- freeList_(list);
- }
-
- // Reserves memory for the given number of lists.
- void reserveLists(int listCount) {
- m_lists.setCapacity(listCount);
- }
-
- // Adds element to a given list. The element is added to the end. Returns
- // the new
- int addElement(int list, int element) {
- int head = m_lists.getField(list, 0);
- int tail = m_lists.getField(list, 1);
- int node = newNode_();
- if (tail != nullNode()) {
- assert (head != nullNode());
- m_listNodes.setField(tail, 1, node);
- m_lists.setField(list, 1, node);
- } else {// empty list
- assert (head == nullNode());
- m_lists.setField(list, 0, node);
- m_lists.setField(list, 1, node);
- }
-
- m_listNodes.setField(node, 0, element);
- return node;
- }
-
- // Reserves memory for the given number of nodes.
- void reserveNodes(int nodeCount) {
- m_listNodes.setCapacity(nodeCount);
- }
-
- // Deletes a node from a list, given the previous node (previous node is
- // required, because the list is singly connected).
- void deleteElement(int list, int prevNode, int node) {
- if (prevNode != nullNode()) {
- assert (m_listNodes.getField(prevNode, 1) == node);
- m_listNodes.setField(prevNode, 1, m_listNodes.getField(node, 1));
- if (m_lists.getField(list, 1) == node)// deleting a tail
- {
- m_lists.setField(list, 1, prevNode);
- }
- } else {
- assert (m_lists.getField(list, 0) == node);
- m_lists.setField(list, 0, m_listNodes.getField(node, 1));
- if (m_lists.getField(list, 1) == node) {// removing last element
- assert (m_listNodes.getField(node, 1) == nullNode());
- m_lists.setField(list, 1, nullNode());
- }
- }
- freeNode_(node);
- }
-
- // Concatenates list1 and list2. The nodes of list2 are added to the end of
- // list1. The list2 index becomes invalid.
- // Returns list1.
- int concatenateLists(int list1, int list2) {
- int tailNode1 = m_lists.getField(list1, 1);
- int headNode2 = m_lists.getField(list2, 0);
- if (headNode2 != nullNode())// do not concatenate empty lists
- {
- if (tailNode1 != nullNode()) {
- // connect head of list2 to the tail of list1.
- m_listNodes.setField(tailNode1, 1, headNode2);
- // set the tail of the list1 to be the tail of list2.
- m_lists.setField(list1, 1, m_lists.getField(list2, 1));
- } else {// list1 is empty, while list2 is not.
- m_lists.setField(list1, 0, headNode2);
- m_lists.setField(list1, 1, m_lists.getField(list2, 1));
- }
- }
-
- if (m_b_allow_navigation_between_lists) {
- int prevList = m_lists.getField(list2, 2);
- int nextList = m_lists.getField(list2, 3);
- if (prevList != nullNode())
- m_lists.setField(prevList, 3, nextList);
- else
- m_list_of_lists = nextList;
-
- if (nextList != nullNode())
- m_lists.setField(nextList, 2, prevList);
- }
-
- freeList_(list2);
- return list1;
- }
-
- // Returns the data from the given list node.
- int getElement(int node_index) {
- return m_listNodes.getField(node_index, 0);
- }
-
- // Sets the data to the given list node.
- void setElement(int node_index, int element) {
- m_listNodes.setField(node_index, 0, element);
- }
-
- // Returns index of next node for the give node.
- int getNext(int node_index) {
- return m_listNodes.getField(node_index, 1);
- }
-
- // Returns the first node in the least
- int getFirst(int list) {
- return m_lists.getField(list, 0);
- }
-
- // Returns the element from the first node in the least. Equivalent to
- // get_element(get_first(list));
- int getFirstElement(int list) {
- int f = getFirst(list);
- return getElement(f);
- }
-
- // Check if the node is Null (does not exist)
- static int nullNode() {
- return -1;
- }
-
- // Clears all nodes and removes all lists. Frees the memory.
- void clear() {
- m_listNodes.deleteAll(true);
- m_lists.deleteAll(true);
- m_list_of_lists = nullNode();
- }
-
- // Returns True if the given list is empty.
- boolean isEmpty(int list) {
- return m_lists.getField(list, 0) == nullNode();
- }
-
- boolean isEmpty() {
- return m_listNodes.size() == 0;
- }
-
- int getNodeCount() {
- return m_listNodes.size();
- }
-
- int getListCount() {
- return m_lists.size();
- }
-
- int getFirstList() {
- assert (m_b_allow_navigation_between_lists);
- return m_list_of_lists;
- }
-
- int getNextList(int list) {
- assert (m_b_allow_navigation_between_lists);
- return m_lists.getField(list, 3);
- }
+ StridedIndexTypeCollection m_listNodes; // stores lists and list elements.
+ // Each list element is Index, next.
+ StridedIndexTypeCollection m_lists; // stores lists. Each list is Head,
+ // Tail, [PrevList, NextList].
+ int m_list_of_lists;
+ boolean m_b_allow_navigation_between_lists;// when False, get_first_list,
+ // get_next_list return -1.
+
+ void freeNode_(int node) {
+ m_listNodes.deleteElement(node);
+ }
+
+ int newNode_() {
+ int node = m_listNodes.newElement();
+ return node;
+ }
+
+ void freeList_(int list) {
+ m_lists.deleteElement(list);
+ }
+
+ int newList_() {
+ int list = m_lists.newElement();
+ return list;
+ }
+
+ // Same as Index_multi_list(true);
+ IndexMultiList() {
+ m_listNodes = new StridedIndexTypeCollection(2);
+ m_lists = new StridedIndexTypeCollection(4);
+ m_list_of_lists = nullNode();
+ m_b_allow_navigation_between_lists = true;
+ }
+
+ // When b_allow_navigation_between_lists is False, the get_first_list and
+ // get_next_list do not work.
+ // There will be two Index_type elements per list and two Index_type
+ // elements per list element
+ // When b_allow_navigation_between_lists is True, the get_first_list and
+ // get_next_list will work.
+ // There will be four Index_type elements per list and two Index_type
+ // elements per list element
+ IndexMultiList(boolean b_allow_navigation_between_lists) {
+ m_listNodes = new StridedIndexTypeCollection(2);
+ m_lists = new StridedIndexTypeCollection(
+ b_allow_navigation_between_lists ? 4 : 2);
+ m_list_of_lists = nullNode();
+ m_b_allow_navigation_between_lists = b_allow_navigation_between_lists;
+ }
+
+ // Creates new list and returns it's handle.
+ int createList() {
+ int node = newList_();
+ if (m_b_allow_navigation_between_lists) {
+ m_lists.setField(node, 3, m_list_of_lists);
+ if (m_list_of_lists != nullNode())
+ m_lists.setField(m_list_of_lists, 2, node);
+ m_list_of_lists = node;
+ }
+
+ return node;
+ }
+
+ // Deletes a list.
+ void deleteList(int list) {
+ int ptr = getFirst(list);
+ while (ptr != nullNode()) {
+ int p = ptr;
+ ptr = getNext(ptr);
+ freeNode_(p);
+ }
+
+ if (m_b_allow_navigation_between_lists) {
+ int prevList = m_lists.getField(list, 2);
+ int nextList = m_lists.getField(list, 3);
+ if (prevList != nullNode())
+ m_lists.setField(prevList, 3, nextList);
+ else
+ m_list_of_lists = nextList;
+
+ if (nextList != nullNode())
+ m_lists.setField(nextList, 2, prevList);
+ }
+
+ freeList_(list);
+ }
+
+ // Reserves memory for the given number of lists.
+ void reserveLists(int listCount) {
+ m_lists.setCapacity(listCount);
+ }
+
+ // Adds element to a given list. The element is added to the end. Returns
+ // the new
+ int addElement(int list, int element) {
+ int head = m_lists.getField(list, 0);
+ int tail = m_lists.getField(list, 1);
+ int node = newNode_();
+ if (tail != nullNode()) {
+ assert (head != nullNode());
+ m_listNodes.setField(tail, 1, node);
+ m_lists.setField(list, 1, node);
+ } else {// empty list
+ assert (head == nullNode());
+ m_lists.setField(list, 0, node);
+ m_lists.setField(list, 1, node);
+ }
+
+ m_listNodes.setField(node, 0, element);
+ return node;
+ }
+
+ // Reserves memory for the given number of nodes.
+ void reserveNodes(int nodeCount) {
+ m_listNodes.setCapacity(nodeCount);
+ }
+
+ // Deletes a node from a list, given the previous node (previous node is
+ // required, because the list is singly connected).
+ void deleteElement(int list, int prevNode, int node) {
+ if (prevNode != nullNode()) {
+ assert (m_listNodes.getField(prevNode, 1) == node);
+ m_listNodes.setField(prevNode, 1, m_listNodes.getField(node, 1));
+ if (m_lists.getField(list, 1) == node)// deleting a tail
+ {
+ m_lists.setField(list, 1, prevNode);
+ }
+ } else {
+ assert (m_lists.getField(list, 0) == node);
+ m_lists.setField(list, 0, m_listNodes.getField(node, 1));
+ if (m_lists.getField(list, 1) == node) {// removing last element
+ assert (m_listNodes.getField(node, 1) == nullNode());
+ m_lists.setField(list, 1, nullNode());
+ }
+ }
+ freeNode_(node);
+ }
+
+ // Concatenates list1 and list2. The nodes of list2 are added to the end of
+ // list1. The list2 index becomes invalid.
+ // Returns list1.
+ int concatenateLists(int list1, int list2) {
+ int tailNode1 = m_lists.getField(list1, 1);
+ int headNode2 = m_lists.getField(list2, 0);
+ if (headNode2 != nullNode())// do not concatenate empty lists
+ {
+ if (tailNode1 != nullNode()) {
+ // connect head of list2 to the tail of list1.
+ m_listNodes.setField(tailNode1, 1, headNode2);
+ // set the tail of the list1 to be the tail of list2.
+ m_lists.setField(list1, 1, m_lists.getField(list2, 1));
+ } else {// list1 is empty, while list2 is not.
+ m_lists.setField(list1, 0, headNode2);
+ m_lists.setField(list1, 1, m_lists.getField(list2, 1));
+ }
+ }
+
+ if (m_b_allow_navigation_between_lists) {
+ int prevList = m_lists.getField(list2, 2);
+ int nextList = m_lists.getField(list2, 3);
+ if (prevList != nullNode())
+ m_lists.setField(prevList, 3, nextList);
+ else
+ m_list_of_lists = nextList;
+
+ if (nextList != nullNode())
+ m_lists.setField(nextList, 2, prevList);
+ }
+
+ freeList_(list2);
+ return list1;
+ }
+
+ // Returns the data from the given list node.
+ int getElement(int node_index) {
+ return m_listNodes.getField(node_index, 0);
+ }
+
+ // Sets the data to the given list node.
+ void setElement(int node_index, int element) {
+ m_listNodes.setField(node_index, 0, element);
+ }
+
+ // Returns index of next node for the give node.
+ int getNext(int node_index) {
+ return m_listNodes.getField(node_index, 1);
+ }
+
+ // Returns the first node in the least
+ int getFirst(int list) {
+ return m_lists.getField(list, 0);
+ }
+
+ // Returns the element from the first node in the least. Equivalent to
+ // get_element(get_first(list));
+ int getFirstElement(int list) {
+ int f = getFirst(list);
+ return getElement(f);
+ }
+
+ // Check if the node is Null (does not exist)
+ static int nullNode() {
+ return -1;
+ }
+
+ // Clears all nodes and removes all lists. Frees the memory.
+ void clear() {
+ m_listNodes.deleteAll(true);
+ m_lists.deleteAll(true);
+ m_list_of_lists = nullNode();
+ }
+
+ // Returns True if the given list is empty.
+ boolean isEmpty(int list) {
+ return m_lists.getField(list, 0) == nullNode();
+ }
+
+ boolean isEmpty() {
+ return m_listNodes.size() == 0;
+ }
+
+ int getNodeCount() {
+ return m_listNodes.size();
+ }
+
+ int getListCount() {
+ return m_lists.size();
+ }
+
+ int getFirstList() {
+ assert (m_b_allow_navigation_between_lists);
+ return m_list_of_lists;
+ }
+
+ int getNextList(int list) {
+ assert (m_b_allow_navigation_between_lists);
+ return m_lists.getField(list, 3);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/InternalUtils.java b/src/main/java/com/esri/core/geometry/InternalUtils.java
index f7219126..1ce3082f 100644
--- a/src/main/java/com/esri/core/geometry/InternalUtils.java
+++ b/src/main/java/com/esri/core/geometry/InternalUtils.java
@@ -28,538 +28,538 @@
final class InternalUtils {
- // p0 and p1 have to be on left/right boundary of fullRange2D (since this
- // fuction can be called recursively, p0 or p1 can also be fullRange2D
- // corners)
- static int addPointsToArray(Point2D p0In, Point2D p1In,
- Point2D[] pointsArray, int idx, Envelope2D fullRange2D,
- boolean clockwise, double densifyDist)// PointerOfArrayOf(Point2D)
- // pointsArray, int idx,
- // Envelope2D fullRange2D,
- // boolean clockwise, double
- // densifyDist)
- {
- Point2D p0 = new Point2D();
- p0.setCoords(p0In);
- Point2D p1 = new Point2D();
- p1.setCoords(p1In);
- fullRange2D._snapToBoundary(p0);
- fullRange2D._snapToBoundary(p1);
- // //_ASSERT((p0.x == fullRange2D.xmin || p0.x == fullRange2D.xmax) &&
- // (p1.x == fullRange2D.xmin || p1.x == fullRange2D.xmax));
- double boundDist0 = fullRange2D._boundaryDistance(p0);
- double boundDist1 = fullRange2D._boundaryDistance(p1);
- if (boundDist1 == 0.0)
- boundDist1 = fullRange2D.getLength();
-
- if ((p0.x == p1.x || p0.y == p1.y
- && (p0.y == fullRange2D.ymin || p0.y == fullRange2D.ymax))
- && (boundDist1 > boundDist0) == clockwise) {
- Point2D delta = new Point2D();
- delta.setCoords(p1.x - p0.x, p1.y - p0.y);
- if (densifyDist != 0)// if (densifyDist)
- {
- long cPoints = (long) (delta._norm(0) / densifyDist);
- if (cPoints > 0) // if (cPoints)
- {
- delta.scale(1.0 / (cPoints + 1));
- for (long i = 0; i < cPoints; i++) {
- p0.add(delta);
- pointsArray[idx++].setCoords(p0.x, p0.y);// ARRAYELEMENT(pointsArray,
- // idx++).setCoords(p0.x,
- // p0.y);
- }
- }
- }
- } else {
- int side0 = fullRange2D._envelopeSide(p0);
- int side1 = fullRange2D._envelopeSide(p1);
- // create up to four corner points; the order depends on boolean
- // clockwise
- Point2D corner;
- int deltaSide = clockwise ? 1 : 3; // 3 is equivalent to -1
- do {
- side0 = (side0 + deltaSide) & 3;
- corner = fullRange2D.queryCorner(side0);
- if (densifyDist != 0)// if (densifyDist)
- {
- idx = addPointsToArray(p0, corner, pointsArray, idx,
- fullRange2D, clockwise, densifyDist);
- }
- pointsArray[idx++].setCoords(corner.x, corner.y);// ARRAYELEMENT(pointsArray,
- // idx++).setCoords(corner.x,
- // corner.y);
- p0 = corner;
- } while ((side0 & 3) != side1);
-
- if (densifyDist != 0)// if (densifyDist)
- idx = addPointsToArray(p0, p1, pointsArray, idx, fullRange2D,
- clockwise, densifyDist);
- }
-
- return idx;
- }
-
- void shiftPath(MultiPath inputGeom, int iPath, double shift) {
- MultiVertexGeometryImpl vertexGeometryImpl = (MultiVertexGeometryImpl) inputGeom
- ._getImpl();
- AttributeStreamOfDbl xyStream = (AttributeStreamOfDbl) vertexGeometryImpl
- .getAttributeStreamRef(VertexDescription.Semantics.POSITION);
-
- int i1 = inputGeom.getPathStart(iPath);
- int i2 = inputGeom.getPathEnd(iPath);
- Point2D pt = new Point2D();
-
- while (i1 < i2) {
- xyStream.read(i1, pt);
- pt.x += shift;
- xyStream.write(i1, pt);
- i1++;
- }
- }
-
- static double calculateToleranceFromGeometry(SpatialReference sr,
- Envelope2D env2D, boolean bConservative) {
- double gtolerance = env2D._calculateToleranceFromEnvelope();
- double stolerance = sr != null ? sr
- .getTolerance(VertexDescription.Semantics.POSITION) : 0;
- if (bConservative) {
- gtolerance *= 4;
- stolerance *= 1.1;
- }
- return Math.max(stolerance, gtolerance);
- }
-
- static double adjust_tolerance_for_TE_clustering(double tol) {
- return 2.0 * Math.sqrt(2.0) * tol;
- }
-
- static double adjust_tolerance_for_TE_cracking(double tol) {
- return Math.sqrt(2.0) * tol;
- }
-
- static double calculateToleranceFromGeometry(SpatialReference sr,
- Geometry geometry, boolean bConservative) {
- Envelope2D env2D = new Envelope2D();
- geometry.queryEnvelope2D(env2D);
- return calculateToleranceFromGeometry(sr, env2D, bConservative);
- }
-
- static double calculateZToleranceFromGeometry(SpatialReference sr,
- Geometry geometry, boolean bConservative) {
- Envelope1D env1D = geometry.queryInterval(
- VertexDescription.Semantics.Z, 0);
- double gtolerance = env1D._calculateToleranceFromEnvelope();
- double stolerance = sr != null ? sr
- .getTolerance(VertexDescription.Semantics.Z) : 0;
- if (bConservative) {
- gtolerance *= 4;
- stolerance *= 1.1;
- }
- return Math.max(stolerance, gtolerance);
- }
-
- double calculateZToleranceFromGeometry(SpatialReference sr,
- Geometry geometry) {
- Envelope1D env1D = geometry.queryInterval(
- VertexDescription.Semantics.Z, 0);
- double tolerance = env1D._calculateToleranceFromEnvelope();
- return Math
- .max(sr != null ? sr
- .getTolerance(VertexDescription.Semantics.Z) : 0,
- tolerance);
- }
-
- public static Envelope2D getMergedExtent(Geometry geom1, Envelope2D env2) {
- Envelope2D env1 = new Envelope2D();
- geom1.queryLooseEnvelope2D(env1);
- env1.merge(env2);
- return env1;
- }
-
- public static Envelope2D getMergedExtent(Geometry geom1, Geometry geom2) {
- Envelope2D env1 = new Envelope2D();
- geom1.queryLooseEnvelope2D(env1);
- Envelope2D env2 = new Envelope2D();
- geom2.queryLooseEnvelope2D(env2);
- env1.merge(env2);
- return env1;
- }
-
- public static Geometry createGeometry(int gt, VertexDescription vdIn) {
- VertexDescription vd = vdIn;
- if (vd == null)
- vd = VertexDescriptionDesignerImpl.getDefaultDescriptor2D();
- switch (gt) {
- case Geometry.GeometryType.Point:
- return new Point(vd);
- case Geometry.GeometryType.Line:
- return new Line(vd);
- // case enum_value2(Geometry, GeometryType, enumBezier):
- // break;
- // case enum_value2(Geometry, GeometryType, enumEllipticArc):
- // break;
- case Geometry.GeometryType.Envelope:
- return new Envelope(vd);
- case Geometry.GeometryType.MultiPoint:
- return new MultiPoint(vd);
- case Geometry.GeometryType.Polyline:
- return new Polyline(vd);
- case Geometry.GeometryType.Polygon:
- return new Polygon(vd);
- default:
- throw new GeometryException("invalid argument.");
- }
- }
-
- static boolean isClockwiseRing(MultiPathImpl polygon, int iring) {
- int high_point_index = polygon.getHighestPointIndex(iring);
- int path_start = polygon.getPathStart(iring);
- int path_end = polygon.getPathEnd(iring);
-
- Point2D q = polygon.getXY(high_point_index);
- Point2D p, r;
-
- if (high_point_index == path_start) {
- p = polygon.getXY(path_end - 1);
- r = polygon.getXY(path_start + 1);
- } else if (high_point_index == path_end - 1) {
- p = polygon.getXY(high_point_index - 1);
- r = polygon.getXY(path_start);
- } else {
- p = polygon.getXY(high_point_index - 1);
- r = polygon.getXY(high_point_index + 1);
- }
-
- int orientation = Point2D.orientationRobust(p, q, r);
-
- if (orientation == 0)
- return polygon.calculateRingArea2D(iring) > 0.0;
-
- return orientation == -1;
- }
-
- static QuadTreeImpl buildQuadTree(MultiPathImpl multipathImpl) {
- Envelope2D extent = new Envelope2D();
- multipathImpl.queryLooseEnvelope2D(extent);
- QuadTreeImpl quad_tree_impl = new QuadTreeImpl(extent, 8);
- int hint_index = -1;
- SegmentIteratorImpl seg_iter = multipathImpl.querySegmentIterator();
- Envelope2D boundingbox = new Envelope2D();
- boolean resized_extent = false;
-
- while (seg_iter.nextPath()) {
- while (seg_iter.hasNextSegment()) {
- Segment segment = seg_iter.nextSegment();
- int index = seg_iter.getStartPointIndex();
- segment.queryEnvelope2D(boundingbox);
- hint_index = quad_tree_impl.insert(index, boundingbox,
- hint_index);
-
- if (hint_index == -1) {
- if (resized_extent)
- throw GeometryException.GeometryInternalError();
-
- // resize extent
- multipathImpl.calculateEnvelope2D(extent, false);
- resized_extent = true;
- quad_tree_impl.reset(extent, 8);
- seg_iter.resetToFirstPath();
- break;
- }
- }
- }
-
- return quad_tree_impl;
- }
-
- static QuadTreeImpl buildQuadTree(MultiPathImpl multipathImpl,
- Envelope2D extentOfInterest) {
- Envelope2D extent = new Envelope2D();
- multipathImpl.queryLooseEnvelope2D(extent);
- QuadTreeImpl quad_tree_impl = new QuadTreeImpl(extent, 8);
- int hint_index = -1;
- Envelope2D boundingbox = new Envelope2D();
- SegmentIteratorImpl seg_iter = multipathImpl.querySegmentIterator();
-
- boolean resized_extent = false;
- while (seg_iter.nextPath()) {
- while (seg_iter.hasNextSegment()) {
- Segment segment = seg_iter.nextSegment();
- int index = seg_iter.getStartPointIndex();
- segment.queryEnvelope2D(boundingbox);
-
- if (boundingbox.isIntersecting(extentOfInterest)) {
- hint_index = quad_tree_impl.insert(index, boundingbox,
- hint_index);
-
- if (hint_index == -1) {
- if (resized_extent)
- throw GeometryException.GeometryInternalError();
-
- // resize extent
- multipathImpl.calculateEnvelope2D(extent, false);
- resized_extent = true;
- quad_tree_impl.reset(extent, 8);
- seg_iter.resetToFirstPath();
- break;
- }
- }
- }
- }
-
- return quad_tree_impl;
- }
-
- static QuadTreeImpl buildQuadTreeForPaths(MultiPathImpl multipathImpl) {
- Envelope2D extent = new Envelope2D();
- multipathImpl.queryLooseEnvelope2D(extent);
- if (extent.isEmpty())
- return null;
-
- QuadTreeImpl quad_tree_impl = new QuadTreeImpl(extent, 8);
- int hint_index = -1;
- Envelope2D boundingbox = new Envelope2D();
-
- boolean resized_extent = false;
- do {
- for (int ipath = 0, npaths = multipathImpl.getPathCount(); ipath < npaths; ipath++) {
- multipathImpl.queryPathEnvelope2D(ipath, boundingbox);
- hint_index = quad_tree_impl.insert(ipath, boundingbox, hint_index);
-
- if (hint_index == -1) {
- if (resized_extent)
- throw GeometryException.GeometryInternalError();
-
- //This is usually happens because esri shape buffer contains geometry extent which is slightly different from the true extent.
- //Recalculate extent
- multipathImpl.calculateEnvelope2D(extent, false);
- resized_extent = true;
- quad_tree_impl.reset(extent, 8);
- break; //break the for loop
- } else {
- resized_extent = false;
- }
- }
-
- } while (resized_extent);
-
- return quad_tree_impl;
- }
-
- static QuadTreeImpl buildQuadTree(MultiPointImpl multipointImpl) {
- Envelope2D extent = new Envelope2D();
- multipointImpl.queryLooseEnvelope2D(extent);
- QuadTreeImpl quad_tree_impl = new QuadTreeImpl(extent, 8);
-
- Point2D pt = new Point2D();
- Envelope2D boundingbox = new Envelope2D();
- boolean resized_extent = false;
- for (int i = 0; i < multipointImpl.getPointCount(); i++) {
- multipointImpl.getXY(i, pt);
- boundingbox.setCoords(pt);
- int element_handle = quad_tree_impl.insert(i, boundingbox);
-
- if (element_handle == -1) {
- if (resized_extent)
- throw GeometryException.GeometryInternalError();
-
- // resize extent
- multipointImpl.calculateEnvelope2D(extent, false);
- resized_extent = true;
- quad_tree_impl.reset(extent, 8);
- i = -1; // resets the for-loop
- continue;
- }
- }
-
- return quad_tree_impl;
- }
-
- static QuadTreeImpl buildQuadTree(MultiPointImpl multipointImpl,
- Envelope2D extentOfInterest) {
- QuadTreeImpl quad_tree_impl = new QuadTreeImpl(extentOfInterest, 8);
- Point2D pt = new Point2D();
- boolean resized_extent = false;
- Envelope2D boundingbox = new Envelope2D();
- for (int i = 0; i < multipointImpl.getPointCount(); i++) {
- multipointImpl.getXY(i, pt);
-
- if (!extentOfInterest.contains(pt))
- continue;
-
- boundingbox.setCoords(pt);
- int element_handle = quad_tree_impl.insert(i, boundingbox);
-
- if (element_handle == -1) {
- if (resized_extent)
- throw GeometryException.GeometryInternalError();
-
- // resize extent
- resized_extent = true;
- Envelope2D extent = new Envelope2D();
- multipointImpl.calculateEnvelope2D(extent, false);
- quad_tree_impl.reset(extent, 8);
- i = -1; // resets the for-loop
- continue;
- }
- }
-
- return quad_tree_impl;
- }
-
- static Envelope2DIntersectorImpl getEnvelope2DIntersector(
- MultiPathImpl multipathImplA, MultiPathImpl multipathImplB,
- double tolerance) {
- Envelope2D env_a = new Envelope2D(), env_b = new Envelope2D();
- multipathImplA.queryLooseEnvelope2D(env_a);
- multipathImplB.queryLooseEnvelope2D(env_b);
- env_a.inflate(tolerance, tolerance);
- env_b.inflate(tolerance, tolerance);
-
- Envelope2D envInter = new Envelope2D();
- envInter.setCoords(env_a);
- envInter.intersect(env_b);
-
- SegmentIteratorImpl segIterA = multipathImplA.querySegmentIterator();
- SegmentIteratorImpl segIterB = multipathImplB.querySegmentIterator();
-
- Envelope2DIntersectorImpl intersector = new Envelope2DIntersectorImpl();
- intersector.setTolerance(tolerance);
-
- boolean b_found_red = false;
- intersector.startRedConstruction();
- while (segIterA.nextPath()) {
- while (segIterA.hasNextSegment()) {
- Segment segmentA = segIterA.nextSegment();
- segmentA.queryEnvelope2D(env_a);
-
- if (!env_a.isIntersecting(envInter))
- continue;
-
- b_found_red = true;
- Envelope2D env = new Envelope2D();
- env.setCoords(env_a);
- intersector.addRedEnvelope(segIterA.getStartPointIndex(), env);
- }
- }
- intersector.endRedConstruction();
-
- if (!b_found_red)
- return null;
-
- boolean b_found_blue = false;
- intersector.startBlueConstruction();
- while (segIterB.nextPath()) {
- while (segIterB.hasNextSegment()) {
- Segment segmentB = segIterB.nextSegment();
- segmentB.queryEnvelope2D(env_b);
-
- if (!env_b.isIntersecting(envInter))
- continue;
-
- b_found_blue = true;
- Envelope2D env = new Envelope2D();
- env.setCoords(env_b);
- intersector.addBlueEnvelope(segIterB.getStartPointIndex(), env);
- }
- }
- intersector.endBlueConstruction();
-
- if (!b_found_blue)
- return null;
-
- return intersector;
- }
-
- static Envelope2DIntersectorImpl getEnvelope2DIntersectorForParts(
- MultiPathImpl multipathImplA, MultiPathImpl multipathImplB,
- double tolerance, boolean bExteriorOnlyA, boolean bExteriorOnlyB) {
- int type_a = multipathImplA.getType().value();
- int type_b = multipathImplB.getType().value();
-
- Envelope2D env_a = new Envelope2D(), env_b = new Envelope2D();
- multipathImplA.queryLooseEnvelope2D(env_a);
- multipathImplB.queryLooseEnvelope2D(env_b);
- env_a.inflate(tolerance, tolerance);
- env_b.inflate(tolerance, tolerance);
-
- Envelope2D envInter = new Envelope2D();
- envInter.setCoords(env_a);
- envInter.intersect(env_b);
-
- Envelope2DIntersectorImpl intersector = new Envelope2DIntersectorImpl();
- intersector.setTolerance(tolerance);
-
- boolean b_found_red = false;
- intersector.startRedConstruction();
- for (int ipath_a = 0, npaths = multipathImplA.getPathCount(); ipath_a < npaths; ipath_a++) {
- if (bExteriorOnlyA && type_a == Geometry.GeometryType.Polygon && !multipathImplA.isExteriorRing(ipath_a))
- continue;
-
- multipathImplA.queryPathEnvelope2D(ipath_a, env_a);
-
- if (!env_a.isIntersecting(envInter))
- continue;
-
- b_found_red = true;
- intersector.addRedEnvelope(ipath_a, env_a);
- }
- intersector.endRedConstruction();
-
- if (!b_found_red)
- return null;
-
- boolean b_found_blue = false;
- intersector.startBlueConstruction();
- for (int ipath_b = 0, npaths = multipathImplB.getPathCount(); ipath_b < npaths; ipath_b++) {
- if (bExteriorOnlyB && type_b == Geometry.GeometryType.Polygon && !multipathImplB.isExteriorRing(ipath_b))
- continue;
-
- multipathImplB.queryPathEnvelope2D(ipath_b, env_b);
-
- if (!env_b.isIntersecting(envInter))
- continue;
-
- b_found_blue = true;
- intersector.addBlueEnvelope(ipath_b, env_b);
- }
- intersector.endBlueConstruction();
-
- if (!b_found_blue)
- return null;
-
- return intersector;
- }
-
- static boolean isWeakSimple(MultiVertexGeometry geom, double tol) {
- return ((MultiVertexGeometryImpl) geom._getImpl()).getIsSimple(tol) > 0;
- }
-
- static QuadTree buildQuadTreeForOnePath(MultiPathImpl multipathImpl, int path) {
- Envelope2D extent = new Envelope2D();
- multipathImpl.queryLoosePathEnvelope2D(path, extent);
- QuadTree quad_tree = new QuadTree(extent, 8);
- int hint_index = -1;
- Envelope2D boundingbox = new Envelope2D();
- SegmentIteratorImpl seg_iter = multipathImpl.querySegmentIterator();
-
- seg_iter.resetToPath(path);
- if (seg_iter.nextPath()) {
- while (seg_iter.hasNextSegment()) {
- Segment segment = seg_iter.nextSegment();
- int index = seg_iter.getStartPointIndex();
- segment.queryLooseEnvelope2D(boundingbox);
- hint_index = quad_tree.insert(index, boundingbox, hint_index);
-
- if (hint_index == -1) {
- throw new GeometryException("internal error");
- }
- }
- }
-
- return quad_tree;
- }
+ // p0 and p1 have to be on left/right boundary of fullRange2D (since this
+ // fuction can be called recursively, p0 or p1 can also be fullRange2D
+ // corners)
+ static int addPointsToArray(Point2D p0In, Point2D p1In,
+ Point2D[] pointsArray, int idx, Envelope2D fullRange2D,
+ boolean clockwise, double densifyDist)// PointerOfArrayOf(Point2D)
+ // pointsArray, int idx,
+ // Envelope2D fullRange2D,
+ // boolean clockwise, double
+ // densifyDist)
+ {
+ Point2D p0 = new Point2D();
+ p0.setCoords(p0In);
+ Point2D p1 = new Point2D();
+ p1.setCoords(p1In);
+ fullRange2D._snapToBoundary(p0);
+ fullRange2D._snapToBoundary(p1);
+ // //_ASSERT((p0.x == fullRange2D.xmin || p0.x == fullRange2D.xmax) &&
+ // (p1.x == fullRange2D.xmin || p1.x == fullRange2D.xmax));
+ double boundDist0 = fullRange2D._boundaryDistance(p0);
+ double boundDist1 = fullRange2D._boundaryDistance(p1);
+ if (boundDist1 == 0.0)
+ boundDist1 = fullRange2D.getLength();
+
+ if ((p0.x == p1.x || p0.y == p1.y
+ && (p0.y == fullRange2D.ymin || p0.y == fullRange2D.ymax))
+ && (boundDist1 > boundDist0) == clockwise) {
+ Point2D delta = new Point2D();
+ delta.setCoords(p1.x - p0.x, p1.y - p0.y);
+ if (densifyDist != 0)// if (densifyDist)
+ {
+ long cPoints = (long) (delta._norm(0) / densifyDist);
+ if (cPoints > 0) // if (cPoints)
+ {
+ delta.scale(1.0 / (cPoints + 1));
+ for (long i = 0; i < cPoints; i++) {
+ p0.add(delta);
+ pointsArray[idx++].setCoords(p0.x, p0.y);// ARRAYELEMENT(pointsArray,
+ // idx++).setCoords(p0.x,
+ // p0.y);
+ }
+ }
+ }
+ } else {
+ int side0 = fullRange2D._envelopeSide(p0);
+ int side1 = fullRange2D._envelopeSide(p1);
+ // create up to four corner points; the order depends on boolean
+ // clockwise
+ Point2D corner;
+ int deltaSide = clockwise ? 1 : 3; // 3 is equivalent to -1
+ do {
+ side0 = (side0 + deltaSide) & 3;
+ corner = fullRange2D.queryCorner(side0);
+ if (densifyDist != 0)// if (densifyDist)
+ {
+ idx = addPointsToArray(p0, corner, pointsArray, idx,
+ fullRange2D, clockwise, densifyDist);
+ }
+ pointsArray[idx++].setCoords(corner.x, corner.y);// ARRAYELEMENT(pointsArray,
+ // idx++).setCoords(corner.x,
+ // corner.y);
+ p0 = corner;
+ } while ((side0 & 3) != side1);
+
+ if (densifyDist != 0)// if (densifyDist)
+ idx = addPointsToArray(p0, p1, pointsArray, idx, fullRange2D,
+ clockwise, densifyDist);
+ }
+
+ return idx;
+ }
+
+ void shiftPath(MultiPath inputGeom, int iPath, double shift) {
+ MultiVertexGeometryImpl vertexGeometryImpl = (MultiVertexGeometryImpl) inputGeom
+ ._getImpl();
+ AttributeStreamOfDbl xyStream = (AttributeStreamOfDbl) vertexGeometryImpl
+ .getAttributeStreamRef(VertexDescription.Semantics.POSITION);
+
+ int i1 = inputGeom.getPathStart(iPath);
+ int i2 = inputGeom.getPathEnd(iPath);
+ Point2D pt = new Point2D();
+
+ while (i1 < i2) {
+ xyStream.read(i1, pt);
+ pt.x += shift;
+ xyStream.write(i1, pt);
+ i1++;
+ }
+ }
+
+ static double calculateToleranceFromGeometry(SpatialReference sr,
+ Envelope2D env2D, boolean bConservative) {
+ double gtolerance = env2D._calculateToleranceFromEnvelope();
+ double stolerance = sr != null ? sr
+ .getTolerance(VertexDescription.Semantics.POSITION) : 0;
+ if (bConservative) {
+ gtolerance *= 4;
+ stolerance *= 1.1;
+ }
+ return Math.max(stolerance, gtolerance);
+ }
+
+ static double adjust_tolerance_for_TE_clustering(double tol) {
+ return 2.0 * Math.sqrt(2.0) * tol;
+ }
+
+ static double adjust_tolerance_for_TE_cracking(double tol) {
+ return Math.sqrt(2.0) * tol;
+ }
+
+ static double calculateToleranceFromGeometry(SpatialReference sr,
+ Geometry geometry, boolean bConservative) {
+ Envelope2D env2D = new Envelope2D();
+ geometry.queryEnvelope2D(env2D);
+ return calculateToleranceFromGeometry(sr, env2D, bConservative);
+ }
+
+ static double calculateZToleranceFromGeometry(SpatialReference sr,
+ Geometry geometry, boolean bConservative) {
+ Envelope1D env1D = geometry.queryInterval(
+ VertexDescription.Semantics.Z, 0);
+ double gtolerance = env1D._calculateToleranceFromEnvelope();
+ double stolerance = sr != null ? sr
+ .getTolerance(VertexDescription.Semantics.Z) : 0;
+ if (bConservative) {
+ gtolerance *= 4;
+ stolerance *= 1.1;
+ }
+ return Math.max(stolerance, gtolerance);
+ }
+
+ double calculateZToleranceFromGeometry(SpatialReference sr,
+ Geometry geometry) {
+ Envelope1D env1D = geometry.queryInterval(
+ VertexDescription.Semantics.Z, 0);
+ double tolerance = env1D._calculateToleranceFromEnvelope();
+ return Math
+ .max(sr != null ? sr
+ .getTolerance(VertexDescription.Semantics.Z) : 0,
+ tolerance);
+ }
+
+ public static Envelope2D getMergedExtent(Geometry geom1, Envelope2D env2) {
+ Envelope2D env1 = new Envelope2D();
+ geom1.queryLooseEnvelope2D(env1);
+ env1.merge(env2);
+ return env1;
+ }
+
+ public static Envelope2D getMergedExtent(Geometry geom1, Geometry geom2) {
+ Envelope2D env1 = new Envelope2D();
+ geom1.queryLooseEnvelope2D(env1);
+ Envelope2D env2 = new Envelope2D();
+ geom2.queryLooseEnvelope2D(env2);
+ env1.merge(env2);
+ return env1;
+ }
+
+ public static Geometry createGeometry(int gt, VertexDescription vdIn) {
+ VertexDescription vd = vdIn;
+ if (vd == null)
+ vd = VertexDescriptionDesignerImpl.getDefaultDescriptor2D();
+ switch (gt) {
+ case Geometry.GeometryType.Point:
+ return new Point(vd);
+ case Geometry.GeometryType.Line:
+ return new Line(vd);
+ // case enum_value2(Geometry, GeometryType, enumBezier):
+ // break;
+ // case enum_value2(Geometry, GeometryType, enumEllipticArc):
+ // break;
+ case Geometry.GeometryType.Envelope:
+ return new Envelope(vd);
+ case Geometry.GeometryType.MultiPoint:
+ return new MultiPoint(vd);
+ case Geometry.GeometryType.Polyline:
+ return new Polyline(vd);
+ case Geometry.GeometryType.Polygon:
+ return new Polygon(vd);
+ default:
+ throw new GeometryException("invalid argument.");
+ }
+ }
+
+ static boolean isClockwiseRing(MultiPathImpl polygon, int iring) {
+ int high_point_index = polygon.getHighestPointIndex(iring);
+ int path_start = polygon.getPathStart(iring);
+ int path_end = polygon.getPathEnd(iring);
+
+ Point2D q = polygon.getXY(high_point_index);
+ Point2D p, r;
+
+ if (high_point_index == path_start) {
+ p = polygon.getXY(path_end - 1);
+ r = polygon.getXY(path_start + 1);
+ } else if (high_point_index == path_end - 1) {
+ p = polygon.getXY(high_point_index - 1);
+ r = polygon.getXY(path_start);
+ } else {
+ p = polygon.getXY(high_point_index - 1);
+ r = polygon.getXY(high_point_index + 1);
+ }
+
+ int orientation = Point2D.orientationRobust(p, q, r);
+
+ if (orientation == 0)
+ return polygon.calculateRingArea2D(iring) > 0.0;
+
+ return orientation == -1;
+ }
+
+ static QuadTreeImpl buildQuadTree(MultiPathImpl multipathImpl) {
+ Envelope2D extent = new Envelope2D();
+ multipathImpl.queryLooseEnvelope2D(extent);
+ QuadTreeImpl quad_tree_impl = new QuadTreeImpl(extent, 8);
+ int hint_index = -1;
+ SegmentIteratorImpl seg_iter = multipathImpl.querySegmentIterator();
+ Envelope2D boundingbox = new Envelope2D();
+ boolean resized_extent = false;
+
+ while (seg_iter.nextPath()) {
+ while (seg_iter.hasNextSegment()) {
+ Segment segment = seg_iter.nextSegment();
+ int index = seg_iter.getStartPointIndex();
+ segment.queryEnvelope2D(boundingbox);
+ hint_index = quad_tree_impl.insert(index, boundingbox,
+ hint_index);
+
+ if (hint_index == -1) {
+ if (resized_extent)
+ throw GeometryException.GeometryInternalError();
+
+ // resize extent
+ multipathImpl.calculateEnvelope2D(extent, false);
+ resized_extent = true;
+ quad_tree_impl.reset(extent, 8);
+ seg_iter.resetToFirstPath();
+ break;
+ }
+ }
+ }
+
+ return quad_tree_impl;
+ }
+
+ static QuadTreeImpl buildQuadTree(MultiPathImpl multipathImpl,
+ Envelope2D extentOfInterest) {
+ Envelope2D extent = new Envelope2D();
+ multipathImpl.queryLooseEnvelope2D(extent);
+ QuadTreeImpl quad_tree_impl = new QuadTreeImpl(extent, 8);
+ int hint_index = -1;
+ Envelope2D boundingbox = new Envelope2D();
+ SegmentIteratorImpl seg_iter = multipathImpl.querySegmentIterator();
+
+ boolean resized_extent = false;
+ while (seg_iter.nextPath()) {
+ while (seg_iter.hasNextSegment()) {
+ Segment segment = seg_iter.nextSegment();
+ int index = seg_iter.getStartPointIndex();
+ segment.queryEnvelope2D(boundingbox);
+
+ if (boundingbox.isIntersecting(extentOfInterest)) {
+ hint_index = quad_tree_impl.insert(index, boundingbox,
+ hint_index);
+
+ if (hint_index == -1) {
+ if (resized_extent)
+ throw GeometryException.GeometryInternalError();
+
+ // resize extent
+ multipathImpl.calculateEnvelope2D(extent, false);
+ resized_extent = true;
+ quad_tree_impl.reset(extent, 8);
+ seg_iter.resetToFirstPath();
+ break;
+ }
+ }
+ }
+ }
+
+ return quad_tree_impl;
+ }
+
+ static QuadTreeImpl buildQuadTreeForPaths(MultiPathImpl multipathImpl) {
+ Envelope2D extent = new Envelope2D();
+ multipathImpl.queryLooseEnvelope2D(extent);
+ if (extent.isEmpty())
+ return null;
+
+ QuadTreeImpl quad_tree_impl = new QuadTreeImpl(extent, 8);
+ int hint_index = -1;
+ Envelope2D boundingbox = new Envelope2D();
+
+ boolean resized_extent = false;
+ do {
+ for (int ipath = 0, npaths = multipathImpl.getPathCount(); ipath < npaths; ipath++) {
+ multipathImpl.queryPathEnvelope2D(ipath, boundingbox);
+ hint_index = quad_tree_impl.insert(ipath, boundingbox, hint_index);
+
+ if (hint_index == -1) {
+ if (resized_extent)
+ throw GeometryException.GeometryInternalError();
+
+ //This is usually happens because esri shape buffer contains geometry extent which is slightly different from the true extent.
+ //Recalculate extent
+ multipathImpl.calculateEnvelope2D(extent, false);
+ resized_extent = true;
+ quad_tree_impl.reset(extent, 8);
+ break; //break the for loop
+ } else {
+ resized_extent = false;
+ }
+ }
+
+ } while (resized_extent);
+
+ return quad_tree_impl;
+ }
+
+ static QuadTreeImpl buildQuadTree(MultiPointImpl multipointImpl) {
+ Envelope2D extent = new Envelope2D();
+ multipointImpl.queryLooseEnvelope2D(extent);
+ QuadTreeImpl quad_tree_impl = new QuadTreeImpl(extent, 8);
+
+ Point2D pt = new Point2D();
+ Envelope2D boundingbox = new Envelope2D();
+ boolean resized_extent = false;
+ for (int i = 0; i < multipointImpl.getPointCount(); i++) {
+ multipointImpl.getXY(i, pt);
+ boundingbox.setCoords(pt);
+ int element_handle = quad_tree_impl.insert(i, boundingbox);
+
+ if (element_handle == -1) {
+ if (resized_extent)
+ throw GeometryException.GeometryInternalError();
+
+ // resize extent
+ multipointImpl.calculateEnvelope2D(extent, false);
+ resized_extent = true;
+ quad_tree_impl.reset(extent, 8);
+ i = -1; // resets the for-loop
+ continue;
+ }
+ }
+
+ return quad_tree_impl;
+ }
+
+ static QuadTreeImpl buildQuadTree(MultiPointImpl multipointImpl,
+ Envelope2D extentOfInterest) {
+ QuadTreeImpl quad_tree_impl = new QuadTreeImpl(extentOfInterest, 8);
+ Point2D pt = new Point2D();
+ boolean resized_extent = false;
+ Envelope2D boundingbox = new Envelope2D();
+ for (int i = 0; i < multipointImpl.getPointCount(); i++) {
+ multipointImpl.getXY(i, pt);
+
+ if (!extentOfInterest.contains(pt))
+ continue;
+
+ boundingbox.setCoords(pt);
+ int element_handle = quad_tree_impl.insert(i, boundingbox);
+
+ if (element_handle == -1) {
+ if (resized_extent)
+ throw GeometryException.GeometryInternalError();
+
+ // resize extent
+ resized_extent = true;
+ Envelope2D extent = new Envelope2D();
+ multipointImpl.calculateEnvelope2D(extent, false);
+ quad_tree_impl.reset(extent, 8);
+ i = -1; // resets the for-loop
+ continue;
+ }
+ }
+
+ return quad_tree_impl;
+ }
+
+ static Envelope2DIntersectorImpl getEnvelope2DIntersector(
+ MultiPathImpl multipathImplA, MultiPathImpl multipathImplB,
+ double tolerance) {
+ Envelope2D env_a = new Envelope2D(), env_b = new Envelope2D();
+ multipathImplA.queryLooseEnvelope2D(env_a);
+ multipathImplB.queryLooseEnvelope2D(env_b);
+ env_a.inflate(tolerance, tolerance);
+ env_b.inflate(tolerance, tolerance);
+
+ Envelope2D envInter = new Envelope2D();
+ envInter.setCoords(env_a);
+ envInter.intersect(env_b);
+
+ SegmentIteratorImpl segIterA = multipathImplA.querySegmentIterator();
+ SegmentIteratorImpl segIterB = multipathImplB.querySegmentIterator();
+
+ Envelope2DIntersectorImpl intersector = new Envelope2DIntersectorImpl();
+ intersector.setTolerance(tolerance);
+
+ boolean b_found_red = false;
+ intersector.startRedConstruction();
+ while (segIterA.nextPath()) {
+ while (segIterA.hasNextSegment()) {
+ Segment segmentA = segIterA.nextSegment();
+ segmentA.queryEnvelope2D(env_a);
+
+ if (!env_a.isIntersecting(envInter))
+ continue;
+
+ b_found_red = true;
+ Envelope2D env = new Envelope2D();
+ env.setCoords(env_a);
+ intersector.addRedEnvelope(segIterA.getStartPointIndex(), env);
+ }
+ }
+ intersector.endRedConstruction();
+
+ if (!b_found_red)
+ return null;
+
+ boolean b_found_blue = false;
+ intersector.startBlueConstruction();
+ while (segIterB.nextPath()) {
+ while (segIterB.hasNextSegment()) {
+ Segment segmentB = segIterB.nextSegment();
+ segmentB.queryEnvelope2D(env_b);
+
+ if (!env_b.isIntersecting(envInter))
+ continue;
+
+ b_found_blue = true;
+ Envelope2D env = new Envelope2D();
+ env.setCoords(env_b);
+ intersector.addBlueEnvelope(segIterB.getStartPointIndex(), env);
+ }
+ }
+ intersector.endBlueConstruction();
+
+ if (!b_found_blue)
+ return null;
+
+ return intersector;
+ }
+
+ static Envelope2DIntersectorImpl getEnvelope2DIntersectorForParts(
+ MultiPathImpl multipathImplA, MultiPathImpl multipathImplB,
+ double tolerance, boolean bExteriorOnlyA, boolean bExteriorOnlyB) {
+ int type_a = multipathImplA.getType().value();
+ int type_b = multipathImplB.getType().value();
+
+ Envelope2D env_a = new Envelope2D(), env_b = new Envelope2D();
+ multipathImplA.queryLooseEnvelope2D(env_a);
+ multipathImplB.queryLooseEnvelope2D(env_b);
+ env_a.inflate(tolerance, tolerance);
+ env_b.inflate(tolerance, tolerance);
+
+ Envelope2D envInter = new Envelope2D();
+ envInter.setCoords(env_a);
+ envInter.intersect(env_b);
+
+ Envelope2DIntersectorImpl intersector = new Envelope2DIntersectorImpl();
+ intersector.setTolerance(tolerance);
+
+ boolean b_found_red = false;
+ intersector.startRedConstruction();
+ for (int ipath_a = 0, npaths = multipathImplA.getPathCount(); ipath_a < npaths; ipath_a++) {
+ if (bExteriorOnlyA && type_a == Geometry.GeometryType.Polygon && !multipathImplA.isExteriorRing(ipath_a))
+ continue;
+
+ multipathImplA.queryPathEnvelope2D(ipath_a, env_a);
+
+ if (!env_a.isIntersecting(envInter))
+ continue;
+
+ b_found_red = true;
+ intersector.addRedEnvelope(ipath_a, env_a);
+ }
+ intersector.endRedConstruction();
+
+ if (!b_found_red)
+ return null;
+
+ boolean b_found_blue = false;
+ intersector.startBlueConstruction();
+ for (int ipath_b = 0, npaths = multipathImplB.getPathCount(); ipath_b < npaths; ipath_b++) {
+ if (bExteriorOnlyB && type_b == Geometry.GeometryType.Polygon && !multipathImplB.isExteriorRing(ipath_b))
+ continue;
+
+ multipathImplB.queryPathEnvelope2D(ipath_b, env_b);
+
+ if (!env_b.isIntersecting(envInter))
+ continue;
+
+ b_found_blue = true;
+ intersector.addBlueEnvelope(ipath_b, env_b);
+ }
+ intersector.endBlueConstruction();
+
+ if (!b_found_blue)
+ return null;
+
+ return intersector;
+ }
+
+ static boolean isWeakSimple(MultiVertexGeometry geom, double tol) {
+ return ((MultiVertexGeometryImpl) geom._getImpl()).getIsSimple(tol) > 0;
+ }
+
+ static QuadTree buildQuadTreeForOnePath(MultiPathImpl multipathImpl, int path) {
+ Envelope2D extent = new Envelope2D();
+ multipathImpl.queryLoosePathEnvelope2D(path, extent);
+ QuadTree quad_tree = new QuadTree(extent, 8);
+ int hint_index = -1;
+ Envelope2D boundingbox = new Envelope2D();
+ SegmentIteratorImpl seg_iter = multipathImpl.querySegmentIterator();
+
+ seg_iter.resetToPath(path);
+ if (seg_iter.nextPath()) {
+ while (seg_iter.hasNextSegment()) {
+ Segment segment = seg_iter.nextSegment();
+ int index = seg_iter.getStartPointIndex();
+ segment.queryLooseEnvelope2D(boundingbox);
+ hint_index = quad_tree.insert(index, boundingbox, hint_index);
+
+ if (hint_index == -1) {
+ throw new GeometryException("internal error");
+ }
+ }
+ }
+
+ return quad_tree;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/Interop.java b/src/main/java/com/esri/core/geometry/Interop.java
index b90726f0..b47801c7 100644
--- a/src/main/java/com/esri/core/geometry/Interop.java
+++ b/src/main/java/com/esri/core/geometry/Interop.java
@@ -25,11 +25,11 @@
package com.esri.core.geometry;
class Interop {
- public static double translateFromAVNaN(double n) {
- return (n < -1.0e38) ? NumberUtils.NaN() : n;
- }
+ public static double translateFromAVNaN(double n) {
+ return (n < -1.0e38) ? NumberUtils.NaN() : n;
+ }
- public static double translateToAVNaN(double n) {
- return (NumberUtils.isNaN(n)) ? -Double.MAX_VALUE : n;
- }
+ public static double translateToAVNaN(double n) {
+ return (NumberUtils.isNaN(n)) ? -Double.MAX_VALUE : n;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/IntervalTreeImpl.java b/src/main/java/com/esri/core/geometry/IntervalTreeImpl.java
index cd1d2553..f7248c47 100644
--- a/src/main/java/com/esri/core/geometry/IntervalTreeImpl.java
+++ b/src/main/java/com/esri/core/geometry/IntervalTreeImpl.java
@@ -26,183 +26,183 @@
import java.util.ArrayList;
final class IntervalTreeImpl {
- private void sortEndIndices_(AttributeStreamOfInt32 end_indices, int begin_, int end_) {
- IntervalTreeBucketSortHelper sorter = new IntervalTreeBucketSortHelper(this);
- BucketSort bucket_sort = new BucketSort();
- bucket_sort.sort(end_indices, begin_, end_, sorter);
- }
-
- private void sortEndIndicesHelper_(AttributeStreamOfInt32 end_indices, int begin_, int end_) {
- end_indices.Sort(begin_, end_, new EndPointsComparer(this));
- }
-
- private double getValue_(int e) {
- if (!m_b_envelopes_ref) {
- Envelope1D interval = m_intervals.get(e >> 1);
- double v = (isLeft_(e) ? interval.vmin : interval.vmax);
- return v;
- }
-
- Envelope2D interval = m_envelopes_ref.get(e >> 1);
- double v = (isLeft_(e) ? interval.xmin : interval.xmax);
- return v;
- }
-
- private static final class EndPointsComparer extends AttributeStreamOfInt32.IntComparator { // For user sort
-
- EndPointsComparer(IntervalTreeImpl interval_tree) {
- m_interval_tree = interval_tree;
- }
-
- @Override
- public int compare(int e_1, int e_2) {
- double v_1 = m_interval_tree.getValue_(e_1);
- double v_2 = m_interval_tree.getValue_(e_2);
-
- if (v_1 < v_2 || (v_1 == v_2 && isLeft_(e_1) && isRight_(e_2)))
- return -1;
-
- return 1;
- }
-
- private IntervalTreeImpl m_interval_tree;
- }
-
- private class IntervalTreeBucketSortHelper extends ClassicSort { // For bucket sort
-
- IntervalTreeBucketSortHelper(IntervalTreeImpl interval_tree) {
- m_interval_tree = interval_tree;
- }
-
- @Override
- public void userSort(int begin, int end, AttributeStreamOfInt32 indices) {
- m_interval_tree.sortEndIndicesHelper_(indices, begin, end);
- }
-
- @Override
- public double getValue(int e) {
- return m_interval_tree.getValue_(e);
- }
-
- private IntervalTreeImpl m_interval_tree;
- }
-
- IntervalTreeImpl(boolean b_offline_dynamic) {
- m_b_envelopes_ref = false;
- m_b_offline_dynamic = b_offline_dynamic;
- m_b_constructing = false;
- m_b_construction_ended = false;
- }
-
- void addEnvelopesRef(ArrayList
- * Returns an ID associated with the current Geometry. The ID is passed
- * along and is returned by some operators to preserve relationship between
- * the input and output geometry classes. It is not always possible to
- * preserve an ID during an operation.
- */
- public abstract int getID();
+ /**
+ * Moves the cursor to the next string. Returns null when reached the end.
+ */
+ public abstract String next();
+
+ /**
+ * Returns the ID of the current geometry. The ID is propagated across the
+ * operations (when possible).
+ *
+ * Returns an ID associated with the current Geometry. The ID is passed
+ * along and is returned by some operators to preserve relationship between
+ * the input and output geometry classes. It is not always possible to
+ * preserve an ID during an operation.
+ */
+ public abstract int getID();
}
diff --git a/src/main/java/com/esri/core/geometry/JsonGeometryException.java b/src/main/java/com/esri/core/geometry/JsonGeometryException.java
index 75f27a9b..7981a27a 100644
--- a/src/main/java/com/esri/core/geometry/JsonGeometryException.java
+++ b/src/main/java/com/esri/core/geometry/JsonGeometryException.java
@@ -28,25 +28,25 @@
* A runtime exception raised when a JSON related exception occurs.
*/
public class JsonGeometryException extends GeometryException {
- private static final long serialVersionUID = 1L;
-
- /**
- * Constructs a Json Geometry Exception with the given error string/message.
- *
- * @param str - The error string.
- */
- public JsonGeometryException(String str) {
- super(str);
- }
-
- /**
- * Constructs a Json Geometry Exception with the given another exception.
- *
- * @param ex - The exception to copy the message from.
- */
- public JsonGeometryException(Exception ex) {
- super(ex.getMessage());
- }
+ private static final long serialVersionUID = 1L;
+
+ /**
+ * Constructs a Json Geometry Exception with the given error string/message.
+ *
+ * @param str - The error string.
+ */
+ public JsonGeometryException(String str) {
+ super(str);
+ }
+
+ /**
+ * Constructs a Json Geometry Exception with the given another exception.
+ *
+ * @param ex - The exception to copy the message from.
+ */
+ public JsonGeometryException(Exception ex) {
+ super(ex.getMessage());
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/JsonParserReader.java b/src/main/java/com/esri/core/geometry/JsonParserReader.java
index ce8db6b6..cccef914 100644
--- a/src/main/java/com/esri/core/geometry/JsonParserReader.java
+++ b/src/main/java/com/esri/core/geometry/JsonParserReader.java
@@ -31,138 +31,138 @@
*/
public class JsonParserReader implements JsonReader {
- private JsonParser m_jsonParser;
-
- public JsonParserReader(JsonParser jsonParser) {
- m_jsonParser = jsonParser;
- }
-
- /**
- * Creates a JsonReader for the string.
- * The nextToken is called by this method.
- */
- public static JsonReader createFromString(String str) {
- try {
- JsonFactory factory = new JsonFactory();
- JsonParser jsonParser = factory.createParser(str);
-
- jsonParser.nextToken();
- return new JsonParserReader(jsonParser);
- } catch (Exception ex) {
- throw new JsonGeometryException(ex.getMessage());
- }
- }
-
- /**
- * Creates a JsonReader for the string.
- * The nextToken is not called by this method.
- */
- public static JsonReader createFromStringNNT(String str) {
- try {
- JsonFactory factory = new JsonFactory();
- JsonParser jsonParser = factory.createParser(str);
-
- return new JsonParserReader(jsonParser);
- } catch (Exception ex) {
- throw new JsonGeometryException(ex.getMessage());
- }
- }
-
- private static Token mapToken(JsonToken token) {
- if (token == JsonToken.END_ARRAY)
- return Token.END_ARRAY;
- if (token == JsonToken.END_OBJECT)
- return Token.END_OBJECT;
- if (token == JsonToken.FIELD_NAME)
- return Token.FIELD_NAME;
- if (token == JsonToken.START_ARRAY)
- return Token.START_ARRAY;
- if (token == JsonToken.START_OBJECT)
- return Token.START_OBJECT;
- if (token == JsonToken.VALUE_FALSE)
- return Token.VALUE_FALSE;
- if (token == JsonToken.VALUE_NULL)
- return Token.VALUE_NULL;
- if (token == JsonToken.VALUE_NUMBER_FLOAT)
- return Token.VALUE_NUMBER_FLOAT;
- if (token == JsonToken.VALUE_NUMBER_INT)
- return Token.VALUE_NUMBER_INT;
- if (token == JsonToken.VALUE_STRING)
- return Token.VALUE_STRING;
- if (token == JsonToken.VALUE_TRUE)
- return Token.VALUE_TRUE;
- if (token == null)
- return null;
-
- throw new JsonGeometryException("unexpected token");
- }
-
- @Override
- public Token nextToken() throws JsonGeometryException {
- try {
- JsonToken token = m_jsonParser.nextToken();
- return mapToken(token);
- } catch (Exception ex) {
- throw new JsonGeometryException(ex);
- }
- }
-
- @Override
- public Token currentToken() throws JsonGeometryException {
- try {
- return mapToken(m_jsonParser.getCurrentToken());
- } catch (Exception ex) {
- throw new JsonGeometryException(ex);
- }
- }
-
- @Override
- public void skipChildren() throws JsonGeometryException {
- try {
- m_jsonParser.skipChildren();
- } catch (Exception ex) {
- throw new JsonGeometryException(ex);
- }
-
- }
-
- @Override
- public String currentString() throws JsonGeometryException {
- try {
- return m_jsonParser.getText();
- } catch (Exception ex) {
- throw new JsonGeometryException(ex);
- }
-
- }
-
- @Override
- public double currentDoubleValue() throws JsonGeometryException {
- try {
- return m_jsonParser.getValueAsDouble();
- } catch (Exception ex) {
- throw new JsonGeometryException(ex);
- }
-
- }
-
- @Override
- public int currentIntValue() throws JsonGeometryException {
- try {
- return m_jsonParser.getValueAsInt();
- } catch (Exception ex) {
- throw new JsonGeometryException(ex);
- }
- }
-
- @Override
- public boolean currentBooleanValue() {
- Token t = currentToken();
- if (t == Token.VALUE_TRUE)
- return true;
- else if (t == Token.VALUE_FALSE)
- return false;
- throw new JsonGeometryException("Not a boolean");
- }
+ private JsonParser m_jsonParser;
+
+ public JsonParserReader(JsonParser jsonParser) {
+ m_jsonParser = jsonParser;
+ }
+
+ /**
+ * Creates a JsonReader for the string.
+ * The nextToken is called by this method.
+ */
+ public static JsonReader createFromString(String str) {
+ try {
+ JsonFactory factory = new JsonFactory();
+ JsonParser jsonParser = factory.createParser(str);
+
+ jsonParser.nextToken();
+ return new JsonParserReader(jsonParser);
+ } catch (Exception ex) {
+ throw new JsonGeometryException(ex.getMessage());
+ }
+ }
+
+ /**
+ * Creates a JsonReader for the string.
+ * The nextToken is not called by this method.
+ */
+ public static JsonReader createFromStringNNT(String str) {
+ try {
+ JsonFactory factory = new JsonFactory();
+ JsonParser jsonParser = factory.createParser(str);
+
+ return new JsonParserReader(jsonParser);
+ } catch (Exception ex) {
+ throw new JsonGeometryException(ex.getMessage());
+ }
+ }
+
+ private static Token mapToken(JsonToken token) {
+ if (token == JsonToken.END_ARRAY)
+ return Token.END_ARRAY;
+ if (token == JsonToken.END_OBJECT)
+ return Token.END_OBJECT;
+ if (token == JsonToken.FIELD_NAME)
+ return Token.FIELD_NAME;
+ if (token == JsonToken.START_ARRAY)
+ return Token.START_ARRAY;
+ if (token == JsonToken.START_OBJECT)
+ return Token.START_OBJECT;
+ if (token == JsonToken.VALUE_FALSE)
+ return Token.VALUE_FALSE;
+ if (token == JsonToken.VALUE_NULL)
+ return Token.VALUE_NULL;
+ if (token == JsonToken.VALUE_NUMBER_FLOAT)
+ return Token.VALUE_NUMBER_FLOAT;
+ if (token == JsonToken.VALUE_NUMBER_INT)
+ return Token.VALUE_NUMBER_INT;
+ if (token == JsonToken.VALUE_STRING)
+ return Token.VALUE_STRING;
+ if (token == JsonToken.VALUE_TRUE)
+ return Token.VALUE_TRUE;
+ if (token == null)
+ return null;
+
+ throw new JsonGeometryException("unexpected token");
+ }
+
+ @Override
+ public Token nextToken() throws JsonGeometryException {
+ try {
+ JsonToken token = m_jsonParser.nextToken();
+ return mapToken(token);
+ } catch (Exception ex) {
+ throw new JsonGeometryException(ex);
+ }
+ }
+
+ @Override
+ public Token currentToken() throws JsonGeometryException {
+ try {
+ return mapToken(m_jsonParser.getCurrentToken());
+ } catch (Exception ex) {
+ throw new JsonGeometryException(ex);
+ }
+ }
+
+ @Override
+ public void skipChildren() throws JsonGeometryException {
+ try {
+ m_jsonParser.skipChildren();
+ } catch (Exception ex) {
+ throw new JsonGeometryException(ex);
+ }
+
+ }
+
+ @Override
+ public String currentString() throws JsonGeometryException {
+ try {
+ return m_jsonParser.getText();
+ } catch (Exception ex) {
+ throw new JsonGeometryException(ex);
+ }
+
+ }
+
+ @Override
+ public double currentDoubleValue() throws JsonGeometryException {
+ try {
+ return m_jsonParser.getValueAsDouble();
+ } catch (Exception ex) {
+ throw new JsonGeometryException(ex);
+ }
+
+ }
+
+ @Override
+ public int currentIntValue() throws JsonGeometryException {
+ try {
+ return m_jsonParser.getValueAsInt();
+ } catch (Exception ex) {
+ throw new JsonGeometryException(ex);
+ }
+ }
+
+ @Override
+ public boolean currentBooleanValue() {
+ Token t = currentToken();
+ if (t == Token.VALUE_TRUE)
+ return true;
+ else if (t == Token.VALUE_FALSE)
+ return false;
+ throw new JsonGeometryException("Not a boolean");
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/JsonReader.java b/src/main/java/com/esri/core/geometry/JsonReader.java
index 00dd3f12..8c1126e9 100644
--- a/src/main/java/com/esri/core/geometry/JsonReader.java
+++ b/src/main/java/com/esri/core/geometry/JsonReader.java
@@ -29,32 +29,32 @@
* See JsonParserReader for a concrete implementation around JsonParser.
*/
abstract public interface JsonReader {
- public static enum Token {
- END_ARRAY,
- END_OBJECT,
- FIELD_NAME,
- START_ARRAY,
- START_OBJECT,
- VALUE_FALSE,
- VALUE_NULL,
- VALUE_NUMBER_FLOAT,
- VALUE_NUMBER_INT,
- VALUE_STRING,
- VALUE_TRUE
- }
+ public static enum Token {
+ END_ARRAY,
+ END_OBJECT,
+ FIELD_NAME,
+ START_ARRAY,
+ START_OBJECT,
+ VALUE_FALSE,
+ VALUE_NULL,
+ VALUE_NUMBER_FLOAT,
+ VALUE_NUMBER_INT,
+ VALUE_STRING,
+ VALUE_TRUE
+ }
- abstract public Token nextToken() throws JsonGeometryException;
+ abstract public Token nextToken() throws JsonGeometryException;
- abstract public Token currentToken() throws JsonGeometryException;
+ abstract public Token currentToken() throws JsonGeometryException;
- abstract public void skipChildren() throws JsonGeometryException;
+ abstract public void skipChildren() throws JsonGeometryException;
- abstract public String currentString() throws JsonGeometryException;
+ abstract public String currentString() throws JsonGeometryException;
- abstract public double currentDoubleValue() throws JsonGeometryException;
+ abstract public double currentDoubleValue() throws JsonGeometryException;
- abstract public int currentIntValue() throws JsonGeometryException;
+ abstract public int currentIntValue() throws JsonGeometryException;
- abstract public boolean currentBooleanValue() throws JsonGeometryException;
+ abstract public boolean currentBooleanValue() throws JsonGeometryException;
}
diff --git a/src/main/java/com/esri/core/geometry/JsonReaderCursor.java b/src/main/java/com/esri/core/geometry/JsonReaderCursor.java
index 240e0ce1..c36ebe11 100644
--- a/src/main/java/com/esri/core/geometry/JsonReaderCursor.java
+++ b/src/main/java/com/esri/core/geometry/JsonReaderCursor.java
@@ -46,26 +46,26 @@
*/
abstract class JsonReaderCursor implements Iterator
- * Returns an ID associated with the current Geometry. The ID is passed
- * along and is returned by some operators to preserve relationship between
- * the input and output geometry classes. It is not always possible to
- * preserve an ID during an operation.
- */
- public abstract int getID();
-
- public abstract SimpleStateEnum getSimpleState();
-
- public abstract String getFeatureID();
-
- public abstract boolean hasNext();
+ /**
+ * Moves the cursor to the next JsonReader. Returns null when reached the
+ * end.
+ */
+ public abstract JsonReader next();
+
+ /**
+ * Returns the ID of the current geometry. The ID is propagated across the
+ * operations (when possible).
+ *
+ * Returns an ID associated with the current Geometry. The ID is passed
+ * along and is returned by some operators to preserve relationship between
+ * the input and output geometry classes. It is not always possible to
+ * preserve an ID during an operation.
+ */
+ public abstract int getID();
+
+ public abstract SimpleStateEnum getSimpleState();
+
+ public abstract String getFeatureID();
+
+ public abstract boolean hasNext();
}
diff --git a/src/main/java/com/esri/core/geometry/JsonStringWriter.java b/src/main/java/com/esri/core/geometry/JsonStringWriter.java
index 4c551d25..36be1445 100644
--- a/src/main/java/com/esri/core/geometry/JsonStringWriter.java
+++ b/src/main/java/com/esri/core/geometry/JsonStringWriter.java
@@ -25,402 +25,402 @@
final class JsonStringWriter extends JsonWriter {
- @Override
- Object getJson() {
- next_(Action.accept);
- return m_jsonString.toString();
- }
-
- @Override
- void startObject() {
- next_(Action.addObject);
- m_jsonString.append('{');
- m_functionStack.add(State.objectStart);
- }
-
- @Override
- void startArray() {
- next_(Action.addArray);
- m_jsonString.append('[');
- m_functionStack.add(State.arrayStart);
- }
-
- @Override
- void endObject() {
- next_(Action.popObject);
- m_jsonString.append('}');
- }
-
- @Override
- void endArray() {
- next_(Action.popArray);
- m_jsonString.append(']');
- }
-
- @Override
- void addFieldName(String fieldName) {
- next_(Action.addKey);
- appendQuote_(fieldName);
- }
-
- @Override
- void addPairObject(String fieldName) {
- next_(Action.addPair);
- appendQuote_(fieldName);
- m_jsonString.append(":");
- addValueObject_();
- }
-
- @Override
- void addPairArray(String fieldName) {
- next_(Action.addPair);
- appendQuote_(fieldName);
- m_jsonString.append(":");
- addValueArray_();
- }
-
- @Override
- void addPairString(String fieldName, String v) {
- next_(Action.addPair);
- appendQuote_(fieldName);
- m_jsonString.append(":");
- addValueString_(v);
- }
-
- @Override
- void addPairDouble(String fieldName, double v) {
- next_(Action.addPair);
- appendQuote_(fieldName);
- m_jsonString.append(":");
- addValueDouble_(v);
- }
-
- @Override
- void addPairDouble(String fieldName, double v, int precision, boolean bFixedPoint) {
- next_(Action.addPair);
- appendQuote_(fieldName);
- m_jsonString.append(":");
- addValueDouble_(v, precision, bFixedPoint);
- }
-
- @Override
- void addPairInt(String fieldName, int v) {
- next_(Action.addPair);
- appendQuote_(fieldName);
- m_jsonString.append(":");
- addValueInt_(v);
- }
-
- @Override
- void addPairBoolean(String fieldName, boolean v) {
- next_(Action.addPair);
- appendQuote_(fieldName);
- m_jsonString.append(":");
- addValueBoolean_(v);
- }
-
- @Override
- void addPairNull(String fieldName) {
- next_(Action.addPair);
- appendQuote_(fieldName);
- m_jsonString.append(":");
- addValueNull_();
- }
-
- @Override
- void addValueObject() {
- next_(Action.addObject);
- addValueObject_();
- }
-
- @Override
- void addValueArray() {
- next_(Action.addArray);
- addValueArray_();
- }
-
- @Override
- void addValueString(String v) {
- next_(Action.addTerminal);
- addValueString_(v);
- }
-
- @Override
- void addValueDouble(double v) {
- next_(Action.addTerminal);
- addValueDouble_(v);
- }
-
- @Override
- void addValueDouble(double v, int precision, boolean bFixedPoint) {
- next_(Action.addTerminal);
- addValueDouble_(v, precision, bFixedPoint);
- }
-
- @Override
- void addValueInt(int v) {
- next_(Action.addTerminal);
- addValueInt_(v);
- }
-
- @Override
- void addValueBoolean(boolean v) {
- next_(Action.addTerminal);
- addValueBoolean_(v);
- }
-
- @Override
- void addValueNull() {
- next_(Action.addTerminal);
- addValueNull_();
- }
-
- JsonStringWriter() {
- m_jsonString = new StringBuilder();
- m_functionStack = new AttributeStreamOfInt32(0);
- m_functionStack.add(State.accept);
- m_functionStack.add(State.start);
- }
-
- private StringBuilder m_jsonString;
- private AttributeStreamOfInt32 m_functionStack;
-
- private void addValueObject_() {
- m_jsonString.append('{');
- m_functionStack.add(State.objectStart);
- }
-
- private void addValueArray_() {
- m_jsonString.append('[');
- m_functionStack.add(State.arrayStart);
- }
-
- private void addValueString_(String v) {
- appendQuote_(v);
- }
-
- private void addValueDouble_(double v) {
- if (NumberUtils.isNaN(v)) {
- addValueNull_();
- return;
- }
-
- StringUtils.appendDouble(v, 17, m_jsonString);
- }
-
- private void addValueDouble_(double v, int precision, boolean bFixedPoint) {
- if (NumberUtils.isNaN(v)) {
- addValueNull_();
- return;
- }
-
- if (bFixedPoint)
- StringUtils.appendDoubleF(v, precision, m_jsonString);
- else
- StringUtils.appendDouble(v, precision, m_jsonString);
- }
-
- private void addValueInt_(int v) {
- m_jsonString.append(v);
- }
-
- private void addValueBoolean_(boolean v) {
- if (v) {
- m_jsonString.append("true");
- } else {
- m_jsonString.append("false");
- }
- }
-
- private void addValueNull_() {
- m_jsonString.append("null");
- }
-
- private void next_(int action) {
- switch (m_functionStack.getLast()) {
- case State.accept:
- accept_(action);
- break;
- case State.start:
- start_(action);
- break;
- case State.objectStart:
- objectStart_(action);
- break;
- case State.arrayStart:
- arrayStart_(action);
- break;
- case State.pairEnd:
- pairEnd_(action);
- break;
- case State.elementEnd:
- elementEnd_(action);
- break;
- case State.fieldNameEnd:
- fieldNameEnd_(action);
- break;
- default:
- throw new GeometryException("internal error");
- }
- }
-
- private void accept_(int action) {
- if (action != Action.accept) {
- throw new GeometryException("invalid call");
- }
- }
-
- private void start_(int action) {
- if ((action & Action.addContainer) != 0) {
- m_functionStack.removeLast();
- } else {
- throw new GeometryException("invalid call");
- }
- }
-
- private void objectStart_(int action) {
- if (action != Action.popObject && action != Action.addPair && action != Action.addKey)
- throw new GeometryException("invalid call");
-
- m_functionStack.removeLast();
-
- if (action == Action.addPair) {
- m_functionStack.add(State.pairEnd);
- } else if (action == Action.addKey) {
- m_functionStack.add(State.pairEnd);
- m_functionStack.add(State.fieldNameEnd);
- }
- }
-
- private void pairEnd_(int action) {
- if (action == Action.addPair) {
- m_jsonString.append(',');
- } else if (action == Action.addKey) {
- m_jsonString.append(',');
- m_functionStack.add(State.fieldNameEnd);
- } else if (action == Action.popObject) {
- m_functionStack.removeLast();
- } else {
- throw new GeometryException("invalid call");
- }
- }
-
- private void arrayStart_(int action) {
- if ((action & Action.addValue) == 0 && action != Action.popArray)
- throw new GeometryException("invalid call");
-
- m_functionStack.removeLast();
-
- if ((action & Action.addValue) != 0) {
- m_functionStack.add(State.elementEnd);
- }
- }
-
- private void elementEnd_(int action) {
- if ((action & Action.addValue) != 0) {
- m_jsonString.append(',');
- } else if (action == Action.popArray) {
- m_functionStack.removeLast();
- } else {
- throw new GeometryException("invalid call");
- }
- }
-
- private void fieldNameEnd_(int action) {
- if ((action & Action.addValue) == 0)
- throw new GeometryException("invalid call");
-
- m_functionStack.removeLast();
- m_jsonString.append(':');
- }
-
- private void appendQuote_(String string) {
- int count = 0;
- int start = 0;
- int end = string.length();
-
- m_jsonString.append('"');
-
- for (int i = 0; i < end; i++) {
- switch (string.charAt(i)) {
- case '"':
- if (count > 0) {
- m_jsonString.append(string, start, start + count);
- count = 0;
- }
- m_jsonString.append("\\\"");
- start = i + 1;
- break;
- case '\\':
- if (count > 0) {
- m_jsonString.append(string, start, start + count);
- count = 0;
- }
- m_jsonString.append("\\\\");
- start = i + 1;
- break;
- case '/':
- if (i > 0 && string.charAt(i - 1) == '<') {
- if (count > 0) {
- m_jsonString.append(string, start, start + count);
- count = 0;
- }
- m_jsonString.append("\\/");
- start = i + 1;
- } else {
- count++;
- }
- break;
- case '\b':
- if (count > 0) {
- m_jsonString.append(string, start, start + count);
- count = 0;
- }
- m_jsonString.append("\\b");
- start = i + 1;
- break;
- case '\f':
- if (count > 0) {
- m_jsonString.append(string, start, start + count);
- count = 0;
- }
- m_jsonString.append("\\f");
- start = i + 1;
- break;
- case '\n':
- if (count > 0) {
- m_jsonString.append(string, start, start + count);
- count = 0;
- }
- m_jsonString.append("\\n");
- start = i + 1;
- break;
- case '\r':
- if (count > 0) {
- m_jsonString.append(string, start, start + count);
- count = 0;
- }
- m_jsonString.append("\\r");
- start = i + 1;
- break;
- case '\t':
- if (count > 0) {
- m_jsonString.append(string, start, start + count);
- count = 0;
- }
- m_jsonString.append("\\t");
- start = i + 1;
- break;
- default:
- count++;
- break;
- }
- }
-
- if (count > 0) {
- m_jsonString.append(string, start, start + count);
- }
-
- m_jsonString.append('"');
- }
+ @Override
+ Object getJson() {
+ next_(Action.accept);
+ return m_jsonString.toString();
+ }
+
+ @Override
+ void startObject() {
+ next_(Action.addObject);
+ m_jsonString.append('{');
+ m_functionStack.add(State.objectStart);
+ }
+
+ @Override
+ void startArray() {
+ next_(Action.addArray);
+ m_jsonString.append('[');
+ m_functionStack.add(State.arrayStart);
+ }
+
+ @Override
+ void endObject() {
+ next_(Action.popObject);
+ m_jsonString.append('}');
+ }
+
+ @Override
+ void endArray() {
+ next_(Action.popArray);
+ m_jsonString.append(']');
+ }
+
+ @Override
+ void addFieldName(String fieldName) {
+ next_(Action.addKey);
+ appendQuote_(fieldName);
+ }
+
+ @Override
+ void addPairObject(String fieldName) {
+ next_(Action.addPair);
+ appendQuote_(fieldName);
+ m_jsonString.append(":");
+ addValueObject_();
+ }
+
+ @Override
+ void addPairArray(String fieldName) {
+ next_(Action.addPair);
+ appendQuote_(fieldName);
+ m_jsonString.append(":");
+ addValueArray_();
+ }
+
+ @Override
+ void addPairString(String fieldName, String v) {
+ next_(Action.addPair);
+ appendQuote_(fieldName);
+ m_jsonString.append(":");
+ addValueString_(v);
+ }
+
+ @Override
+ void addPairDouble(String fieldName, double v) {
+ next_(Action.addPair);
+ appendQuote_(fieldName);
+ m_jsonString.append(":");
+ addValueDouble_(v);
+ }
+
+ @Override
+ void addPairDouble(String fieldName, double v, int precision, boolean bFixedPoint) {
+ next_(Action.addPair);
+ appendQuote_(fieldName);
+ m_jsonString.append(":");
+ addValueDouble_(v, precision, bFixedPoint);
+ }
+
+ @Override
+ void addPairInt(String fieldName, int v) {
+ next_(Action.addPair);
+ appendQuote_(fieldName);
+ m_jsonString.append(":");
+ addValueInt_(v);
+ }
+
+ @Override
+ void addPairBoolean(String fieldName, boolean v) {
+ next_(Action.addPair);
+ appendQuote_(fieldName);
+ m_jsonString.append(":");
+ addValueBoolean_(v);
+ }
+
+ @Override
+ void addPairNull(String fieldName) {
+ next_(Action.addPair);
+ appendQuote_(fieldName);
+ m_jsonString.append(":");
+ addValueNull_();
+ }
+
+ @Override
+ void addValueObject() {
+ next_(Action.addObject);
+ addValueObject_();
+ }
+
+ @Override
+ void addValueArray() {
+ next_(Action.addArray);
+ addValueArray_();
+ }
+
+ @Override
+ void addValueString(String v) {
+ next_(Action.addTerminal);
+ addValueString_(v);
+ }
+
+ @Override
+ void addValueDouble(double v) {
+ next_(Action.addTerminal);
+ addValueDouble_(v);
+ }
+
+ @Override
+ void addValueDouble(double v, int precision, boolean bFixedPoint) {
+ next_(Action.addTerminal);
+ addValueDouble_(v, precision, bFixedPoint);
+ }
+
+ @Override
+ void addValueInt(int v) {
+ next_(Action.addTerminal);
+ addValueInt_(v);
+ }
+
+ @Override
+ void addValueBoolean(boolean v) {
+ next_(Action.addTerminal);
+ addValueBoolean_(v);
+ }
+
+ @Override
+ void addValueNull() {
+ next_(Action.addTerminal);
+ addValueNull_();
+ }
+
+ JsonStringWriter() {
+ m_jsonString = new StringBuilder();
+ m_functionStack = new AttributeStreamOfInt32(0);
+ m_functionStack.add(State.accept);
+ m_functionStack.add(State.start);
+ }
+
+ private StringBuilder m_jsonString;
+ private AttributeStreamOfInt32 m_functionStack;
+
+ private void addValueObject_() {
+ m_jsonString.append('{');
+ m_functionStack.add(State.objectStart);
+ }
+
+ private void addValueArray_() {
+ m_jsonString.append('[');
+ m_functionStack.add(State.arrayStart);
+ }
+
+ private void addValueString_(String v) {
+ appendQuote_(v);
+ }
+
+ private void addValueDouble_(double v) {
+ if (NumberUtils.isNaN(v)) {
+ addValueNull_();
+ return;
+ }
+
+ StringUtils.appendDouble(v, 17, m_jsonString);
+ }
+
+ private void addValueDouble_(double v, int precision, boolean bFixedPoint) {
+ if (NumberUtils.isNaN(v)) {
+ addValueNull_();
+ return;
+ }
+
+ if (bFixedPoint)
+ StringUtils.appendDoubleF(v, precision, m_jsonString);
+ else
+ StringUtils.appendDouble(v, precision, m_jsonString);
+ }
+
+ private void addValueInt_(int v) {
+ m_jsonString.append(v);
+ }
+
+ private void addValueBoolean_(boolean v) {
+ if (v) {
+ m_jsonString.append("true");
+ } else {
+ m_jsonString.append("false");
+ }
+ }
+
+ private void addValueNull_() {
+ m_jsonString.append("null");
+ }
+
+ private void next_(int action) {
+ switch (m_functionStack.getLast()) {
+ case State.accept:
+ accept_(action);
+ break;
+ case State.start:
+ start_(action);
+ break;
+ case State.objectStart:
+ objectStart_(action);
+ break;
+ case State.arrayStart:
+ arrayStart_(action);
+ break;
+ case State.pairEnd:
+ pairEnd_(action);
+ break;
+ case State.elementEnd:
+ elementEnd_(action);
+ break;
+ case State.fieldNameEnd:
+ fieldNameEnd_(action);
+ break;
+ default:
+ throw new GeometryException("internal error");
+ }
+ }
+
+ private void accept_(int action) {
+ if (action != Action.accept) {
+ throw new GeometryException("invalid call");
+ }
+ }
+
+ private void start_(int action) {
+ if ((action & Action.addContainer) != 0) {
+ m_functionStack.removeLast();
+ } else {
+ throw new GeometryException("invalid call");
+ }
+ }
+
+ private void objectStart_(int action) {
+ if (action != Action.popObject && action != Action.addPair && action != Action.addKey)
+ throw new GeometryException("invalid call");
+
+ m_functionStack.removeLast();
+
+ if (action == Action.addPair) {
+ m_functionStack.add(State.pairEnd);
+ } else if (action == Action.addKey) {
+ m_functionStack.add(State.pairEnd);
+ m_functionStack.add(State.fieldNameEnd);
+ }
+ }
+
+ private void pairEnd_(int action) {
+ if (action == Action.addPair) {
+ m_jsonString.append(',');
+ } else if (action == Action.addKey) {
+ m_jsonString.append(',');
+ m_functionStack.add(State.fieldNameEnd);
+ } else if (action == Action.popObject) {
+ m_functionStack.removeLast();
+ } else {
+ throw new GeometryException("invalid call");
+ }
+ }
+
+ private void arrayStart_(int action) {
+ if ((action & Action.addValue) == 0 && action != Action.popArray)
+ throw new GeometryException("invalid call");
+
+ m_functionStack.removeLast();
+
+ if ((action & Action.addValue) != 0) {
+ m_functionStack.add(State.elementEnd);
+ }
+ }
+
+ private void elementEnd_(int action) {
+ if ((action & Action.addValue) != 0) {
+ m_jsonString.append(',');
+ } else if (action == Action.popArray) {
+ m_functionStack.removeLast();
+ } else {
+ throw new GeometryException("invalid call");
+ }
+ }
+
+ private void fieldNameEnd_(int action) {
+ if ((action & Action.addValue) == 0)
+ throw new GeometryException("invalid call");
+
+ m_functionStack.removeLast();
+ m_jsonString.append(':');
+ }
+
+ private void appendQuote_(String string) {
+ int count = 0;
+ int start = 0;
+ int end = string.length();
+
+ m_jsonString.append('"');
+
+ for (int i = 0; i < end; i++) {
+ switch (string.charAt(i)) {
+ case '"':
+ if (count > 0) {
+ m_jsonString.append(string, start, start + count);
+ count = 0;
+ }
+ m_jsonString.append("\\\"");
+ start = i + 1;
+ break;
+ case '\\':
+ if (count > 0) {
+ m_jsonString.append(string, start, start + count);
+ count = 0;
+ }
+ m_jsonString.append("\\\\");
+ start = i + 1;
+ break;
+ case '/':
+ if (i > 0 && string.charAt(i - 1) == '<') {
+ if (count > 0) {
+ m_jsonString.append(string, start, start + count);
+ count = 0;
+ }
+ m_jsonString.append("\\/");
+ start = i + 1;
+ } else {
+ count++;
+ }
+ break;
+ case '\b':
+ if (count > 0) {
+ m_jsonString.append(string, start, start + count);
+ count = 0;
+ }
+ m_jsonString.append("\\b");
+ start = i + 1;
+ break;
+ case '\f':
+ if (count > 0) {
+ m_jsonString.append(string, start, start + count);
+ count = 0;
+ }
+ m_jsonString.append("\\f");
+ start = i + 1;
+ break;
+ case '\n':
+ if (count > 0) {
+ m_jsonString.append(string, start, start + count);
+ count = 0;
+ }
+ m_jsonString.append("\\n");
+ start = i + 1;
+ break;
+ case '\r':
+ if (count > 0) {
+ m_jsonString.append(string, start, start + count);
+ count = 0;
+ }
+ m_jsonString.append("\\r");
+ start = i + 1;
+ break;
+ case '\t':
+ if (count > 0) {
+ m_jsonString.append(string, start, start + count);
+ count = 0;
+ }
+ m_jsonString.append("\\t");
+ start = i + 1;
+ break;
+ default:
+ count++;
+ break;
+ }
+ }
+
+ if (count > 0) {
+ m_jsonString.append(string, start, start + count);
+ }
+
+ m_jsonString.append('"');
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/JsonWriter.java b/src/main/java/com/esri/core/geometry/JsonWriter.java
index 0013cfcc..095f50e1 100644
--- a/src/main/java/com/esri/core/geometry/JsonWriter.java
+++ b/src/main/java/com/esri/core/geometry/JsonWriter.java
@@ -25,72 +25,72 @@
abstract class JsonWriter {
- abstract Object getJson();
+ abstract Object getJson();
- abstract void startObject();
+ abstract void startObject();
- abstract void startArray();
+ abstract void startArray();
- abstract void endObject();
+ abstract void endObject();
- abstract void endArray();
+ abstract void endArray();
- abstract void addFieldName(String fieldName);
+ abstract void addFieldName(String fieldName);
- abstract void addPairObject(String fieldName);
+ abstract void addPairObject(String fieldName);
- abstract void addPairArray(String fieldName);
+ abstract void addPairArray(String fieldName);
- abstract void addPairString(String fieldName, String v);
+ abstract void addPairString(String fieldName, String v);
- abstract void addPairDouble(String fieldName, double v);
+ abstract void addPairDouble(String fieldName, double v);
- abstract void addPairDouble(String fieldName, double v, int precision, boolean bFixedPoint);
+ abstract void addPairDouble(String fieldName, double v, int precision, boolean bFixedPoint);
- abstract void addPairInt(String fieldName, int v);
+ abstract void addPairInt(String fieldName, int v);
- abstract void addPairBoolean(String fieldName, boolean v);
+ abstract void addPairBoolean(String fieldName, boolean v);
- abstract void addPairNull(String fieldName);
+ abstract void addPairNull(String fieldName);
- abstract void addValueObject();
+ abstract void addValueObject();
- abstract void addValueArray();
+ abstract void addValueArray();
- abstract void addValueString(String v);
+ abstract void addValueString(String v);
- abstract void addValueDouble(double v);
+ abstract void addValueDouble(double v);
- abstract void addValueDouble(double v, int precision, boolean bFixedPoint);
+ abstract void addValueDouble(double v, int precision, boolean bFixedPoint);
- abstract void addValueInt(int v);
+ abstract void addValueInt(int v);
- abstract void addValueBoolean(boolean v);
+ abstract void addValueBoolean(boolean v);
- abstract void addValueNull();
+ abstract void addValueNull();
- protected interface Action {
+ protected interface Action {
- static final int accept = 0;
- static final int addObject = 1;
- static final int addArray = 2;
- static final int popObject = 4;
- static final int popArray = 8;
- static final int addKey = 16;
- static final int addTerminal = 32;
- static final int addPair = 64;
- static final int addContainer = addObject | addArray;
- static final int addValue = addContainer | addTerminal;
- }
+ static final int accept = 0;
+ static final int addObject = 1;
+ static final int addArray = 2;
+ static final int popObject = 4;
+ static final int popArray = 8;
+ static final int addKey = 16;
+ static final int addTerminal = 32;
+ static final int addPair = 64;
+ static final int addContainer = addObject | addArray;
+ static final int addValue = addContainer | addTerminal;
+ }
- protected interface State {
+ protected interface State {
- static final int accept = 0;
- static final int start = 1;
- static final int objectStart = 2;
- static final int arrayStart = 3;
- static final int pairEnd = 4;
- static final int elementEnd = 5;
- static final int fieldNameEnd = 6;
- }
+ static final int accept = 0;
+ static final int start = 1;
+ static final int objectStart = 2;
+ static final int arrayStart = 3;
+ static final int pairEnd = 4;
+ static final int elementEnd = 5;
+ static final int fieldNameEnd = 6;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/Line.java b/src/main/java/com/esri/core/geometry/Line.java
index 4c717691..ce7b7b23 100644
--- a/src/main/java/com/esri/core/geometry/Line.java
+++ b/src/main/java/com/esri/core/geometry/Line.java
@@ -33,13 +33,14 @@
/**
* A straight line between a pair of points.
+ *
*/
public final class Line extends Segment implements Serializable {
- @Override
- public Geometry.Type getType() {
- return Type.Line;
- }
+ @Override
+ public Geometry.Type getType() {
+ return Type.Line;
+ }
@Override
public long estimateMemorySize()
@@ -54,966 +55,970 @@ public double calculateLength2D() {
return Math.sqrt(dx * dx + dy * dy);
}
- @Override
- boolean isDegenerate(double tolerance) {
- double dx = m_xStart - m_xEnd;
- double dy = m_yStart - m_yEnd;
- return Math.sqrt(dx * dx + dy * dy) <= tolerance;
- }
-
- /**
- * Indicates if the line segment is a curve.
- */
- @Override
- public boolean isCurve() {
- return false;
- }
-
- @Override
- Point2D _getTangent(double t) {
- Point2D pt = new Point2D();
- pt.sub(getEndXY(), getStartXY());
- return pt;
- }
+ @Override
+ boolean isDegenerate(double tolerance) {
+ double dx = m_xStart - m_xEnd;
+ double dy = m_yStart - m_yEnd;
+ return Math.sqrt(dx * dx + dy * dy) <= tolerance;
+ }
- @Override
- boolean _isDegenerate(double tolerance) {
- return calculateLength2D() <= tolerance;
- }
+ /**
+ * Indicates if the line segment is a curve.
+ */
+ @Override
+ public boolean isCurve() {
+ return false;
+ }
- // HEADER DEF
+ @Override
+ Point2D _getTangent(double t) {
+ Point2D pt = new Point2D();
+ pt.sub(getEndXY(), getStartXY());
+ return pt;
+ }
- // Cpp
+ @Override
+ boolean _isDegenerate(double tolerance) {
+ return calculateLength2D() <= tolerance;
+ }
- /**
- * Creates a line segment.
- */
- public Line() {
- m_description = VertexDescriptionDesignerImpl.getDefaultDescriptor2D();
- }
+ // HEADER DEF
- Line(VertexDescription vd) {
- m_description = vd;
- }
+ // Cpp
+ /**
+ * Creates a line segment.
+ */
+ public Line() {
+ m_description = VertexDescriptionDesignerImpl.getDefaultDescriptor2D();
+ }
- public Line(double x1, double y1, double x2, double y2) {
- m_description = VertexDescriptionDesignerImpl.getDefaultDescriptor2D();
- setStartXY(x1, y1);
- setEndXY(x2, y2);
- }
+ Line(VertexDescription vd) {
+ m_description = vd;
+ }
- @Override
- public void queryEnvelope(Envelope env) {
- env.setEmpty();
- env.assignVertexDescription(m_description);
- Envelope2D env2D = new Envelope2D();
- queryEnvelope2D(env2D);
- env.setEnvelope2D(env2D);
-
- for (int i = 1, n = m_description.getAttributeCount(); i < n; i++) {
- int semantics = m_description.getSemantics(i);
- for (int iord = 0, nord = VertexDescription
- .getComponentCount(semantics); i < nord; i++) {
- Envelope1D interval = queryInterval(semantics, iord);
- env.setInterval(semantics, iord, interval);
- }
- }
- }
+ public Line(double x1, double y1, double x2, double y2) {
+ m_description = VertexDescriptionDesignerImpl.getDefaultDescriptor2D();
+ setStartXY(x1, y1);
+ setEndXY(x2, y2);
+ }
- @Override
- public void queryEnvelope2D(Envelope2D env) {
- env.setCoords(m_xStart, m_yStart, m_xEnd, m_yEnd);
- env.normalize();
- }
+ @Override
+ public void queryEnvelope(Envelope env) {
+ env.setEmpty();
+ env.assignVertexDescription(m_description);
+ Envelope2D env2D = new Envelope2D();
+ queryEnvelope2D(env2D);
+ env.setEnvelope2D(env2D);
+
+ for (int i = 1, n = m_description.getAttributeCount(); i < n; i++) {
+ int semantics = m_description.getSemantics(i);
+ for (int iord = 0, nord = VertexDescription
+ .getComponentCount(semantics); i < nord; i++) {
+ Envelope1D interval = queryInterval(semantics, iord);
+ env.setInterval(semantics, iord, interval);
+ }
+ }
+ }
- @Override
- void queryEnvelope3D(Envelope3D env) {
- env.setEmpty();
- env.merge(m_xStart, m_yStart, _getAttributeAsDbl(0, Semantics.Z, 0));
- env.merge(m_xEnd, m_yEnd, _getAttributeAsDbl(1, Semantics.Z, 0));
- }
+ @Override
+ public void queryEnvelope2D(Envelope2D env) {
+ env.setCoords(m_xStart, m_yStart, m_xEnd, m_yEnd);
+ env.normalize();
+ }
- @Override
- public void applyTransformation(Transformation2D transform) {
- _touch();
- Point2D pt = new Point2D();
- pt.x = m_xStart;
- pt.y = m_yStart;
- transform.transform(pt, pt);
- m_xStart = pt.x;
- m_yStart = pt.y;
- pt.x = m_xEnd;
- pt.y = m_yEnd;
- transform.transform(pt, pt);
- m_xEnd = pt.x;
- m_yEnd = pt.y;
- }
+ @Override
+ void queryEnvelope3D(Envelope3D env) {
+ env.setEmpty();
+ env.merge(m_xStart, m_yStart, _getAttributeAsDbl(0, Semantics.Z, 0));
+ env.merge(m_xEnd, m_yEnd, _getAttributeAsDbl(1, Semantics.Z, 0));
+ }
- @Override
- void applyTransformation(Transformation3D transform) {
- _touch();
- Point3D pt = new Point3D();
- pt.x = m_xStart;
- pt.y = m_yStart;
- pt.z = _getAttributeAsDbl(0, Semantics.Z, 0);
- pt = transform.transform(pt);
- m_xStart = pt.x;
- m_yStart = pt.y;
- _setAttribute(0, Semantics.Z, 0, pt.z);
- pt.x = m_xEnd;
- pt.y = m_yEnd;
- pt.z = _getAttributeAsDbl(1, Semantics.Z, 0);
- pt = transform.transform(pt);
- m_xEnd = pt.x;
- m_yEnd = pt.y;
- _setAttribute(1, Semantics.Z, 0, pt.z);
- }
+ @Override
+ public void applyTransformation(Transformation2D transform) {
+ _touch();
+ Point2D pt = new Point2D();
+ pt.x = m_xStart;
+ pt.y = m_yStart;
+ transform.transform(pt, pt);
+ m_xStart = pt.x;
+ m_yStart = pt.y;
+ pt.x = m_xEnd;
+ pt.y = m_yEnd;
+ transform.transform(pt, pt);
+ m_xEnd = pt.x;
+ m_yEnd = pt.y;
+ }
- @Override
- public Geometry createInstance() {
- return new Line(m_description);
- }
+ @Override
+ void applyTransformation(Transformation3D transform) {
+ _touch();
+ Point3D pt = new Point3D();
+ pt.x = m_xStart;
+ pt.y = m_yStart;
+ pt.z = _getAttributeAsDbl(0, Semantics.Z, 0);
+ pt = transform.transform(pt);
+ m_xStart = pt.x;
+ m_yStart = pt.y;
+ _setAttribute(0, Semantics.Z, 0, pt.z);
+ pt.x = m_xEnd;
+ pt.y = m_yEnd;
+ pt.z = _getAttributeAsDbl(1, Semantics.Z, 0);
+ pt = transform.transform(pt);
+ m_xEnd = pt.x;
+ m_yEnd = pt.y;
+ _setAttribute(1, Semantics.Z, 0, pt.z);
+ }
- @Override
- double _calculateArea2DHelper(double xorg, double yorg) {
- return ((m_xEnd - xorg) - (m_xStart - xorg))
- * ((m_yEnd - yorg) + (m_yStart - yorg)) * 0.5;
- }
+ @Override
+ public Geometry createInstance() {
+ return new Line(m_description);
+ }
- @Override
- double tToLength(double t) {
- return t * calculateLength2D();
- }
+ @Override
+ double _calculateArea2DHelper(double xorg, double yorg) {
+ return ((m_xEnd - xorg) - (m_xStart - xorg))
+ * ((m_yEnd - yorg) + (m_yStart - yorg)) * 0.5;
+ }
- @Override
- double lengthToT(double len) {
- return len / calculateLength2D();
- }
+ @Override
+ double tToLength(double t) {
+ return t * calculateLength2D();
+ }
- double getCoordX_(double t) {
- // Must match query_coord_2D and vice verse
- // Also match get_attribute_as_dbl
- return MathUtils.lerp(m_xStart, m_xEnd, t);
- }
+ @Override
+ double lengthToT(double len) {
+ return len / calculateLength2D();
+ }
- double getCoordY_(double t) {
- // Must match query_coord_2D and vice verse
- // Also match get_attribute_as_dbl
- return MathUtils.lerp(m_yStart, m_yEnd, t);
- }
+ double getCoordX_(double t) {
+ // Must match query_coord_2D and vice verse
+ // Also match get_attribute_as_dbl
+ return MathUtils.lerp(m_xStart, m_xEnd, t);
+ }
- @Override
- public void getCoord2D(double t, Point2D pt) {
- // We want:
- // 1. When t == 0, get exactly Start
- // 2. When t == 1, get exactly End
- // 3. When m_x_end == m_x_start, we want m_x_start exactly
- // 4. When m_y_end == m_y_start, we want m_y_start exactly
- MathUtils.lerp(m_xStart, m_yStart, m_xEnd, m_yEnd, t, pt);
- }
+ double getCoordY_(double t) {
+ // Must match query_coord_2D and vice verse
+ // Also match get_attribute_as_dbl
+ return MathUtils.lerp(m_yStart, m_yEnd, t);
+ }
- @Override
- public Segment cut(double t1, double t2) {
- SegmentBuffer segmentBuffer = new SegmentBuffer();
- cut(t1, t2, segmentBuffer);
- return segmentBuffer.get();
- }
+ @Override
+ public void getCoord2D(double t, Point2D pt) {
+ // We want:
+ // 1. When t == 0, get exactly Start
+ // 2. When t == 1, get exactly End
+ // 3. When m_x_end == m_x_start, we want m_x_start exactly
+ // 4. When m_y_end == m_y_start, we want m_y_start exactly
+ MathUtils.lerp(m_xStart, m_yStart, m_xEnd, m_yEnd, t, pt);
+ }
- @Override
- void cut(double t1, double t2, SegmentBuffer subSegmentBuffer) {
- if (subSegmentBuffer == null)
- throw new IllegalArgumentException();
-
- subSegmentBuffer.createLine();// Make sure buffer contains Line class.
- Segment subSegment = subSegmentBuffer.get();
- subSegment.assignVertexDescription(m_description);
-
- Point2D point = new Point2D();
- getCoord2D(t1, point);
- subSegment.setStartXY(point.x, point.y);
- getCoord2D(t2, point);
- subSegment.setEndXY(point.x, point.y);
-
- for (int iattr = 1, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
- int semantics = m_description._getSemanticsImpl(iattr);
- int ncomps = VertexDescription.getComponentCount(semantics);
-
- for (int ordinate = 0; ordinate < ncomps; ordinate++) {
- double value1 = getAttributeAsDbl(t1, semantics, ordinate);
- subSegment.setStartAttribute(semantics, ordinate, value1);
-
- double value2 = getAttributeAsDbl(t2, semantics, ordinate);
- subSegment.setEndAttribute(semantics, ordinate, value2);
- }
- }
- }
+ @Override
+ public Segment cut(double t1, double t2) {
+ SegmentBuffer segmentBuffer = new SegmentBuffer();
+ cut(t1, t2, segmentBuffer);
+ return segmentBuffer.get();
+ }
- @Override
- public double getAttributeAsDbl(double t, int semantics, int ordinate) {
- if (semantics == VertexDescription.Semantics.POSITION)
- return ordinate == 0 ? getCoord2D(t).x : getCoord2D(t).y;
-
- int interpolation = VertexDescription.getInterpolation(semantics);
- switch (interpolation) {
- case VertexDescription.Interpolation.NONE:
- if (t < 0.5)
- return getStartAttributeAsDbl(semantics, ordinate);
- else
- return getEndAttributeAsDbl(semantics, ordinate);
- case VertexDescription.Interpolation.LINEAR: {
- double s = getStartAttributeAsDbl(semantics, ordinate);
- double e = getEndAttributeAsDbl(semantics, ordinate);
- return MathUtils.lerp(s, e, t);
- }
- case VertexDescription.Interpolation.ANGULAR: {
- throw new GeometryException("not implemented");
- }
- }
-
- throw GeometryException.GeometryInternalError();
- }
+ @Override
+ void cut(double t1, double t2, SegmentBuffer subSegmentBuffer) {
+ if (subSegmentBuffer == null)
+ throw new IllegalArgumentException();
+
+ subSegmentBuffer.createLine();// Make sure buffer contains Line class.
+ Segment subSegment = subSegmentBuffer.get();
+ subSegment.assignVertexDescription(m_description);
+
+ Point2D point = new Point2D();
+ getCoord2D(t1, point);
+ subSegment.setStartXY(point.x, point.y);
+ getCoord2D(t2, point);
+ subSegment.setEndXY(point.x, point.y);
+
+ for (int iattr = 1, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
+ int semantics = m_description._getSemanticsImpl(iattr);
+ int ncomps = VertexDescription.getComponentCount(semantics);
+
+ for (int ordinate = 0; ordinate < ncomps; ordinate++) {
+ double value1 = getAttributeAsDbl(t1, semantics, ordinate);
+ subSegment.setStartAttribute(semantics, ordinate, value1);
+
+ double value2 = getAttributeAsDbl(t2, semantics, ordinate);
+ subSegment.setEndAttribute(semantics, ordinate, value2);
+ }
+ }
+ }
- @Override
- public double getClosestCoordinate(Point2D inputPt, boolean bExtrapolate) {
- double vx = m_xEnd - m_xStart;
- double vy = m_yEnd - m_yStart;
- double v2 = vx * vx + vy * vy;
- if (v2 == 0)
- return 0.5;
- double rx = inputPt.x - m_xStart;
- double ry = inputPt.y - m_yStart;
- double t = (rx * vx + ry * vy) / v2;
- if (!bExtrapolate) {
- if (t < 0.0)
- t = 0.0;
- else if (t > 1.0)
- t = 1.0;
- }
-
- return t;
- }
+ @Override
+ public double getAttributeAsDbl(double t, int semantics, int ordinate) {
+ if (semantics == VertexDescription.Semantics.POSITION)
+ return ordinate == 0 ? getCoord2D(t).x : getCoord2D(t).y;
+
+ int interpolation = VertexDescription.getInterpolation(semantics);
+ switch (interpolation) {
+ case VertexDescription.Interpolation.NONE:
+ if (t < 0.5)
+ return getStartAttributeAsDbl(semantics, ordinate);
+ else
+ return getEndAttributeAsDbl(semantics, ordinate);
+ case VertexDescription.Interpolation.LINEAR: {
+ double s = getStartAttributeAsDbl(semantics, ordinate);
+ double e = getEndAttributeAsDbl(semantics, ordinate);
+ return MathUtils.lerp(s, e, t);
+ }
+ case VertexDescription.Interpolation.ANGULAR: {
+ throw new GeometryException("not implemented");
+ }
+ }
+
+ throw GeometryException.GeometryInternalError();
+ }
- @Override
- public int intersectionWithAxis2D(boolean b_axis_x, double ordinate,
- double[] result_ordinates, double[] parameters) {
- if (b_axis_x) {
- double a = (m_yEnd - m_yStart);
+ @Override
+ public double getClosestCoordinate(Point2D inputPt, boolean bExtrapolate) {
+ double vx = m_xEnd - m_xStart;
+ double vy = m_yEnd - m_yStart;
+ double v2 = vx * vx + vy * vy;
+ if (v2 == 0)
+ return 0.5;
+ double rx = inputPt.x - m_xStart;
+ double ry = inputPt.y - m_yStart;
+ double t = (rx * vx + ry * vy) / v2;
+ if (!bExtrapolate) {
+ if (t < 0.0)
+ t = 0.0;
+ else if (t > 1.0)
+ t = 1.0;
+ }
+
+ return t;
+ }
- if (a == 0)
- return (ordinate == m_yEnd) ? -1 : 0;
+ @Override
+ public int intersectionWithAxis2D(boolean b_axis_x, double ordinate,
+ double[] result_ordinates, double[] parameters) {
+ if (b_axis_x) {
+ double a = (m_yEnd - m_yStart);
- double t = (ordinate - m_yStart) / a;
+ if (a == 0)
+ return (ordinate == m_yEnd) ? -1 : 0;
- if (t < 0.0 || t > 1.0)
- return 0;
+ double t = (ordinate - m_yStart) / a;
- if (result_ordinates != null)
- (result_ordinates)[0] = getCoordX_(t);
+ if (t < 0.0 || t > 1.0)
+ return 0;
- if (parameters != null)
- (parameters)[0] = t;
+ if (result_ordinates != null)
+ (result_ordinates)[0] = getCoordX_(t);
- return 1;
- } else {
- double a = (m_xEnd - m_xStart);
+ if (parameters != null)
+ (parameters)[0] = t;
- if (a == 0)
- return (ordinate == m_xEnd) ? -1 : 0;
+ return 1;
+ } else {
+ double a = (m_xEnd - m_xStart);
- double t = (ordinate - m_xStart) / a;
+ if (a == 0)
+ return (ordinate == m_xEnd) ? -1 : 0;
- if (t < 0.0 || t > 1.0)
- return 0;
+ double t = (ordinate - m_xStart) / a;
- if (result_ordinates != null)
- (result_ordinates)[0] = getCoordY_(t);
+ if (t < 0.0 || t > 1.0)
+ return 0;
- if (parameters != null)
- (parameters)[0] = t;
+ if (result_ordinates != null)
+ (result_ordinates)[0] = getCoordY_(t);
- return 1;
- }
- }
+ if (parameters != null)
+ (parameters)[0] = t;
- // line segment can have 0 or 1 intersection interval with clipEnv2D.
- // The function return 0 or 2 segParams (e.g. 0.0, 0.4; or 0.1, 0.9; or 0.6,
- // 1.0; or 0.0, 1.0)
- // segParams will be sorted in ascending order; the order of the
- // envelopeDistances will correspond (i.e. the envelopeDistances may not be
- // in ascending order);
- // an envelopeDistance can be -1.0 if the corresponding endpoint is properly
- // inside clipEnv2D.
- int intersectionWithEnvelope2D(Envelope2D clipEnv2D,
- boolean includeEnvBoundary, double[] segParams,
- double[] envelopeDistances) {
- Point2D p1 = getStartXY();
- Point2D p2 = getEndXY();
-
- // includeEnvBoundary xxx ???
-
- int modified = clipEnv2D.clipLine(p1, p2, 0, segParams,
- envelopeDistances);
- return modified != 0 ? 2 : 0;
+ return 1;
+ }
+ }
- }
+ // line segment can have 0 or 1 intersection interval with clipEnv2D.
+ // The function return 0 or 2 segParams (e.g. 0.0, 0.4; or 0.1, 0.9; or 0.6,
+ // 1.0; or 0.0, 1.0)
+ // segParams will be sorted in ascending order; the order of the
+ // envelopeDistances will correspond (i.e. the envelopeDistances may not be
+ // in ascending order);
+ // an envelopeDistance can be -1.0 if the corresponding endpoint is properly
+ // inside clipEnv2D.
+ int intersectionWithEnvelope2D(Envelope2D clipEnv2D,
+ boolean includeEnvBoundary, double[] segParams,
+ double[] envelopeDistances) {
+ Point2D p1 = getStartXY();
+ Point2D p2 = getEndXY();
+
+ // includeEnvBoundary xxx ???
+
+ int modified = clipEnv2D.clipLine(p1, p2, 0, segParams,
+ envelopeDistances);
+ return modified != 0 ? 2 : 0;
- @Override
- double intersectionOfYMonotonicWithAxisX(double y, double x_parallel) {
- double a = (m_yEnd - m_yStart);
-
- if (a == 0)
- return (y == m_yEnd) ? x_parallel : NumberUtils.NaN();
-
- double t = (y - m_yStart) / a;
- assert (t >= 0 && t <= 1.0);
- // double t_1 = 1.0 - t;
- // assert(t + t_1 == 1.0);
- double resx = getCoordX_(t);
- if (t == 1.0)
- resx = m_xEnd;
- assert ((resx >= m_xStart && resx <= m_xEnd) || (resx <= m_xStart && resx >= m_xEnd));
- return resx;
- }
+ }
- @Override
- boolean _isIntersectingPoint(Point2D pt, double tolerance,
- boolean bExcludeExactEndpoints) {
- return _intersection(pt, tolerance, bExcludeExactEndpoints) >= 0;// must
- // use
- // same
- // method
- // that
- // the
- // intersection
- // routine
- // uses.
- }
+ @Override
+ double intersectionOfYMonotonicWithAxisX(double y, double x_parallel) {
+ double a = (m_yEnd - m_yStart);
+
+ if (a == 0)
+ return (y == m_yEnd) ? x_parallel : NumberUtils.NaN();
+
+ double t = (y - m_yStart) / a;
+ assert (t >= 0 && t <= 1.0);
+ // double t_1 = 1.0 - t;
+ // assert(t + t_1 == 1.0);
+ double resx = getCoordX_(t);
+ if (t == 1.0)
+ resx = m_xEnd;
+ assert ((resx >= m_xStart && resx <= m_xEnd) || (resx <= m_xStart && resx >= m_xEnd));
+ return resx;
+ }
- /**
- * Returns True if point and the segment intersect (not disjoint) for the
- * given tolerance.
- */
- @Override
- public boolean isIntersecting(Point2D pt, double tolerance) {
- return _isIntersectingPoint(pt, tolerance, false);
- }
+ @Override
+ boolean _isIntersectingPoint(Point2D pt, double tolerance,
+ boolean bExcludeExactEndpoints) {
+ return _intersection(pt, tolerance, bExcludeExactEndpoints) >= 0;// must
+ // use
+ // same
+ // method
+ // that
+ // the
+ // intersection
+ // routine
+ // uses.
+ }
- void orientBottomUp_() {
- if (m_yEnd < m_yStart || (m_yEnd == m_yStart && m_xEnd < m_xStart)) {
- double x = m_xStart;
- m_xStart = m_xEnd;
- m_xEnd = x;
-
- double y = m_yStart;
- m_yStart = m_yEnd;
- m_yEnd = y;
- for (int i = 0, n = m_description.getTotalComponentCount() - 2; i < n; i++) {
- double a = m_attributes[i];
- m_attributes[i] = m_attributes[i + n];
- m_attributes[i + n] = a;
- }
- }
- }
+ /**
+ * Returns True if point and the segment intersect (not disjoint) for the
+ * given tolerance.
+ */
+ @Override
+ public boolean isIntersecting(Point2D pt, double tolerance) {
+ return _isIntersectingPoint(pt, tolerance, false);
+ }
- // return -1 for the left side from the infinite line passing through thais
- // Line, 1 for the right side of the line, 0 if on the line (in the bounds
- // of the roundoff error)
- int _side(Point2D pt) {
- return _side(pt.x, pt.y);
- }
+ void orientBottomUp_() {
+ if (m_yEnd < m_yStart || (m_yEnd == m_yStart && m_xEnd < m_xStart)) {
+ double x = m_xStart;
+ m_xStart = m_xEnd;
+ m_xEnd = x;
+
+ double y = m_yStart;
+ m_yStart = m_yEnd;
+ m_yEnd = y;
+ for (int i = 0, n = m_description.getTotalComponentCount() - 2; i < n; i++) {
+ double a = m_attributes[i];
+ m_attributes[i] = m_attributes[i + n];
+ m_attributes[i + n] = a;
+ }
+ }
+ }
- // return -1 for the left side from the infinite line passing through thais
- // Line, 1 for the right side of the line, 0 if on the line (in the bounds
- // of the roundoff error)
- int _side(double ptX, double ptY) {
- Point2D v1 = new Point2D(ptX, ptY);
- v1.sub(getStartXY());
- Point2D v2 = new Point2D();
- v2.sub(getEndXY(), getStartXY());
- double cross = v2.crossProduct(v1);
- double crossError = 4 * NumberUtils.doubleEps()
- * (Math.abs(v2.x * v1.y) + Math.abs(v2.y * v1.x));
- return cross > crossError ? -1 : cross < -crossError ? 1 : 0;
- }
+ // return -1 for the left side from the infinite line passing through thais
+ // Line, 1 for the right side of the line, 0 if on the line (in the bounds
+ // of the roundoff error)
+ int _side(Point2D pt) {
+ return _side(pt.x, pt.y);
+ }
- double _intersection(Point2D pt, double tolerance,
- boolean bExcludeExactEndPoints) {
- Point2D v = new Point2D();
- Point2D start = new Point2D();
-
- // Test start point distance to pt.
- start.setCoords(m_xStart, m_yStart);
- v.sub(pt, start);
- double vlength = v.length();
- double vLengthError = vlength * 3 * NumberUtils.doubleEps();
- if (vlength <= Math.max(tolerance, vLengthError)) {
- assert (vlength != 0 || pt.isEqual(start));// probably never asserts
- if (bExcludeExactEndPoints && vlength == 0)
- return NumberUtils.TheNaN;
- else
- return 0;
- }
-
- Point2D end2D = getEndXY();
- // Test end point distance to pt.
- v.sub(pt, end2D);
- vlength = v.length();
- vLengthError = vlength * 3 * NumberUtils.doubleEps();
- if (vlength <= Math.max(tolerance, vLengthError)) {
- assert (vlength != 0 || pt.isEqual(end2D));// probably never asserts
- if (bExcludeExactEndPoints && vlength == 0)
- return NumberUtils.TheNaN;
- else
- return 1.0;
- }
-
- // Find a distance from the line to pt.
- v.setCoords(m_xEnd - m_xStart, m_yEnd - m_yStart);
- double len = v.length();
- if (len > 0) {
- double invertedLength = 1.0 / len;
- v.scale(invertedLength);
- Point2D relativePoint = new Point2D();
- relativePoint.sub(pt, start);
- double projection = relativePoint.dotProduct(v);
- double projectionError = 8 * relativePoint._dotProductAbs(v)
- * NumberUtils.doubleEps();// See Error Estimation Rules In
- // Borg.docx
- v.leftPerpendicular();// get left normal to v
- double distance = relativePoint.dotProduct(v);
- double distanceError = 8 * relativePoint._dotProductAbs(v)
- * NumberUtils.doubleEps();// See Error Estimation Rules In
- // Borg.docx
-
- double perror = Math.max(tolerance, projectionError);
- if (projection < -perror || projection > len + perror)
- return NumberUtils.TheNaN;
-
- double merror = Math.max(tolerance, distanceError);
- if (Math.abs(distance) <= merror) {
- double t = projection * invertedLength;
- t = NumberUtils.snap(t, 0.0, 1.0);
- Point2D ptOnLine = new Point2D();
- getCoord2D(t, ptOnLine);
- if (Point2D.distance(ptOnLine, pt) <= tolerance) {
- if (t < 0.5) {
- if (Point2D.distance(ptOnLine, start) <= tolerance)// the
- // projected
- // point
- // is
- // close
- // to
- // the
- // start
- // point.
- // Need
- // to
- // return
- // 0.
- return 0;
- } else if (Point2D.distance(ptOnLine, end2D) <= tolerance)// the
- // projected
- // point
- // is
- // close
- // to
- // the
- // end
- // point.
- // Need
- // to
- // return
- // 1.0.
- return 1.0;
-
- return t;
- }
- }
- }
-
- return NumberUtils.TheNaN;
- }
+ // return -1 for the left side from the infinite line passing through thais
+ // Line, 1 for the right side of the line, 0 if on the line (in the bounds
+ // of the roundoff error)
+ int _side(double ptX, double ptY) {
+ Point2D v1 = new Point2D(ptX, ptY);
+ v1.sub(getStartXY());
+ Point2D v2 = new Point2D();
+ v2.sub(getEndXY(), getStartXY());
+ double cross = v2.crossProduct(v1);
+ double crossError = 4 * NumberUtils.doubleEps()
+ * (Math.abs(v2.x * v1.y) + Math.abs(v2.y * v1.x));
+ return cross > crossError ? -1 : cross < -crossError ? 1 : 0;
+ }
- @Override
- public boolean equals(Object other) {
- if (other == null)
- return false;
+ double _intersection(Point2D pt, double tolerance,
+ boolean bExcludeExactEndPoints) {
+ Point2D v = new Point2D();
+ Point2D start = new Point2D();
+
+ // Test start point distance to pt.
+ start.setCoords(m_xStart, m_yStart);
+ v.sub(pt, start);
+ double vlength = v.length();
+ double vLengthError = vlength * 3 * NumberUtils.doubleEps();
+ if (vlength <= Math.max(tolerance, vLengthError)) {
+ assert (vlength != 0 || pt.isEqual(start));// probably never asserts
+ if (bExcludeExactEndPoints && vlength == 0)
+ return NumberUtils.TheNaN;
+ else
+ return 0;
+ }
+
+ Point2D end2D = getEndXY();
+ // Test end point distance to pt.
+ v.sub(pt, end2D);
+ vlength = v.length();
+ vLengthError = vlength * 3 * NumberUtils.doubleEps();
+ if (vlength <= Math.max(tolerance, vLengthError)) {
+ assert (vlength != 0 || pt.isEqual(end2D));// probably never asserts
+ if (bExcludeExactEndPoints && vlength == 0)
+ return NumberUtils.TheNaN;
+ else
+ return 1.0;
+ }
+
+ // Find a distance from the line to pt.
+ v.setCoords(m_xEnd - m_xStart, m_yEnd - m_yStart);
+ double len = v.length();
+ if (len > 0) {
+ double invertedLength = 1.0 / len;
+ v.scale(invertedLength);
+ Point2D relativePoint = new Point2D();
+ relativePoint.sub(pt, start);
+ double projection = relativePoint.dotProduct(v);
+ double projectionError = 8 * relativePoint._dotProductAbs(v)
+ * NumberUtils.doubleEps();// See Error Estimation Rules In
+ // Borg.docx
+ v.leftPerpendicular();// get left normal to v
+ double distance = relativePoint.dotProduct(v);
+ double distanceError = 8 * relativePoint._dotProductAbs(v)
+ * NumberUtils.doubleEps();// See Error Estimation Rules In
+ // Borg.docx
+
+ double perror = Math.max(tolerance, projectionError);
+ if (projection < -perror || projection > len + perror)
+ return NumberUtils.TheNaN;
+
+ double merror = Math.max(tolerance, distanceError);
+ if (Math.abs(distance) <= merror) {
+ double t = projection * invertedLength;
+ t = NumberUtils.snap(t, 0.0, 1.0);
+ Point2D ptOnLine = new Point2D();
+ getCoord2D(t, ptOnLine);
+ if (Point2D.distance(ptOnLine, pt) <= tolerance) {
+ if (t < 0.5) {
+ if (Point2D.distance(ptOnLine, start) <= tolerance)// the
+ // projected
+ // point
+ // is
+ // close
+ // to
+ // the
+ // start
+ // point.
+ // Need
+ // to
+ // return
+ // 0.
+ return 0;
+ } else if (Point2D.distance(ptOnLine, end2D) <= tolerance)// the
+ // projected
+ // point
+ // is
+ // close
+ // to
+ // the
+ // end
+ // point.
+ // Need
+ // to
+ // return
+ // 1.0.
+ return 1.0;
+
+ return t;
+ }
+ }
+ }
+
+ return NumberUtils.TheNaN;
+ }
- if (other == this)
- return true;
+ @Override
+ public boolean equals(Object other) {
+ if (other == null)
+ return false;
- if (other.getClass() != getClass())
- return false;
+ if (other == this)
+ return true;
- return _equalsImpl((Segment) other);
- }
+ if (other.getClass() != getClass())
+ return false;
- boolean equals(Line other) {
- if (other == this)
- return true;
+ return _equalsImpl((Segment)other);
+ }
+
+ @Override
+ public int hashCode() {
+ return super.hashCode();
+ }
- if (!(other instanceof Line))
- return false;
+ boolean equals(Line other) {
+ if (other == this)
+ return true;
- return _equalsImpl((Segment) other);
- }
+ if (!(other instanceof Line))
+ return false;
- boolean _projectionIntersectHelper(Line other, Point2D v, boolean bStart) {
- // v is the vector in the direction of this line == end - start.
- double orgX = bStart ? m_xStart : m_xEnd;
- double orgY = bStart ? m_yStart : m_yEnd;
- Point2D m = new Point2D();
- m.x = other.getEndX() - orgX;
- m.y = other.getEndY() - orgY;
- double dot = v.dotProduct(m);
- double dotError = 3 * NumberUtils.doubleEps() * v._dotProductAbs(m);
- if (dot > dotError) {
- m.x = other.getStartX() - orgX;
- m.y = other.getStartY() - orgY;
- double dot2 = v.dotProduct(m);
- double dotError2 = 3 * NumberUtils.doubleEps()
- * v._dotProductAbs(m);
- return dot2 <= dotError2;
- }
-
- return true;
- }
+ return _equalsImpl((Segment) other);
+ }
- boolean _projectionIntersect(Line other) {
- // This function returns true, if the "other"'s projection on "this"
- Point2D v = new Point2D();
- v.x = m_xEnd - m_xStart;
- v.y = m_yEnd - m_yStart;
- if (!_projectionIntersectHelper(other, v, false))
- return false; // Both other.Start and other.End projections on
- // "this" lie to the right of the this.End
-
- v.negate();
- if (!_projectionIntersectHelper(other, v, true))
- return false; // Both other.Start and other.End projections on
- // "this" lie to the left of the this.End
-
- return true;
- }
+ boolean _projectionIntersectHelper(Line other, Point2D v, boolean bStart) {
+ // v is the vector in the direction of this line == end - start.
+ double orgX = bStart ? m_xStart : m_xEnd;
+ double orgY = bStart ? m_yStart : m_yEnd;
+ Point2D m = new Point2D();
+ m.x = other.getEndX() - orgX;
+ m.y = other.getEndY() - orgY;
+ double dot = v.dotProduct(m);
+ double dotError = 3 * NumberUtils.doubleEps() * v._dotProductAbs(m);
+ if (dot > dotError) {
+ m.x = other.getStartX() - orgX;
+ m.y = other.getStartY() - orgY;
+ double dot2 = v.dotProduct(m);
+ double dotError2 = 3 * NumberUtils.doubleEps()
+ * v._dotProductAbs(m);
+ return dot2 <= dotError2;
+ }
+
+ return true;
+ }
- // Tests if two lines intersect using projection of one line to another.
- static boolean _isIntersectingHelper(Line line1, Line line2) {
- int s11 = line1._side(line2.m_xStart, line2.m_yStart);
- int s12 = line1._side(line2.m_xEnd, line2.m_yEnd);
- if (s11 < 0 && s12 < 0 || s11 > 0 && s12 > 0)
- return false;// no intersection. The line2 lies to one side of an
- // infinite line passing through line1
-
- int s21 = line2._side(line1.m_xStart, line1.m_yStart);
- int s22 = line2._side(line1.m_xEnd, line1.m_yEnd);
- if (s21 < 0 && s22 < 0 || s21 > 0 && s22 > 0)
- return false;// no intersection.The line1 lies to one side of an
- // infinite line passing through line2
-
- double len1 = line1.calculateLength2D();
- double len2 = line2.calculateLength2D();
- if (len1 > len2) {
- return line1._projectionIntersect(line2);
- } else {
- return line2._projectionIntersect(line1);
- }
- }
+ boolean _projectionIntersect(Line other) {
+ // This function returns true, if the "other"'s projection on "this"
+ Point2D v = new Point2D();
+ v.x = m_xEnd - m_xStart;
+ v.y = m_yEnd - m_yStart;
+ if (!_projectionIntersectHelper(other, v, false))
+ return false; // Both other.Start and other.End projections on
+ // "this" lie to the right of the this.End
+
+ v.negate();
+ if (!_projectionIntersectHelper(other, v, true))
+ return false; // Both other.Start and other.End projections on
+ // "this" lie to the left of the this.End
+
+ return true;
+ }
- static Point2D _intersectHelper1(Line line1, Line line2, double tolerance) {
- Point2D result = new Point2D(NumberUtils.NaN(), NumberUtils.NaN());
- double k1x = line1.m_xEnd - line1.m_xStart;
- double k1y = line1.m_yEnd - line1.m_yStart;
- double k2x = line2.m_xEnd - line2.m_xStart;
- double k2y = line2.m_yEnd - line2.m_yStart;
-
- double det = k2x * k1y - k1x * k2y;
- if (det == 0)
- return result;
-
- // estimate roundoff error for det:
- double errdet = 4 * NumberUtils.doubleEps()
- * (Math.abs(k2x * k1y) + Math.abs(k1x * k2y));
-
- double bx = line2.m_xStart - line1.m_xStart;
- double by = line2.m_yStart - line1.m_yStart;
-
- double a0 = (k2x * by - bx * k2y);
- double a0error = 4 * NumberUtils.doubleEps()
- * (Math.abs(k2x * by) + Math.abs(bx * k2y));
- double t0 = a0 / det;
- double absdet = Math.abs(det);
- double t0error = (a0error * absdet + errdet * Math.abs(a0))
- / (det * det) + NumberUtils.doubleEps() * Math.abs(t0);
- if (t0 < -t0error || t0 > 1.0 + t0error)
- return result;
-
- double a1 = (k1x * by - bx * k1y);
- double a1error = 4 * NumberUtils.doubleEps()
- * (Math.abs(k1x * by) + Math.abs(bx * k1y));
- double t1 = a1 / det;
- double t1error = (a1error * absdet + errdet * Math.abs(a1))
- / (det * det) + NumberUtils.doubleEps() * Math.abs(t1);
-
- if (t1 < -t1error || t1 > 1.0 + t1error)
- return result;
-
- double t0r = NumberUtils.snap(t0, 0.0, 1.0);
- double t1r = NumberUtils.snap(t1, 0.0, 1.0);
- Point2D pt0 = line1.getCoord2D(t0r);
- Point2D pt1 = line2.getCoord2D(t1r);
- Point2D pt = new Point2D();
- pt.sub(pt0, pt1);
- if (pt.length() > tolerance) {
- // Roundoff errors cause imprecise result. Try recalculate.
- // 1. Use averaged point and recalculate the t values
- // Point2D pt;
- pt.add(pt0, pt1);
- pt.scale(0.5);
- t0r = line1.getClosestCoordinate(pt, false);
- t1r = line2.getClosestCoordinate(pt, false);
- Point2D pt01 = line1.getCoord2D(t0r);
- Point2D pt11 = line2.getCoord2D(t1r);
- pt01.sub(pt11);
- if (pt01.length() > tolerance) {
- // Seems to be no intersection here actually. Return NaNs
- return result;
- }
- }
-
- result.setCoords(t0r, t1r);
- return result;
- }
+ // Tests if two lines intersect using projection of one line to another.
+ static boolean _isIntersectingHelper(Line line1, Line line2) {
+ int s11 = line1._side(line2.m_xStart, line2.m_yStart);
+ int s12 = line1._side(line2.m_xEnd, line2.m_yEnd);
+ if (s11 < 0 && s12 < 0 || s11 > 0 && s12 > 0)
+ return false;// no intersection. The line2 lies to one side of an
+ // infinite line passing through line1
+
+ int s21 = line2._side(line1.m_xStart, line1.m_yStart);
+ int s22 = line2._side(line1.m_xEnd, line1.m_yEnd);
+ if (s21 < 0 && s22 < 0 || s21 > 0 && s22 > 0)
+ return false;// no intersection.The line1 lies to one side of an
+ // infinite line passing through line2
+
+ double len1 = line1.calculateLength2D();
+ double len2 = line2.calculateLength2D();
+ if (len1 > len2) {
+ return line1._projectionIntersect(line2);
+ } else {
+ return line2._projectionIntersect(line1);
+ }
+ }
- static int _isIntersectingLineLine(Line line1, Line line2,
- double tolerance, boolean bExcludeExactEndpoints) {
- // _ASSERT(line1 != line2);
- // Check for the endpoints.
- // The bExcludeExactEndpoints is True, means we care only about overlaps
- // and real intersections, but do not care if the endpoints are exactly
- // equal.
- // bExcludeExactEndpoints is used in Cracking check test, because during
- // cracking test all points are either coincident or further than the
- // tolerance.
- int counter = 0;
- if (line1.m_xStart == line2.m_xStart
- && line1.m_yStart == line2.m_yStart
- || line1.m_xStart == line2.m_xEnd
- && line1.m_yStart == line2.m_yEnd) {
- counter++;
- if (!bExcludeExactEndpoints)
- return 1;
- }
-
- if (line1.m_xEnd == line2.m_xStart && line1.m_yEnd == line2.m_yStart
- || line1.m_xEnd == line2.m_xEnd && line1.m_yEnd == line2.m_yEnd) {
- counter++;
- if (counter == 2)
- return 2; // counter == 2 means both endpoints coincide (Lines
- // overlap).
- if (!bExcludeExactEndpoints)
- return 1;
- }
-
- if (line2._isIntersectingPoint(line1.getStartXY(), tolerance, true))
- return 1;// return true;
- if (line2._isIntersectingPoint(line1.getEndXY(), tolerance, true))
- return 1;// return true;
- if (line1._isIntersectingPoint(line2.getStartXY(), tolerance, true))
- return 1;// return true;
- if (line1._isIntersectingPoint(line2.getEndXY(), tolerance, true))
- return 1;// return true;
-
- if (bExcludeExactEndpoints && (counter != 0))
- return 0;// return false;
-
- return _isIntersectingHelper(line1, line2) == false ? 0 : 1;
- }
+ static Point2D _intersectHelper1(Line line1, Line line2, double tolerance) {
+ Point2D result = new Point2D(NumberUtils.NaN(), NumberUtils.NaN());
+ double k1x = line1.m_xEnd - line1.m_xStart;
+ double k1y = line1.m_yEnd - line1.m_yStart;
+ double k2x = line2.m_xEnd - line2.m_xStart;
+ double k2y = line2.m_yEnd - line2.m_yStart;
+
+ double det = k2x * k1y - k1x * k2y;
+ if (det == 0)
+ return result;
+
+ // estimate roundoff error for det:
+ double errdet = 4 * NumberUtils.doubleEps()
+ * (Math.abs(k2x * k1y) + Math.abs(k1x * k2y));
+
+ double bx = line2.m_xStart - line1.m_xStart;
+ double by = line2.m_yStart - line1.m_yStart;
+
+ double a0 = (k2x * by - bx * k2y);
+ double a0error = 4 * NumberUtils.doubleEps()
+ * (Math.abs(k2x * by) + Math.abs(bx * k2y));
+ double t0 = a0 / det;
+ double absdet = Math.abs(det);
+ double t0error = (a0error * absdet + errdet * Math.abs(a0))
+ / (det * det) + NumberUtils.doubleEps() * Math.abs(t0);
+ if (t0 < -t0error || t0 > 1.0 + t0error)
+ return result;
+
+ double a1 = (k1x * by - bx * k1y);
+ double a1error = 4 * NumberUtils.doubleEps()
+ * (Math.abs(k1x * by) + Math.abs(bx * k1y));
+ double t1 = a1 / det;
+ double t1error = (a1error * absdet + errdet * Math.abs(a1))
+ / (det * det) + NumberUtils.doubleEps() * Math.abs(t1);
+
+ if (t1 < -t1error || t1 > 1.0 + t1error)
+ return result;
+
+ double t0r = NumberUtils.snap(t0, 0.0, 1.0);
+ double t1r = NumberUtils.snap(t1, 0.0, 1.0);
+ Point2D pt0 = line1.getCoord2D(t0r);
+ Point2D pt1 = line2.getCoord2D(t1r);
+ Point2D pt = new Point2D();
+ pt.sub(pt0, pt1);
+ if (pt.length() > tolerance) {
+ // Roundoff errors cause imprecise result. Try recalculate.
+ // 1. Use averaged point and recalculate the t values
+ // Point2D pt;
+ pt.add(pt0, pt1);
+ pt.scale(0.5);
+ t0r = line1.getClosestCoordinate(pt, false);
+ t1r = line2.getClosestCoordinate(pt, false);
+ Point2D pt01 = line1.getCoord2D(t0r);
+ Point2D pt11 = line2.getCoord2D(t1r);
+ pt01.sub(pt11);
+ if (pt01.length() > tolerance) {
+ // Seems to be no intersection here actually. Return NaNs
+ return result;
+ }
+ }
+
+ result.setCoords(t0r, t1r);
+ return result;
+ }
- int _intersectLineLineExact(Line line1, Line line2,
- Point2D[] intersectionPoints, double[] param1, double[] param2) {
- int counter = 0;
- if (line1.m_xStart == line2.m_xStart
- && line1.m_yStart == line2.m_yStart) {
- if (param1 != null)// if (param1)
- param1[counter] = 0.0;
- if (param2 != null)// if (param2)
- param2[counter] = 0.0;
-
- if (intersectionPoints != null)// if (intersectionPoints)
- intersectionPoints[counter] = Point2D.construct(line1.m_xStart,
- line1.m_yStart);
-
- counter++;
- }
-
- if (line1.m_xStart == line2.m_xEnd && line1.m_yStart == line2.m_yEnd) {
- if (param1 != null)// if (param1)
- param1[counter] = 0.0;
- if (param2 != null)// if (param2)
- param2[counter] = 1.0;
-
- if (intersectionPoints != null)// if (intersectionPoints)
- intersectionPoints[counter] = Point2D.construct(line1.m_xStart,
- line1.m_yStart);
-
- counter++;
- }
-
- if (line1.m_xEnd == line2.m_xStart && line1.m_yEnd == line2.m_yStart) {
- if (counter == 2) {// both segments a degenerate
- if (param1 != null)// if (param1)
- {
- param1[0] = 0.0;
- param1[1] = 1.0;
- }
- if (param2 != null)// if (param2)
- {
- param2[0] = 1.0;
- }
-
- if (intersectionPoints != null)// if (intersectionPoints)
- {
- intersectionPoints[0] = Point2D.construct(line1.m_xEnd,
- line1.m_yEnd);
- intersectionPoints[1] = Point2D.construct(line1.m_xEnd,
- line1.m_yEnd);
- }
-
- return counter;
- }
-
- if (param1 != null)// if (param1)
- param1[counter] = 1.0;
- if (param2 != null)// if (param2)
- param2[counter] = 0.0;
-
- if (intersectionPoints != null)// if (intersectionPoints)
- intersectionPoints[counter] = Point2D.construct(line1.m_xEnd,
- line1.m_yEnd);
-
- counter++;
- }
-
- if (line1.m_xEnd == line2.m_xEnd && line1.m_yEnd == line2.m_yEnd) {
- if (counter == 2) {// both segments are degenerate
- if (param1 != null)// if (param1)
- {
- param1[0] = 0.0;
- param1[1] = 1.0;
- }
- if (param2 != null)// if (param2)
- {
- param2[0] = 1.0;
- }
-
- if (intersectionPoints != null)// if (intersectionPoints)
- {
- intersectionPoints[0] = Point2D.construct(line1.m_xEnd,
- line1.m_yEnd);
- intersectionPoints[1] = Point2D.construct(line1.m_xEnd,
- line1.m_yEnd);
- }
-
- return counter;
- }
-
- if (param1 != null)// if (param1)
- param1[counter] = 1.0;
- if (param2 != null)// if (param2)
- param2[counter] = 1.0;
-
- if (intersectionPoints != null)// if (intersectionPoints)
- intersectionPoints[counter] = Point2D.construct(line1.m_xEnd,
- line1.m_yEnd);
- counter++;
- }
-
- return counter;
- }
+ static int _isIntersectingLineLine(Line line1, Line line2,
+ double tolerance, boolean bExcludeExactEndpoints) {
+ // _ASSERT(line1 != line2);
+ // Check for the endpoints.
+ // The bExcludeExactEndpoints is True, means we care only about overlaps
+ // and real intersections, but do not care if the endpoints are exactly
+ // equal.
+ // bExcludeExactEndpoints is used in Cracking check test, because during
+ // cracking test all points are either coincident or further than the
+ // tolerance.
+ int counter = 0;
+ if (line1.m_xStart == line2.m_xStart
+ && line1.m_yStart == line2.m_yStart
+ || line1.m_xStart == line2.m_xEnd
+ && line1.m_yStart == line2.m_yEnd) {
+ counter++;
+ if (!bExcludeExactEndpoints)
+ return 1;
+ }
+
+ if (line1.m_xEnd == line2.m_xStart && line1.m_yEnd == line2.m_yStart
+ || line1.m_xEnd == line2.m_xEnd && line1.m_yEnd == line2.m_yEnd) {
+ counter++;
+ if (counter == 2)
+ return 2; // counter == 2 means both endpoints coincide (Lines
+ // overlap).
+ if (!bExcludeExactEndpoints)
+ return 1;
+ }
+
+ if (line2._isIntersectingPoint(line1.getStartXY(), tolerance, true))
+ return 1;// return true;
+ if (line2._isIntersectingPoint(line1.getEndXY(), tolerance, true))
+ return 1;// return true;
+ if (line1._isIntersectingPoint(line2.getStartXY(), tolerance, true))
+ return 1;// return true;
+ if (line1._isIntersectingPoint(line2.getEndXY(), tolerance, true))
+ return 1;// return true;
+
+ if (bExcludeExactEndpoints && (counter != 0))
+ return 0;// return false;
+
+ return _isIntersectingHelper(line1, line2) == false ? 0 : 1;
+ }
- static int _intersectLineLine(Line line1, Line line2,
- Point2D[] intersectionPoints, double[] param1, double[] param2,
- double tolerance) {
- // _ASSERT(!param1 && !param2 || param1);
- int counter = 0;
- // Test the end points for exact coincidence.
- double t11 = line1._intersection(line2.getStartXY(), tolerance, false);
- double t12 = line1._intersection(line2.getEndXY(), tolerance, false);
- double t21 = line2._intersection(line1.getStartXY(), tolerance, false);
- double t22 = line2._intersection(line1.getEndXY(), tolerance, false);
-
- if (!NumberUtils.isNaN(t11)) {
- if (param1 != null)// if (param1)
- param1[counter] = t11;
- if (param2 != null)// if (param2)
- param2[counter] = 0;
-
- if (intersectionPoints != null)// if (intersectionPoints)
- intersectionPoints[counter] = Point2D.construct(line2.m_xStart,
- line2.m_yStart);
- counter++;
- }
-
- if (!NumberUtils.isNaN(t12)) {
- if (param1 != null)// if (param1)
- param1[counter] = t12;
- if (param2 != null)// if (param2)
- param2[counter] = 1.0;
-
- if (intersectionPoints != null)// if (intersectionPoints)
- intersectionPoints[counter] = Point2D.construct(line2.m_xEnd,
- line2.m_yEnd);
- counter++;
- }
-
- if (counter != 2 && !NumberUtils.isNaN(t21)) {
- if (!(t11 == 0 && t21 == 0) && !(t12 == 0 && t21 == 1.0))// the "if"
- // makes
- // sure
- // this
- // has
- // not
- // been
- // already
- // calculated
- {
- if (param1 != null)// if (param1)
- param1[counter] = 0;
- if (param2 != null)// if (param2)
- param2[counter] = t21;
-
- if (intersectionPoints != null)// if (intersectionPoints)
- intersectionPoints[counter] = Point2D.construct(
- line1.m_xStart, line1.m_yStart);
- counter++;
- }
- }
-
- if (counter != 2 && !NumberUtils.isNaN(t22)) {
- if (!(t11 == 1.0 && t22 == 0) && !(t12 == 1.0 && t22 == 1.0))// the
- // "if"
- // makes
- // sure
- // this
- // has
- // not
- // been
- // already
- // calculated
- {
- if (param1 != null)// if (param1)
- param1[counter] = 1.0;
- if (param2 != null)// if (param2)
- param2[counter] = t22;
-
- if (intersectionPoints != null)// if (intersectionPoints)
- intersectionPoints[counter] = Point2D.construct(
- line2.m_xEnd, line2.m_yEnd);
- counter++;
- }
- }
-
- if (counter > 0) {
- if (counter == 2 && param1 != null && param1[0] > param1[1]) {// make
- // sure
- // the
- // intersection
- // events
- // are
- // sorted
- // along
- // the
- // line1
- // can't
- // swap
- // doulbes
- // in
- // java
- // NumberUtils::Swap(param1[0],
- // param1[1]);
- double zeroParam1 = param1[0];
- param1[0] = param1[1];
- param1[1] = zeroParam1;
-
- if (param2 != null)// if (param2)
- {
- double zeroParam2 = param2[0];
- param2[0] = param2[1];
- param2[1] = zeroParam2;// NumberUtils::Swap(ARRAYELEMENT(param2,
- // 0), ARRAYELEMENT(param2, 1));
- }
-
- if (intersectionPoints != null)// if (intersectionPoints)
- {
- Point2D tmp = new Point2D(intersectionPoints[0].x,
- intersectionPoints[0].y);
- intersectionPoints[0] = intersectionPoints[1];
- intersectionPoints[1] = tmp;
- }
- }
-
- return counter;
- }
-
- Point2D params = _intersectHelper1(line1, line2, tolerance);
- if (NumberUtils.isNaN(params.x))
- return 0;
-
- if (intersectionPoints != null)// if (intersectionPoints)
- {
- intersectionPoints[0] = line1.getCoord2D(params.x);
- }
-
- if (param1 != null)// if (param1)
- {
- param1[0] = params.x;
- }
-
- if (param2 != null)// if (param2)
- {
- param2[0] = params.y;
- }
-
- return 1;
- }
+ int _intersectLineLineExact(Line line1, Line line2,
+ Point2D[] intersectionPoints, double[] param1, double[] param2) {
+ int counter = 0;
+ if (line1.m_xStart == line2.m_xStart
+ && line1.m_yStart == line2.m_yStart) {
+ if (param1 != null)// if (param1)
+ param1[counter] = 0.0;
+ if (param2 != null)// if (param2)
+ param2[counter] = 0.0;
+
+ if (intersectionPoints != null)// if (intersectionPoints)
+ intersectionPoints[counter] = Point2D.construct(line1.m_xStart,
+ line1.m_yStart);
+
+ counter++;
+ }
+
+ if (line1.m_xStart == line2.m_xEnd && line1.m_yStart == line2.m_yEnd) {
+ if (param1 != null)// if (param1)
+ param1[counter] = 0.0;
+ if (param2 != null)// if (param2)
+ param2[counter] = 1.0;
+
+ if (intersectionPoints != null)// if (intersectionPoints)
+ intersectionPoints[counter] = Point2D.construct(line1.m_xStart,
+ line1.m_yStart);
+
+ counter++;
+ }
+
+ if (line1.m_xEnd == line2.m_xStart && line1.m_yEnd == line2.m_yStart) {
+ if (counter == 2) {// both segments a degenerate
+ if (param1 != null)// if (param1)
+ {
+ param1[0] = 0.0;
+ param1[1] = 1.0;
+ }
+ if (param2 != null)// if (param2)
+ {
+ param2[0] = 1.0;
+ }
+
+ if (intersectionPoints != null)// if (intersectionPoints)
+ {
+ intersectionPoints[0] = Point2D.construct(line1.m_xEnd,
+ line1.m_yEnd);
+ intersectionPoints[1] = Point2D.construct(line1.m_xEnd,
+ line1.m_yEnd);
+ }
+
+ return counter;
+ }
+
+ if (param1 != null)// if (param1)
+ param1[counter] = 1.0;
+ if (param2 != null)// if (param2)
+ param2[counter] = 0.0;
+
+ if (intersectionPoints != null)// if (intersectionPoints)
+ intersectionPoints[counter] = Point2D.construct(line1.m_xEnd,
+ line1.m_yEnd);
+
+ counter++;
+ }
+
+ if (line1.m_xEnd == line2.m_xEnd && line1.m_yEnd == line2.m_yEnd) {
+ if (counter == 2) {// both segments are degenerate
+ if (param1 != null)// if (param1)
+ {
+ param1[0] = 0.0;
+ param1[1] = 1.0;
+ }
+ if (param2 != null)// if (param2)
+ {
+ param2[0] = 1.0;
+ }
+
+ if (intersectionPoints != null)// if (intersectionPoints)
+ {
+ intersectionPoints[0] = Point2D.construct(line1.m_xEnd,
+ line1.m_yEnd);
+ intersectionPoints[1] = Point2D.construct(line1.m_xEnd,
+ line1.m_yEnd);
+ }
+
+ return counter;
+ }
+
+ if (param1 != null)// if (param1)
+ param1[counter] = 1.0;
+ if (param2 != null)// if (param2)
+ param2[counter] = 1.0;
+
+ if (intersectionPoints != null)// if (intersectionPoints)
+ intersectionPoints[counter] = Point2D.construct(line1.m_xEnd,
+ line1.m_yEnd);
+ counter++;
+ }
+
+ return counter;
+ }
+ static int _intersectLineLine(Line line1, Line line2,
+ Point2D[] intersectionPoints, double[] param1, double[] param2,
+ double tolerance) {
+ // _ASSERT(!param1 && !param2 || param1);
+ int counter = 0;
+ // Test the end points for exact coincidence.
+ double t11 = line1._intersection(line2.getStartXY(), tolerance, false);
+ double t12 = line1._intersection(line2.getEndXY(), tolerance, false);
+ double t21 = line2._intersection(line1.getStartXY(), tolerance, false);
+ double t22 = line2._intersection(line1.getEndXY(), tolerance, false);
+
+ if (!NumberUtils.isNaN(t11)) {
+ if (param1 != null)// if (param1)
+ param1[counter] = t11;
+ if (param2 != null)// if (param2)
+ param2[counter] = 0;
+
+ if (intersectionPoints != null)// if (intersectionPoints)
+ intersectionPoints[counter] = Point2D.construct(line2.m_xStart,
+ line2.m_yStart);
+ counter++;
+ }
+
+ if (!NumberUtils.isNaN(t12)) {
+ if (param1 != null)// if (param1)
+ param1[counter] = t12;
+ if (param2 != null)// if (param2)
+ param2[counter] = 1.0;
+
+ if (intersectionPoints != null)// if (intersectionPoints)
+ intersectionPoints[counter] = Point2D.construct(line2.m_xEnd,
+ line2.m_yEnd);
+ counter++;
+ }
+
+ if (counter != 2 && !NumberUtils.isNaN(t21)) {
+ if (!(t11 == 0 && t21 == 0) && !(t12 == 0 && t21 == 1.0))// the "if"
+ // makes
+ // sure
+ // this
+ // has
+ // not
+ // been
+ // already
+ // calculated
+ {
+ if (param1 != null)// if (param1)
+ param1[counter] = 0;
+ if (param2 != null)// if (param2)
+ param2[counter] = t21;
+
+ if (intersectionPoints != null)// if (intersectionPoints)
+ intersectionPoints[counter] = Point2D.construct(
+ line1.m_xStart, line1.m_yStart);
+ counter++;
+ }
+ }
+
+ if (counter != 2 && !NumberUtils.isNaN(t22)) {
+ if (!(t11 == 1.0 && t22 == 0) && !(t12 == 1.0 && t22 == 1.0))// the
+ // "if"
+ // makes
+ // sure
+ // this
+ // has
+ // not
+ // been
+ // already
+ // calculated
+ {
+ if (param1 != null)// if (param1)
+ param1[counter] = 1.0;
+ if (param2 != null)// if (param2)
+ param2[counter] = t22;
+
+ if (intersectionPoints != null)// if (intersectionPoints)
+ intersectionPoints[counter] = Point2D.construct(
+ line2.m_xEnd, line2.m_yEnd);
+ counter++;
+ }
+ }
+
+ if (counter > 0) {
+ if (counter == 2 && param1 != null && param1[0] > param1[1]) {// make
+ // sure
+ // the
+ // intersection
+ // events
+ // are
+ // sorted
+ // along
+ // the
+ // line1
+ // can't
+ // swap
+ // doulbes
+ // in
+ // java
+ // NumberUtils::Swap(param1[0],
+ // param1[1]);
+ double zeroParam1 = param1[0];
+ param1[0] = param1[1];
+ param1[1] = zeroParam1;
+
+ if (param2 != null)// if (param2)
+ {
+ double zeroParam2 = param2[0];
+ param2[0] = param2[1];
+ param2[1] = zeroParam2;// NumberUtils::Swap(ARRAYELEMENT(param2,
+ // 0), ARRAYELEMENT(param2, 1));
+ }
+
+ if (intersectionPoints != null)// if (intersectionPoints)
+ {
+ Point2D tmp = new Point2D(intersectionPoints[0].x,
+ intersectionPoints[0].y);
+ intersectionPoints[0] = intersectionPoints[1];
+ intersectionPoints[1] = tmp;
+ }
+ }
+
+ return counter;
+ }
+
+ Point2D params = _intersectHelper1(line1, line2, tolerance);
+ if (NumberUtils.isNaN(params.x))
+ return 0;
+
+ if (intersectionPoints != null)// if (intersectionPoints)
+ {
+ intersectionPoints[0] = line1.getCoord2D(params.x);
+ }
+
+ if (param1 != null)// if (param1)
+ {
+ param1[0] = params.x;
+ }
+
+ if (param2 != null)// if (param2)
+ {
+ param2[0] = params.y;
+ }
+
+ return 1;
+ }
+
@Override
public void replaceNaNs(int semantics, double value) {
- addAttribute(semantics);
- if (isEmpty())
- return;
-
- int ncomps = VertexDescription.getComponentCount(semantics);
- for (int i = 0; i < ncomps; i++) {
- double v = _getAttributeAsDbl(0, semantics, i);
- if (Double.isNaN(v))
- _setAttribute(0, semantics, 0, value);
-
- v = _getAttributeAsDbl(1, semantics, i);
- if (Double.isNaN(v))
- _setAttribute(1, semantics, 0, value);
- }
+ addAttribute(semantics);
+ if (isEmpty())
+ return;
+
+ int ncomps = VertexDescription.getComponentCount(semantics);
+ for (int i = 0; i < ncomps; i++) {
+ double v = _getAttributeAsDbl(0, semantics, i);
+ if (Double.isNaN(v))
+ _setAttribute(0, semantics, 0, value);
+
+ v = _getAttributeAsDbl(1, semantics, i);
+ if (Double.isNaN(v))
+ _setAttribute(1, semantics, 0, value);
+ }
}
+
+ @Override
+ int getYMonotonicParts(SegmentBuffer[] monotonicSegments) {
+ return 0;
+ }
- @Override
- int getYMonotonicParts(SegmentBuffer[] monotonicSegments) {
- return 0;
- }
-
- @Override
- void _copyToImpl(Segment dst) {
- // TODO Auto-generated method stub
-
- }
+ @Override
+ void _copyToImpl(Segment dst) {
+ // TODO Auto-generated method stub
- /**
- * The output of this method can be only used for debugging. It is subject to change without notice.
- */
- @Override
- public String toString() {
- String s = "Line: [" + m_xStart + ", " + m_yStart + ", " + m_xEnd + ", " + m_yEnd + "]";
- return s;
- }
+ }
+ /**
+ * The output of this method can be only used for debugging. It is subject to change without notice.
+ */
+ @Override
+ public String toString() {
+ String s = "Line: [" + m_xStart + ", " + m_yStart + ", " + m_xEnd + ", " + m_yEnd +"]";
+ return s;
+ }
+
}
diff --git a/src/main/java/com/esri/core/geometry/ListeningGeometryCursor.java b/src/main/java/com/esri/core/geometry/ListeningGeometryCursor.java
index d4867194..5ab1297a 100644
--- a/src/main/java/com/esri/core/geometry/ListeningGeometryCursor.java
+++ b/src/main/java/com/esri/core/geometry/ListeningGeometryCursor.java
@@ -34,47 +34,51 @@
* but are coming in a stream.
*/
public final class ListeningGeometryCursor extends GeometryCursor {
- // required for use with grpc streaming
- // https://github.com/grpc/grpc-java/blob/06e9b8814787b5cdec10a60e0d9a2228feb8554d/examples/src/main/java/io/grpc/examples/routeguide/RouteGuideServer.java#L246
- private Queue
- * This estimate doesn't include the size of the {@link SpatialReference} object
- * because instances of {@link SpatialReference} are expected to be shared among
- * geometry objects.
- *
- * @return Returns an estimate of this object size in bytes.
- */
- public long estimateMemorySize() {
- long sz = SIZE_OF_MAPGEOMETRY;
- if (m_geometry != null)
- sz += m_geometry.estimateMemorySize();
- return sz;
- }
-
- @Override
- public int hashCode() {
- SpatialReference sr = getSpatialReference();
- Geometry g = getGeometry();
- int hc = 0x2937912;
- if (sr != null)
- hc ^= sr.hashCode();
- if (g != null)
- hc ^= g.hashCode();
-
- return hc;
- }
+ private static final long serialVersionUID = 1L;
+
+ Geometry m_geometry = null;
+ SpatialReference sr = null;
+
+ /**
+ * Construct a MapGeometry instance using the specified geometry instance
+ * and its corresponding spatial reference.
+ *
+ * @param g The geometry to construct the new MapGeometry object.
+ * @param _sr The spatial reference of the geometry.
+ */
+ public MapGeometry(Geometry g, SpatialReference _sr) {
+ m_geometry = g;
+ sr = _sr;
+ }
+
+ /**
+ * Gets the only geometry without the spatial reference from the
+ * MapGeometry.
+ */
+ public Geometry getGeometry() {
+ return m_geometry;
+ }
+
+ /**
+ * Sets the geometry for this MapGeometry.
+ *
+ * @param geometry The geometry.
+ */
+
+ public void setGeometry(Geometry geometry) {
+ this.m_geometry = geometry;
+ }
+
+ /**
+ * Sets the spatial reference for this MapGeometry.
+ *
+ * @param sr The spatial reference.
+ */
+ public void setSpatialReference(SpatialReference sr) {
+ this.sr = sr;
+ }
+
+ /**
+ * Gets the spatial reference for this MapGeometry.
+ */
+ public SpatialReference getSpatialReference() {
+ return sr;
+ }
+
+ /**
+ * The output of this method can be only used for debugging. It is subject to change without notice.
+ */
+ @Override
+ public String toString() {
+ String snippet = OperatorExportToJson.local().execute(getSpatialReference(), getGeometry());
+ if (snippet.length() > 200) {
+ return snippet.substring(0, 197) + "... (" + snippet.length() + " characters)";
+ } else {
+ return snippet;
+ }
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == null)
+ return false;
+
+ if (other == this)
+ return true;
+
+ if (other.getClass() != getClass())
+ return false;
+
+ MapGeometry omg = (MapGeometry) other;
+ SpatialReference sr = getSpatialReference();
+ Geometry g = getGeometry();
+ SpatialReference osr = omg.getSpatialReference();
+ Geometry og = omg.getGeometry();
+
+ if (sr != osr) {
+ if (sr == null || !sr.equals(osr))
+ return false;
+ }
+
+ if (g != og) {
+ if (g == null || !g.equals(og))
+ return false;
+ }
+
+ return true;
+ }
+
+ /**
+ * Returns an estimate of this object size in bytes.
+ *
+ * This estimate doesn't include the size of the {@link SpatialReference} object
+ * because instances of {@link SpatialReference} are expected to be shared among
+ * geometry objects.
+ *
+ * @return Returns an estimate of this object size in bytes.
+ */
+ public long estimateMemorySize() {
+ long sz = SIZE_OF_MAPGEOMETRY;
+ if (m_geometry != null)
+ sz += m_geometry.estimateMemorySize();
+ return sz;
+ }
+
+ @Override
+ public int hashCode() {
+ SpatialReference sr = getSpatialReference();
+ Geometry g = getGeometry();
+ int hc = 0x2937912;
+ if (sr != null)
+ hc ^= sr.hashCode();
+ if (g != null)
+ hc ^= g.hashCode();
+
+ return hc;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/MapGeometryCursor.java b/src/main/java/com/esri/core/geometry/MapGeometryCursor.java
index 20923fc6..925474f8 100644
--- a/src/main/java/com/esri/core/geometry/MapGeometryCursor.java
+++ b/src/main/java/com/esri/core/geometry/MapGeometryCursor.java
@@ -30,26 +30,26 @@
*/
public abstract class MapGeometryCursor implements Iterator
- * Returns an ID associated with the current Geometry. The ID is passed
- * along and is returned by some operators to preserve relationship between
- * the input and output geometry classes. It is not always possible to
- * preserve an ID during an operation.
- */
- public abstract long getGeometryID();
-
- public abstract SimpleStateEnum getSimpleState();
-
- public abstract String getFeatureID();
-
- public abstract boolean hasNext();
+ /**
+ * Moves the cursor to the next ProjectedGeometry. Returns null when reached
+ * the end.
+ */
+ public abstract MapGeometry next();
+
+ /**
+ * Returns the ID of the current geometry. The ID is propagated across the
+ * operations (when possible).
+ *
+ * Returns an ID associated with the current Geometry. The ID is passed
+ * along and is returned by some operators to preserve relationship between
+ * the input and output geometry classes. It is not always possible to
+ * preserve an ID during an operation.
+ */
+ public abstract long getGeometryID();
+
+ public abstract SimpleStateEnum getSimpleState();
+
+ public abstract String getFeatureID();
+
+ public abstract boolean hasNext();
}
diff --git a/src/main/java/com/esri/core/geometry/MapOGCStructure.java b/src/main/java/com/esri/core/geometry/MapOGCStructure.java
index ea2e8d4c..c4eb5241 100644
--- a/src/main/java/com/esri/core/geometry/MapOGCStructure.java
+++ b/src/main/java/com/esri/core/geometry/MapOGCStructure.java
@@ -24,6 +24,6 @@
package com.esri.core.geometry;
public class MapOGCStructure {
- public OGCStructure m_ogcStructure;
- public SpatialReference m_spatialReference;
+ public OGCStructure m_ogcStructure;
+ public SpatialReference m_spatialReference;
}
diff --git a/src/main/java/com/esri/core/geometry/MathUtils.java b/src/main/java/com/esri/core/geometry/MathUtils.java
index fa37aed2..2b41d433 100644
--- a/src/main/java/com/esri/core/geometry/MathUtils.java
+++ b/src/main/java/com/esri/core/geometry/MathUtils.java
@@ -25,211 +25,211 @@
package com.esri.core.geometry;
final class MathUtils {
- /**
- * The implementation of the Kahan summation algorithm. Use to get better
- * precision when adding a lot of values.
- */
- static final class KahanSummator {
- private double sum; // the accumulated sum
- private double compensation;
- private double startValue; // the Base (the class returns sum +
- // startValue)
-
- /**
- * initialize to the given start value. \param startValue_ The value to
- * be added to the accumulated sum.
- */
- KahanSummator(double startValue_) {
- startValue = startValue_;
- reset();
- }
-
- /**
- * Resets the accumulated sum to zero. The getResult() returns
- * startValue_ after this call.
- */
- void reset() {
- sum = 0;
- compensation = 0;
- }
-
- /**
- * add a value.
- */
- void add(double v) {
- double y = v - compensation;
- double t = sum + y;
- double h = t - sum;
- compensation = h - y;
- sum = t;
- }
-
- /**
- * Subtracts a value.
- */
- void sub(double v) {
- add(-v);
- }
-
- /**
- * add another summator.
- */
- void add(/* const */KahanSummator v) {
- double y = (v.getResult() + v.compensation) - compensation;
- double t = sum + y;
- double h = t - sum;
- compensation = h - y;
- sum = t;
- }
-
- /**
- * Subtracts another summator.
- */
- void sub(/* const */KahanSummator v) {
- double y = -(v.getResult() - v.compensation) - compensation;
- double t = sum + y;
- double h = t - sum;
- compensation = h - y;
- sum = t;
- }
-
- /**
- * Returns current value of the sum.
- */
- double getResult() /* const */ {
- return startValue + sum;
- }
-
- KahanSummator plusEquals(double v) {
- add(v);
- return this;
- }
-
- KahanSummator minusEquals(double v) {
- add(-v);
- return this;
- }
-
- KahanSummator plusEquals(/* const */KahanSummator v) {
- add(v);
- return this;
- }
-
- KahanSummator minusEquals(/* const */KahanSummator v) {
- sub(v);
- return this;
- }
- }
-
- /**
- * Returns one value with the sign of another (like copysign).
- */
- static double copySign(double x, double y) {
- return y >= 0.0 ? Math.abs(x) : -Math.abs(x);
- }
-
- /**
- * Calculates sign of the given value. Returns 0 if the value is equal to 0.
- */
- static int sign(double value) {
- return value < 0 ? -1 : (value > 0) ? 1 : 0;
- }
-
- /**
- * Rounds towards zero.
- */
- static double truncate(double v) {
- if (v >= 0)
- return Math.floor(v);
- else
- return -Math.floor(-v);
- }
-
- /**
- * C fmod function.
- */
- static double FMod(double x, double y) {
- return x - truncate(x / y) * y;
- }
-
-
- /**
- * Rounds double to the closest integer value.
- */
- static double round(double v) {
- return Math.floor(v + 0.5);
- }
-
- static double sqr(double v) {
- return v * v;
- }
-
- /**
- * Computes interpolation between two values, using the interpolation factor t.
- * The interpolation formula is (end - start) * t + start.
- * However, the computation ensures that t = 0 produces exactly start, and t = 1, produces exactly end.
- * It also guarantees that for 0 <= t <= 1, the interpolated value v is between start and end.
- */
- static double lerp(double start_, double end_, double t) {
- // When end == start, we want result to be equal to start, for all t
- // values. At the same time, when end != start, we want the result to be
- // equal to start for t==0 and end for t == 1.0
- // The regular formula end_ * t + (1.0 - t) * start_, when end_ ==
- // start_, and t at 1/3, produces value different from start
- double v;
- if (t <= 0.5)
- v = start_ + (end_ - start_) * t;
- else
- v = end_ - (end_ - start_) * (1.0 - t);
-
- assert (t < 0 || t > 1.0 || (v >= start_ && v <= end_) || (v <= start_ && v >= end_) || NumberUtils.isNaN(start_) || NumberUtils.isNaN(end_));
- return v;
- }
-
- /**
- * Computes interpolation between two values, using the interpolation factor t.
- * The interpolation formula is (end - start) * t + start.
- * However, the computation ensures that t = 0 produces exactly start, and t = 1, produces exactly end.
- * It also guarantees that for 0 <= t <= 1, the interpolated value v is between start and end.
- */
- static void lerp(Point2D start_, Point2D end_, double t, Point2D result) {
- assert (start_ != result);
- // When end == start, we want result to be equal to start, for all t
- // values. At the same time, when end != start, we want the result to be
- // equal to start for t==0 and end for t == 1.0
- // The regular formula end_ * t + (1.0 - t) * start_, when end_ ==
- // start_, and t at 1/3, produces value different from start
- double rx, ry;
- if (t <= 0.5) {
- rx = start_.x + (end_.x - start_.x) * t;
- ry = start_.y + (end_.y - start_.y) * t;
- } else {
- rx = end_.x - (end_.x - start_.x) * (1.0 - t);
- ry = end_.y - (end_.y - start_.y) * (1.0 - t);
- }
-
- assert (t < 0 || t > 1.0 || (rx >= start_.x && rx <= end_.x) || (rx <= start_.x && rx >= end_.x));
- assert (t < 0 || t > 1.0 || (ry >= start_.y && ry <= end_.y) || (ry <= start_.y && ry >= end_.y));
- result.x = rx;
- result.y = ry;
- }
-
- static void lerp(double start_x, double start_y, double end_x, double end_y, double t, Point2D result) {
- // When end == start, we want result to be equal to start, for all t
- // values. At the same time, when end != start, we want the result to be
- // equal to start for t==0 and end for t == 1.0
- // The regular formula end_ * t + (1.0 - t) * start_, when end_ ==
- // start_, and t at 1/3, produces value different from start
- if (t <= 0.5) {
- result.x = start_x + (end_x - start_x) * t;
- result.y = start_y + (end_y - start_y) * t;
- } else {
- result.x = end_x - (end_x - start_x) * (1.0 - t);
- result.y = end_y - (end_y - start_y) * (1.0 - t);
- }
-
- assert (t < 0 || t > 1.0 || (result.x >= start_x && result.x <= end_x) || (result.x <= start_x && result.x >= end_x));
- assert (t < 0 || t > 1.0 || (result.y >= start_y && result.y <= end_y) || (result.y <= start_y && result.y >= end_y));
- }
+ /**
+ * The implementation of the Kahan summation algorithm. Use to get better
+ * precision when adding a lot of values.
+ */
+ static final class KahanSummator {
+ private double sum; // the accumulated sum
+ private double compensation;
+ private double startValue; // the Base (the class returns sum +
+ // startValue)
+
+ /**
+ * initialize to the given start value. \param startValue_ The value to
+ * be added to the accumulated sum.
+ */
+ KahanSummator(double startValue_) {
+ startValue = startValue_;
+ reset();
+ }
+
+ /**
+ * Resets the accumulated sum to zero. The getResult() returns
+ * startValue_ after this call.
+ */
+ void reset() {
+ sum = 0;
+ compensation = 0;
+ }
+
+ /**
+ * add a value.
+ */
+ void add(double v) {
+ double y = v - compensation;
+ double t = sum + y;
+ double h = t - sum;
+ compensation = h - y;
+ sum = t;
+ }
+
+ /**
+ * Subtracts a value.
+ */
+ void sub(double v) {
+ add(-v);
+ }
+
+ /**
+ * add another summator.
+ */
+ void add(/* const */KahanSummator v) {
+ double y = (v.getResult() + v.compensation) - compensation;
+ double t = sum + y;
+ double h = t - sum;
+ compensation = h - y;
+ sum = t;
+ }
+
+ /**
+ * Subtracts another summator.
+ */
+ void sub(/* const */KahanSummator v) {
+ double y = -(v.getResult() - v.compensation) - compensation;
+ double t = sum + y;
+ double h = t - sum;
+ compensation = h - y;
+ sum = t;
+ }
+
+ /**
+ * Returns current value of the sum.
+ */
+ double getResult() /* const */ {
+ return startValue + sum;
+ }
+
+ KahanSummator plusEquals(double v) {
+ add(v);
+ return this;
+ }
+
+ KahanSummator minusEquals(double v) {
+ add(-v);
+ return this;
+ }
+
+ KahanSummator plusEquals(/* const */KahanSummator v) {
+ add(v);
+ return this;
+ }
+
+ KahanSummator minusEquals(/* const */KahanSummator v) {
+ sub(v);
+ return this;
+ }
+ }
+
+ /**
+ * Returns one value with the sign of another (like copysign).
+ */
+ static double copySign(double x, double y) {
+ return y >= 0.0 ? Math.abs(x) : -Math.abs(x);
+ }
+
+ /**
+ * Calculates sign of the given value. Returns 0 if the value is equal to 0.
+ */
+ static int sign(double value) {
+ return value < 0 ? -1 : (value > 0) ? 1 : 0;
+ }
+
+ /**
+ * Rounds towards zero.
+ */
+ static double truncate(double v) {
+ if (v >= 0)
+ return Math.floor(v);
+ else
+ return -Math.floor(-v);
+ }
+
+ /**
+ * C fmod function.
+ */
+ static double FMod(double x, double y) {
+ return x - truncate(x / y) * y;
+ }
+
+
+ /**
+ * Rounds double to the closest integer value.
+ */
+ static double round(double v) {
+ return Math.floor(v + 0.5);
+ }
+
+ static double sqr(double v) {
+ return v * v;
+ }
+
+ /**
+ * Computes interpolation between two values, using the interpolation factor t.
+ * The interpolation formula is (end - start) * t + start.
+ * However, the computation ensures that t = 0 produces exactly start, and t = 1, produces exactly end.
+ * It also guarantees that for 0 <= t <= 1, the interpolated value v is between start and end.
+ */
+ static double lerp(double start_, double end_, double t) {
+ // When end == start, we want result to be equal to start, for all t
+ // values. At the same time, when end != start, we want the result to be
+ // equal to start for t==0 and end for t == 1.0
+ // The regular formula end_ * t + (1.0 - t) * start_, when end_ ==
+ // start_, and t at 1/3, produces value different from start
+ double v;
+ if (t <= 0.5)
+ v = start_ + (end_ - start_) * t;
+ else
+ v = end_ - (end_ - start_) * (1.0 - t);
+
+ assert (t < 0 || t > 1.0 || (v >= start_ && v <= end_) || (v <= start_ && v >= end_) || NumberUtils.isNaN(start_) || NumberUtils.isNaN(end_));
+ return v;
+ }
+
+ /**
+ * Computes interpolation between two values, using the interpolation factor t.
+ * The interpolation formula is (end - start) * t + start.
+ * However, the computation ensures that t = 0 produces exactly start, and t = 1, produces exactly end.
+ * It also guarantees that for 0 <= t <= 1, the interpolated value v is between start and end.
+ */
+ static void lerp(Point2D start_, Point2D end_, double t, Point2D result) {
+ assert (start_ != result);
+ // When end == start, we want result to be equal to start, for all t
+ // values. At the same time, when end != start, we want the result to be
+ // equal to start for t==0 and end for t == 1.0
+ // The regular formula end_ * t + (1.0 - t) * start_, when end_ ==
+ // start_, and t at 1/3, produces value different from start
+ double rx, ry;
+ if (t <= 0.5) {
+ rx = start_.x + (end_.x - start_.x) * t;
+ ry = start_.y + (end_.y - start_.y) * t;
+ } else {
+ rx = end_.x - (end_.x - start_.x) * (1.0 - t);
+ ry = end_.y - (end_.y - start_.y) * (1.0 - t);
+ }
+
+ assert (t < 0 || t > 1.0 || (rx >= start_.x && rx <= end_.x) || (rx <= start_.x && rx >= end_.x));
+ assert (t < 0 || t > 1.0 || (ry >= start_.y && ry <= end_.y) || (ry <= start_.y && ry >= end_.y));
+ result.x = rx;
+ result.y = ry;
+ }
+
+ static void lerp(double start_x, double start_y, double end_x, double end_y, double t, Point2D result) {
+ // When end == start, we want result to be equal to start, for all t
+ // values. At the same time, when end != start, we want the result to be
+ // equal to start for t==0 and end for t == 1.0
+ // The regular formula end_ * t + (1.0 - t) * start_, when end_ ==
+ // start_, and t at 1/3, produces value different from start
+ if (t <= 0.5) {
+ result.x = start_x + (end_x - start_x) * t;
+ result.y = start_y + (end_y - start_y) * t;
+ } else {
+ result.x = end_x - (end_x - start_x) * (1.0 - t);
+ result.y = end_y - (end_y - start_y) * (1.0 - t);
+ }
+
+ assert (t < 0 || t > 1.0 || (result.x >= start_x && result.x <= end_x) || (result.x <= start_x && result.x >= end_x));
+ assert (t < 0 || t > 1.0 || (result.y >= start_y && result.y <= end_y) || (result.y <= start_y && result.y >= end_y));
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/MgrsConversionMode.java b/src/main/java/com/esri/core/geometry/MgrsConversionMode.java
index cc47215e..7542f078 100644
--- a/src/main/java/com/esri/core/geometry/MgrsConversionMode.java
+++ b/src/main/java/com/esri/core/geometry/MgrsConversionMode.java
@@ -29,32 +29,32 @@
* notation and coordinates.
*/
public interface MgrsConversionMode {
- /**
- * Uses the spheroid to determine the military grid string.
- */
- public static final int mgrsAutomatic = 0;// PE_MGRS_STYLE_AUTO
- /**
- * Treats all spheroids as new, like WGS 1984, when creating or reading a
- * military grid string. The 180 longitude falls into zone 60.
- */
- public static final int mgrsNewStyle = 0x100; // PE_MGRS_STYLE_NEW
- /**
- * Treats all spheroids as old, like Bessel 1841, when creating or reading a
- * military grid string. The 180 longitude falls into zone 60.
- */
- public static final int mgrsOldStyle = 0x200; // PE_MGRS_STYLE_OLD
- /**
- * Treats all spheroids as new, like WGS 1984, when creating or reading a
- * military grid string. The 180 longitude falls into zone 01.
- */
- public static final int mgrsNewWith180InZone01 = 0x1000 + 0x100; // PE_MGRS_180_ZONE_1_PLUS
- // |
- // PE_MGRS_STYLE_NEW
- /**
- * Treats all spheroids as old, like Bessel 1841, when creating or reading a
- * military grid string. The 180 longitude falls into zone 01.
- */
- public static final int mgrsOldWith180InZone01 = 0x1000 + 0x200; // PE_MGRS_180_ZONE_1_PLUS
- // |
- // PE_MGRS_STYLE_OLD
+ /**
+ * Uses the spheroid to determine the military grid string.
+ */
+ public static final int mgrsAutomatic = 0;// PE_MGRS_STYLE_AUTO
+ /**
+ * Treats all spheroids as new, like WGS 1984, when creating or reading a
+ * military grid string. The 180 longitude falls into zone 60.
+ */
+ public static final int mgrsNewStyle = 0x100; // PE_MGRS_STYLE_NEW
+ /**
+ * Treats all spheroids as old, like Bessel 1841, when creating or reading a
+ * military grid string. The 180 longitude falls into zone 60.
+ */
+ public static final int mgrsOldStyle = 0x200; // PE_MGRS_STYLE_OLD
+ /**
+ * Treats all spheroids as new, like WGS 1984, when creating or reading a
+ * military grid string. The 180 longitude falls into zone 01.
+ */
+ public static final int mgrsNewWith180InZone01 = 0x1000 + 0x100; // PE_MGRS_180_ZONE_1_PLUS
+ // |
+ // PE_MGRS_STYLE_NEW
+ /**
+ * Treats all spheroids as old, like Bessel 1841, when creating or reading a
+ * military grid string. The 180 longitude falls into zone 01.
+ */
+ public static final int mgrsOldWith180InZone01 = 0x1000 + 0x200; // PE_MGRS_180_ZONE_1_PLUS
+ // |
+ // PE_MGRS_STYLE_OLD
}
diff --git a/src/main/java/com/esri/core/geometry/MultiPath.java b/src/main/java/com/esri/core/geometry/MultiPath.java
index 8d7be36b..3f320725 100644
--- a/src/main/java/com/esri/core/geometry/MultiPath.java
+++ b/src/main/java/com/esri/core/geometry/MultiPath.java
@@ -30,687 +30,687 @@
* The MulitPath class is a base class for polygons and polylines.
*/
public abstract class MultiPath extends MultiVertexGeometry implements
- Serializable {
- MultiPathImpl m_impl;
-
- @Override
- public VertexDescription getDescription() {
- return m_impl.getDescription();
- }
-
- @Override
- public void assignVertexDescription(VertexDescription src) {
- m_impl.assignVertexDescription(src);
- }
-
- @Override
- public void mergeVertexDescription(VertexDescription src) {
- m_impl.mergeVertexDescription(src);
- }
-
- @Override
- public void addAttribute(int semantics) {
- m_impl.addAttribute(semantics);
- }
-
- @Override
- public void dropAttribute(int semantics) {
- m_impl.dropAttribute(semantics);
- }
-
- @Override
- public void dropAllAttributes() {
- m_impl.dropAllAttributes();
- }
-
- @Override
- public int getPointCount() {
- return m_impl.getPointCount();
- }
-
- @Override
- public Point getPoint(int index) {
- return m_impl.getPoint(index);
- }
-
- @Override
- public void setPoint(int index, Point point) {
- m_impl.setPoint(index, point);
- }
-
- @Override
- public boolean isEmpty() {
- return m_impl.isEmptyImpl();
- }
-
- @Override
- public double calculateArea2D() {
- return m_impl.calculateArea2D();
- }
-
- @Override
- public double calculateLength2D() {
- return m_impl.calculateLength2D();
- }
-
- public double calculatePathLength2D(int pathIndex) {
- return m_impl.calculatePathLength2D(pathIndex);
- }
-
- @Override
- public double getAttributeAsDbl(int semantics, int index, int ordinate) {
- return m_impl.getAttributeAsDbl(semantics, index, ordinate);
- }
-
- @Override
- public int getAttributeAsInt(int semantics, int index, int ordinate) {
- return m_impl.getAttributeAsInt(semantics, index, ordinate);
- }
-
- @Override
- public void setAttribute(int semantics, int index, int ordinate,
- double value) {
- m_impl.setAttribute(semantics, index, ordinate, value);
- }
-
- @Override
- public void setAttribute(int semantics, int index, int ordinate, int value) {
- m_impl.setAttribute(semantics, index, ordinate, value);
- }
-
- @Override
- public Point2D getXY(int index) {
- return m_impl.getXY(index);
- }
-
- @Override
- public void getXY(int index, Point2D pt) {
- m_impl.getXY(index, pt);
- }
-
- @Override
- public void setXY(int index, Point2D pt) {
- m_impl.setXY(index, pt);
- }
-
- @Override
- Point3D getXYZ(int index) {
- return m_impl.getXYZ(index);
- }
-
- @Override
- void setXYZ(int index, Point3D pt) {
- m_impl.setXYZ(index, pt);
- }
-
- @Override
- public void queryEnvelope(Envelope env) {
- m_impl.queryEnvelope(env);
- }
-
- @Override
- public void queryEnvelope2D(Envelope2D env) {
- m_impl.queryEnvelope2D(env);
- }
-
- public void queryPathEnvelope2D(int pathIndex, Envelope2D env) {
- m_impl.queryPathEnvelope2D(pathIndex, env);
- }
-
- @Override
- void queryEnvelope3D(Envelope3D env) {
- m_impl.queryEnvelope3D(env);
- }
-
- public void queryLooseEnvelope(Envelope2D env) {
- m_impl.queryLooseEnvelope2D(env);
- }
-
- void queryLooseEnvelope(Envelope3D env) {
- m_impl.queryLooseEnvelope3D(env);
- }
-
- @Override
- public Envelope1D queryInterval(int semantics, int ordinate) {
- return m_impl.queryInterval(semantics, ordinate);
- }
-
- @Override
- public void copyTo(Geometry dst) {
- if (getType() != dst.getType())
- throw new IllegalArgumentException();
-
- m_impl.copyTo((Geometry) dst._getImpl());
- }
-
- @Override
- public Geometry getBoundary() {
- return m_impl.getBoundary();
- }
-
- @Override
- public void queryCoordinates(Point2D[] dst) {
- m_impl.queryCoordinates(dst);
- }
-
- public void queryCoordinates(Point2D[] dst, int dstSize, int beginIndex, int endIndex) {
- m_impl.queryCoordinates(dst, dstSize, beginIndex, endIndex);
- }
-
- @Override
- void queryCoordinates(Point3D[] dst) {
- m_impl.queryCoordinates(dst);
- }
-
- @Override
- public void queryCoordinates(Point[] dst) {
- m_impl.queryCoordinates(dst);
-
- }
-
- /**
- * Returns TRUE if the multipath contains non-linear segments.
- */
- boolean hasNonLinearSegments() {
- return m_impl.hasNonLinearSegments();
- }
-
- /**
- * Returns total segment count in the MultiPath.
- */
- public int getSegmentCount() {
- return m_impl.getSegmentCount();
- }
-
- /**
- * Returns the segment count in the given multipath path.
- *
- * @param pathIndex The path to determine the segment.
- * @return The segment of the multipath.
- */
- public int getSegmentCount(int pathIndex) {
- int segCount = getPathSize(pathIndex);
- if (!isClosedPath(pathIndex))
- segCount--;
- return segCount;
- }
-
- /**
- * Appends all paths from another multipath.
- *
- * @param src The multipath to append to this multipath.
- * @param bReversePaths TRUE if the multipath is added should be added with its paths
- * reversed.
- */
- public void add(MultiPath src, boolean bReversePaths) {
- m_impl.add((MultiPathImpl) src._getImpl(), bReversePaths);
- }
-
- /**
- * Copies a path from another multipath.
- *
- * @param src The multipath to copy from.
- * @param srcPathIndex The index of the path in the the source MultiPath.
- * @param bForward When FALSE, the points are inserted in reverse order.
- */
- public void addPath(MultiPath src, int srcPathIndex, boolean bForward) {
- m_impl.addPath((MultiPathImpl) src._getImpl(), srcPathIndex, bForward);
- }
-
- /**
- * Adds a new path to this multipath.
- *
- * @param points The array of points to add to this multipath.
- * @param count The number of points added to the mulitpath.
- * @param bForward When FALSE, the points are inserted in reverse order.
- */
- void addPath(Point2D[] points, int count, boolean bForward) {
- m_impl.addPath(points, count, bForward);
- }
-
- /**
- * Adds segments from a source multipath to this MultiPath.
- *
- * @param src The source MultiPath to add segments from.
- * @param srcPathIndex The index of the path in the the source MultiPath.
- * @param srcSegmentFrom The index of first segment in the path to start adding from.
- * The value has to be between 0 and
- * src.getSegmentCount(srcPathIndex) - 1.
- * @param srcSegmentCount The number of segments to add. If 0, the function does
- * nothing.
- * @param bStartNewPath When true, a new path is added and segments are added to it.
- * Otherwise the segments are added to the last path of this
- * MultiPath.
- *
- * If bStartNewPath false, the first point of the first source
- * segment is not added. This is done to ensure proper connection
- * to existing segments. When the source path is closed, and the
- * closing segment is among those to be added, it is added also
- * as a closing segment, not as a real segment. Use add_segment
- * instead if you do not like that behavior.
- *
- * This MultiPath obtains all missing attributes from the src
- * MultiPath.
- */
- public void addSegmentsFromPath(MultiPath src, int srcPathIndex,
- int srcSegmentFrom, int srcSegmentCount, boolean bStartNewPath) {
- m_impl.addSegmentsFromPath((MultiPathImpl) src._getImpl(),
- srcPathIndex, srcSegmentFrom, srcSegmentCount, bStartNewPath);
- }
-
- /**
- * Adds a new segment to this multipath.
- *
- * @param segment The segment to be added to this mulitpath.
- * @param bStartNewPath TRUE if a new path will be added.
- */
- public void addSegment(Segment segment, boolean bStartNewPath) {
- m_impl.addSegment(segment, bStartNewPath);
- }
-
- /**
- * Reverses the order of the vertices in each path.
- */
- public void reverseAllPaths() {
- m_impl.reverseAllPaths();
- }
-
- /**
- * Reverses the order of vertices in the path.
- *
- * @param pathIndex The start index of the path to reverse the order.
- */
- public void reversePath(int pathIndex) {
- m_impl.reversePath(pathIndex);
- }
-
- /**
- * Removes the path at the given index.
- *
- * @param pathIndex The start index to remove the path.
- */
- public void removePath(int pathIndex) {
- m_impl.removePath(pathIndex);
- }
-
- /**
- * Inserts a path from another multipath.
- *
- * @param pathIndex The start index of the multipath to insert.
- * @param src The multipath to insert into this multipath. Can be the same
- * as the multipath being modified.
- * @param srcPathIndex The start index to insert the path into the multipath.
- * @param bForward When FALSE, the points are inserted in reverse order.
- */
- public void insertPath(int pathIndex, MultiPath src, int srcPathIndex,
- boolean bForward) {
- m_impl.insertPath(pathIndex, (MultiPathImpl) src._getImpl(),
- srcPathIndex, bForward);
- }
-
- /**
- * Inserts a path from an array of 2D Points.
- *
- * @param pathIndex The path index of the multipath to place the new path.
- * @param points The array of points defining the new path.
- * @param pointsOffset The offset into the array to start reading.
- * @param count The number of points to insert into the new path.
- * @param bForward When FALSE, the points are inserted in reverse order.
- */
- void insertPath(int pathIndex, Point2D[] points, int pointsOffset,
- int count, boolean bForward) {
- m_impl.insertPath(pathIndex, points, pointsOffset, count, bForward);
- }
-
- /**
- * Inserts vertices from the given multipath into this multipath. All added
- * vertices are connected by linear segments with each other and with the
- * existing vertices.
- *
- * @param pathIndex The path index in this multipath to insert points to. Must
- * correspond to an existing path.
- * @param beforePointIndex The point index before all other vertices to insert in the
- * given path of this multipath. This value must be between 0 and
- * GetPathSize(pathIndex), or -1 to insert points at the end of
- * the given path.
- * @param src The source multipath.
- * @param srcPathIndex The source path index to copy points from.
- * @param srcPointIndexFrom The start point in the source path to start copying from.
- * @param srcPointCount The count of points to add.
- * @param bForward When FALSE, the points are inserted in reverse order.
- */
- public void insertPoints(int pathIndex, int beforePointIndex,
- MultiPath src, int srcPathIndex, int srcPointIndexFrom,
- int srcPointCount, boolean bForward) {
- m_impl.insertPoints(pathIndex, beforePointIndex,
- (MultiPathImpl) src._getImpl(), srcPathIndex,
- srcPointIndexFrom, srcPointCount, bForward);
- }
-
- /**
- * Inserts a part of a path from the given array.
- *
- * @param pathIndex The path index in this class to insert points to. Must
- * correspond to an existing path.
- * @param beforePointIndex The point index in the given path of this MultiPath before
- * which the vertices need to be inserted. This value must be
- * between 0 and GetPathSize(pathIndex), or -1 to insert points
- * at the end of the given path.
- * @param src The source array
- * @param srcPointIndexFrom The start point in the source array to start copying from.
- * @param srcPointCount The count of points to add.
- * @param bForward When FALSE, the points are inserted in reverse order.
- */
- void insertPoints(int pathIndex, int beforePointIndex, Point2D[] src,
- int srcPointIndexFrom, int srcPointCount, boolean bForward) {
- m_impl.insertPoints(pathIndex, beforePointIndex, src,
- srcPointIndexFrom, srcPointCount, bForward);
- }
-
- /**
- * Inserts a point.
- *
- * @param pathIndex The path index in this class to insert the point to. Must
- * correspond to an existing path.
- * @param beforePointIndex The point index in the given path of this multipath. This
- * value must be between 0 and GetPathSize(pathIndex), or -1 to
- * insert the point at the end of the given path.
- * @param pt The point to be inserted.
- */
- void insertPoint(int pathIndex, int beforePointIndex, Point2D pt) {
- m_impl.insertPoint(pathIndex, beforePointIndex, pt);
- }
-
- /**
- * Inserts a point.
- *
- * @param pathIndex The path index in this class to insert the point to. Must
- * correspond to an existing path.
- * @param beforePointIndex The point index in the given path of this multipath. This
- * value must be between 0 and GetPathSize(pathIndex), or -1 to
- * insert the point at the end of the given path.
- * @param pt The point to be inserted.
- */
- public void insertPoint(int pathIndex, int beforePointIndex, Point pt) {
- m_impl.insertPoint(pathIndex, beforePointIndex, pt);
- }
-
- /**
- * Removes a point at a given index.
- *
- * @param pathIndex The path from whom to remove the point.
- * @param pointIndex The index of the point to be removed.
- */
- public void removePoint(int pathIndex, int pointIndex) {
- m_impl.removePoint(pathIndex, pointIndex);
- }
-
- /**
- * Returns the number of paths in this multipath.
- *
- * @return The number of paths in this multipath.
- */
- public int getPathCount() {
- return m_impl.getPathCount();
- }
-
- /**
- * Returns the number of vertices in a path.
- *
- * @param pathIndex The index of the path to return the number of vertices from.
- * @return The number of vertices in a path.
- */
- public int getPathSize(int pathIndex) {
- return m_impl.getPathSize(pathIndex);
- }
-
- /**
- * Returns the start index of the path.
- *
- * @param pathIndex The index of the path to return the start index from.
- * @return The start index of the path.
- */
- public int getPathStart(int pathIndex) {
- return m_impl.getPathStart(pathIndex);
- }
-
- /**
- * Returns the index immediately following the last index of the path.
- *
- * @param pathIndex The index of the path to return the end index from.
- * @return Integer index after last index of path
- */
- public int getPathEnd(int pathIndex) {
- return m_impl.getPathEnd(pathIndex);
- }
-
- /**
- * Returns the path index from the point index. This is O(log N) operation.
- *
- * @param pointIndex The index of the point.
- * @return The index of the path.
- */
- public int getPathIndexFromPointIndex(int pointIndex) {
- return m_impl.getPathIndexFromPointIndex(pointIndex);
- }
-
- /**
- * Starts a new path at given coordinates.
- *
- * @param x The X coordinate of the start point.
- * @param y The Y coordinate of the start point.
- */
- public void startPath(double x, double y) {
- m_impl.startPath(x, y);
- }
-
- void startPath(Point2D point) {
- m_impl.startPath(point);
- }
-
- void startPath(Point3D point) {
- m_impl.startPath(point);
- }
-
- /**
- * Starts a new path at a point.
- *
- * @param point The point to start the path from.
- */
- public void startPath(Point point) {
- m_impl.startPath(point);
- }
-
- /**
- * Adds a line segment from the last point to the given end coordinates.
- *
- * @param x The X coordinate to the end point.
- * @param y The Y coordinate to the end point.
- */
- public void lineTo(double x, double y) {
- m_impl.lineTo(x, y);
- }
-
- void lineTo(Point2D endPoint) {
- m_impl.lineTo(endPoint);
- }
-
- void lineTo(Point3D endPoint) {
- m_impl.lineTo(endPoint);
- }
-
- /**
- * Adds a Line Segment to the given end point.
- *
- * @param endPoint The end point to which the newly added line segment should
- * point.
- */
- public void lineTo(Point endPoint) {
- m_impl.lineTo(endPoint);
- }
-
- /**
- * Adds a Cubic Bezier Segment to the current Path. The Bezier Segment
- * connects the current last Point and the given endPoint.
- */
- void bezierTo(Point2D controlPoint1, Point2D controlPoint2, Point2D endPoint) {
- m_impl.bezierTo(controlPoint1, controlPoint2, endPoint);
- }
-
- /**
- * Closes the last path of this multipath with a line segment. The closing
- * segment is a segment that connects the last and the first points of the
- * path. This is a virtual segment. The first point is not duplicated to
- * close the path.
- *
- * Call this method only for polylines. For polygons this method is
- * implicitly called for the Polygon class.
- */
- public void closePathWithLine() {
- m_impl.closePathWithLine();
- }
-
- /**
- * Closes last path of the MultiPath with the Bezier Segment.
- *
- * The start point of the Bezier is the last point of the path and the last
- * point of the bezier is the first point of the path.
- */
- void closePathWithBezier(Point2D controlPoint1, Point2D controlPoint2) {
- m_impl.closePathWithBezier(controlPoint1, controlPoint2);
- }
-
- /**
- * Closes last path of the MultiPath with the Arc Segment.
- */
- void closePathWithArc() {
- throw new RuntimeException("not implemented");
- }
-
- /**
- * Closes all open paths by adding an implicit line segment from the end
- * point to the start point. Call this method only for polylines.For
- * polygons this method is implicitly called for the Polygon class.
- */
- public void closeAllPaths() {
- m_impl.closeAllPaths();
- }
-
- /**
- * Indicates if the given path is closed (represents a ring). A closed path
- * has a virtual segment that connects the last and the first points of the
- * path. The first point is not duplicated to close the path. Polygons
- * always have all paths closed.
- *
- * @param pathIndex The index of the path to check to be closed.
- * @return TRUE if the given path is closed (represents a Ring).
- */
- public boolean isClosedPath(int pathIndex) {
- return m_impl.isClosedPath(pathIndex);
- }
-
- public boolean isClosedPathInXYPlane(int pathIndex) {
- return m_impl.isClosedPathInXYPlane(pathIndex);
- }
-
- /**
- * Returns TRUE if the given path might have non-linear segments.
- */
- boolean hasNonLinearSegments(int pathIndex) {
- return m_impl.hasNonLinearSegments(pathIndex);
- }
-
- /**
- * Adds a rectangular closed Path to the MultiPathImpl.
- *
- * @param envSrc is the source rectangle.
- * @param bReverse Creates reversed path.
- */
- public void addEnvelope(Envelope2D envSrc, boolean bReverse) {
- m_impl.addEnvelope(envSrc, bReverse);
- }
-
- /**
- * Adds a rectangular closed path to this multipath.
- *
- * @param envSrc Is the envelope to add to this mulitpath.
- * @param bReverse Adds the path reversed (counter-clockwise).
- */
- public void addEnvelope(Envelope envSrc, boolean bReverse) {
- m_impl.addEnvelope(envSrc, bReverse);
- }
-
- /**
- * Returns a SegmentIterator that is set right before the beginning of the
- * multipath. Calling nextPath() will set the iterator to the first path of
- * this multipath.
- *
- * @return The SegmentIterator for this mulitpath.
- */
- public SegmentIterator querySegmentIterator() {
- return new SegmentIterator(m_impl.querySegmentIterator());
- }
-
- /**
- * Returns a SegmentIterator that is set to a specific vertex of the
- * MultiPath. The call to nextSegment() will return the segment that starts
- * at the vertex. Calling PreviousSegment () will return the segment that
- * starts at the previous vertex.
- *
- * @param startVertexIndex The start index of the SegementIterator.
- * @return The SegmentIterator for this mulitpath at the specified vertex.
- */
- public SegmentIterator querySegmentIteratorAtVertex(int startVertexIndex) {
- return new SegmentIterator(
- m_impl.querySegmentIteratorAtVertex(startVertexIndex));
- }
-
- @Override
- public void setEmpty() {
- m_impl.setEmpty();
- }
-
- @Override
- public void applyTransformation(Transformation2D transform) {
- m_impl.applyTransformation(transform);
- }
-
- @Override
- void applyTransformation(Transformation3D transform) {
- m_impl.applyTransformation(transform);
- }
-
- @Override
- protected Object _getImpl() {
- return m_impl;
- }
-
- /**
- * Returns the hash code for the multipath.
- */
- @Override
- public int hashCode() {
- return m_impl.hashCode();
- }
-
- @Override
- public void getPointByVal(int index, Point outPoint) {
- m_impl.getPointByVal(index, outPoint);
- }
-
- @Override
- public void setPointByVal(int index, Point point) {
- m_impl.setPointByVal(index, point);
- }
-
- @Override
- public int getStateFlag() {
- return m_impl.getStateFlag();
- }
-
- @Override
- public void replaceNaNs(int semantics, double value) {
- m_impl.replaceNaNs(semantics, value);
- }
+ Serializable {
+ MultiPathImpl m_impl;
+
+ @Override
+ public VertexDescription getDescription() {
+ return m_impl.getDescription();
+ }
+
+ @Override
+ public void assignVertexDescription(VertexDescription src) {
+ m_impl.assignVertexDescription(src);
+ }
+
+ @Override
+ public void mergeVertexDescription(VertexDescription src) {
+ m_impl.mergeVertexDescription(src);
+ }
+
+ @Override
+ public void addAttribute(int semantics) {
+ m_impl.addAttribute(semantics);
+ }
+
+ @Override
+ public void dropAttribute(int semantics) {
+ m_impl.dropAttribute(semantics);
+ }
+
+ @Override
+ public void dropAllAttributes() {
+ m_impl.dropAllAttributes();
+ }
+
+ @Override
+ public int getPointCount() {
+ return m_impl.getPointCount();
+ }
+
+ @Override
+ public Point getPoint(int index) {
+ return m_impl.getPoint(index);
+ }
+
+ @Override
+ public void setPoint(int index, Point point) {
+ m_impl.setPoint(index, point);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return m_impl.isEmptyImpl();
+ }
+
+ @Override
+ public double calculateArea2D() {
+ return m_impl.calculateArea2D();
+ }
+
+ @Override
+ public double calculateLength2D() {
+ return m_impl.calculateLength2D();
+ }
+
+ public double calculatePathLength2D(int pathIndex) {
+ return m_impl.calculatePathLength2D(pathIndex);
+ }
+
+ @Override
+ public double getAttributeAsDbl(int semantics, int index, int ordinate) {
+ return m_impl.getAttributeAsDbl(semantics, index, ordinate);
+ }
+
+ @Override
+ public int getAttributeAsInt(int semantics, int index, int ordinate) {
+ return m_impl.getAttributeAsInt(semantics, index, ordinate);
+ }
+
+ @Override
+ public void setAttribute(int semantics, int index, int ordinate,
+ double value) {
+ m_impl.setAttribute(semantics, index, ordinate, value);
+ }
+
+ @Override
+ public void setAttribute(int semantics, int index, int ordinate, int value) {
+ m_impl.setAttribute(semantics, index, ordinate, value);
+ }
+
+ @Override
+ public Point2D getXY(int index) {
+ return m_impl.getXY(index);
+ }
+
+ @Override
+ public void getXY(int index, Point2D pt) {
+ m_impl.getXY(index, pt);
+ }
+
+ @Override
+ public void setXY(int index, Point2D pt) {
+ m_impl.setXY(index, pt);
+ }
+
+ @Override
+ Point3D getXYZ(int index) {
+ return m_impl.getXYZ(index);
+ }
+
+ @Override
+ void setXYZ(int index, Point3D pt) {
+ m_impl.setXYZ(index, pt);
+ }
+
+ @Override
+ public void queryEnvelope(Envelope env) {
+ m_impl.queryEnvelope(env);
+ }
+
+ @Override
+ public void queryEnvelope2D(Envelope2D env) {
+ m_impl.queryEnvelope2D(env);
+ }
+
+ public void queryPathEnvelope2D(int pathIndex, Envelope2D env) {
+ m_impl.queryPathEnvelope2D(pathIndex, env);
+ }
+
+ @Override
+ void queryEnvelope3D(Envelope3D env) {
+ m_impl.queryEnvelope3D(env);
+ }
+
+ public void queryLooseEnvelope(Envelope2D env) {
+ m_impl.queryLooseEnvelope2D(env);
+ }
+
+ void queryLooseEnvelope(Envelope3D env) {
+ m_impl.queryLooseEnvelope3D(env);
+ }
+
+ @Override
+ public Envelope1D queryInterval(int semantics, int ordinate) {
+ return m_impl.queryInterval(semantics, ordinate);
+ }
+
+ @Override
+ public void copyTo(Geometry dst) {
+ if (getType() != dst.getType())
+ throw new IllegalArgumentException();
+
+ m_impl.copyTo((Geometry) dst._getImpl());
+ }
+
+ @Override
+ public Geometry getBoundary() {
+ return m_impl.getBoundary();
+ }
+
+ @Override
+ public void queryCoordinates(Point2D[] dst) {
+ m_impl.queryCoordinates(dst);
+ }
+
+ public void queryCoordinates(Point2D[] dst, int dstSize, int beginIndex, int endIndex) {
+ m_impl.queryCoordinates(dst, dstSize, beginIndex, endIndex);
+ }
+
+ @Override
+ void queryCoordinates(Point3D[] dst) {
+ m_impl.queryCoordinates(dst);
+ }
+
+ @Override
+ public void queryCoordinates(Point[] dst) {
+ m_impl.queryCoordinates(dst);
+
+ }
+
+ /**
+ * Returns TRUE if the multipath contains non-linear segments.
+ */
+ boolean hasNonLinearSegments() {
+ return m_impl.hasNonLinearSegments();
+ }
+
+ /**
+ * Returns total segment count in the MultiPath.
+ */
+ public int getSegmentCount() {
+ return m_impl.getSegmentCount();
+ }
+
+ /**
+ * Returns the segment count in the given multipath path.
+ *
+ * @param pathIndex The path to determine the segment.
+ * @return The segment of the multipath.
+ */
+ public int getSegmentCount(int pathIndex) {
+ int segCount = getPathSize(pathIndex);
+ if (!isClosedPath(pathIndex))
+ segCount--;
+ return segCount;
+ }
+
+ /**
+ * Appends all paths from another multipath.
+ *
+ * @param src The multipath to append to this multipath.
+ * @param bReversePaths TRUE if the multipath is added should be added with its paths
+ * reversed.
+ */
+ public void add(MultiPath src, boolean bReversePaths) {
+ m_impl.add((MultiPathImpl) src._getImpl(), bReversePaths);
+ }
+
+ /**
+ * Copies a path from another multipath.
+ *
+ * @param src The multipath to copy from.
+ * @param srcPathIndex The index of the path in the the source MultiPath.
+ * @param bForward When FALSE, the points are inserted in reverse order.
+ */
+ public void addPath(MultiPath src, int srcPathIndex, boolean bForward) {
+ m_impl.addPath((MultiPathImpl) src._getImpl(), srcPathIndex, bForward);
+ }
+
+ /**
+ * Adds a new path to this multipath.
+ *
+ * @param points The array of points to add to this multipath.
+ * @param count The number of points added to the mulitpath.
+ * @param bForward When FALSE, the points are inserted in reverse order.
+ */
+ void addPath(Point2D[] points, int count, boolean bForward) {
+ m_impl.addPath(points, count, bForward);
+ }
+
+ /**
+ * Adds segments from a source multipath to this MultiPath.
+ *
+ * @param src The source MultiPath to add segments from.
+ * @param srcPathIndex The index of the path in the the source MultiPath.
+ * @param srcSegmentFrom The index of first segment in the path to start adding from.
+ * The value has to be between 0 and
+ * src.getSegmentCount(srcPathIndex) - 1.
+ * @param srcSegmentCount The number of segments to add. If 0, the function does
+ * nothing.
+ * @param bStartNewPath When true, a new path is added and segments are added to it.
+ * Otherwise the segments are added to the last path of this
+ * MultiPath.
+ *
+ * If bStartNewPath false, the first point of the first source
+ * segment is not added. This is done to ensure proper connection
+ * to existing segments. When the source path is closed, and the
+ * closing segment is among those to be added, it is added also
+ * as a closing segment, not as a real segment. Use add_segment
+ * instead if you do not like that behavior.
+ *
+ * This MultiPath obtains all missing attributes from the src
+ * MultiPath.
+ */
+ public void addSegmentsFromPath(MultiPath src, int srcPathIndex,
+ int srcSegmentFrom, int srcSegmentCount, boolean bStartNewPath) {
+ m_impl.addSegmentsFromPath((MultiPathImpl) src._getImpl(),
+ srcPathIndex, srcSegmentFrom, srcSegmentCount, bStartNewPath);
+ }
+
+ /**
+ * Adds a new segment to this multipath.
+ *
+ * @param segment The segment to be added to this mulitpath.
+ * @param bStartNewPath TRUE if a new path will be added.
+ */
+ public void addSegment(Segment segment, boolean bStartNewPath) {
+ m_impl.addSegment(segment, bStartNewPath);
+ }
+
+ /**
+ * Reverses the order of the vertices in each path.
+ */
+ public void reverseAllPaths() {
+ m_impl.reverseAllPaths();
+ }
+
+ /**
+ * Reverses the order of vertices in the path.
+ *
+ * @param pathIndex The start index of the path to reverse the order.
+ */
+ public void reversePath(int pathIndex) {
+ m_impl.reversePath(pathIndex);
+ }
+
+ /**
+ * Removes the path at the given index.
+ *
+ * @param pathIndex The start index to remove the path.
+ */
+ public void removePath(int pathIndex) {
+ m_impl.removePath(pathIndex);
+ }
+
+ /**
+ * Inserts a path from another multipath.
+ *
+ * @param pathIndex The start index of the multipath to insert.
+ * @param src The multipath to insert into this multipath. Can be the same
+ * as the multipath being modified.
+ * @param srcPathIndex The start index to insert the path into the multipath.
+ * @param bForward When FALSE, the points are inserted in reverse order.
+ */
+ public void insertPath(int pathIndex, MultiPath src, int srcPathIndex,
+ boolean bForward) {
+ m_impl.insertPath(pathIndex, (MultiPathImpl) src._getImpl(),
+ srcPathIndex, bForward);
+ }
+
+ /**
+ * Inserts a path from an array of 2D Points.
+ *
+ * @param pathIndex The path index of the multipath to place the new path.
+ * @param points The array of points defining the new path.
+ * @param pointsOffset The offset into the array to start reading.
+ * @param count The number of points to insert into the new path.
+ * @param bForward When FALSE, the points are inserted in reverse order.
+ */
+ void insertPath(int pathIndex, Point2D[] points, int pointsOffset,
+ int count, boolean bForward) {
+ m_impl.insertPath(pathIndex, points, pointsOffset, count, bForward);
+ }
+
+ /**
+ * Inserts vertices from the given multipath into this multipath. All added
+ * vertices are connected by linear segments with each other and with the
+ * existing vertices.
+ *
+ * @param pathIndex The path index in this multipath to insert points to. Must
+ * correspond to an existing path.
+ * @param beforePointIndex The point index before all other vertices to insert in the
+ * given path of this multipath. This value must be between 0 and
+ * GetPathSize(pathIndex), or -1 to insert points at the end of
+ * the given path.
+ * @param src The source multipath.
+ * @param srcPathIndex The source path index to copy points from.
+ * @param srcPointIndexFrom The start point in the source path to start copying from.
+ * @param srcPointCount The count of points to add.
+ * @param bForward When FALSE, the points are inserted in reverse order.
+ */
+ public void insertPoints(int pathIndex, int beforePointIndex,
+ MultiPath src, int srcPathIndex, int srcPointIndexFrom,
+ int srcPointCount, boolean bForward) {
+ m_impl.insertPoints(pathIndex, beforePointIndex,
+ (MultiPathImpl) src._getImpl(), srcPathIndex,
+ srcPointIndexFrom, srcPointCount, bForward);
+ }
+
+ /**
+ * Inserts a part of a path from the given array.
+ *
+ * @param pathIndex The path index in this class to insert points to. Must
+ * correspond to an existing path.
+ * @param beforePointIndex The point index in the given path of this MultiPath before
+ * which the vertices need to be inserted. This value must be
+ * between 0 and GetPathSize(pathIndex), or -1 to insert points
+ * at the end of the given path.
+ * @param src The source array
+ * @param srcPointIndexFrom The start point in the source array to start copying from.
+ * @param srcPointCount The count of points to add.
+ * @param bForward When FALSE, the points are inserted in reverse order.
+ */
+ void insertPoints(int pathIndex, int beforePointIndex, Point2D[] src,
+ int srcPointIndexFrom, int srcPointCount, boolean bForward) {
+ m_impl.insertPoints(pathIndex, beforePointIndex, src,
+ srcPointIndexFrom, srcPointCount, bForward);
+ }
+
+ /**
+ * Inserts a point.
+ *
+ * @param pathIndex The path index in this class to insert the point to. Must
+ * correspond to an existing path.
+ * @param beforePointIndex The point index in the given path of this multipath. This
+ * value must be between 0 and GetPathSize(pathIndex), or -1 to
+ * insert the point at the end of the given path.
+ * @param pt The point to be inserted.
+ */
+ void insertPoint(int pathIndex, int beforePointIndex, Point2D pt) {
+ m_impl.insertPoint(pathIndex, beforePointIndex, pt);
+ }
+
+ /**
+ * Inserts a point.
+ *
+ * @param pathIndex The path index in this class to insert the point to. Must
+ * correspond to an existing path.
+ * @param beforePointIndex The point index in the given path of this multipath. This
+ * value must be between 0 and GetPathSize(pathIndex), or -1 to
+ * insert the point at the end of the given path.
+ * @param pt The point to be inserted.
+ */
+ public void insertPoint(int pathIndex, int beforePointIndex, Point pt) {
+ m_impl.insertPoint(pathIndex, beforePointIndex, pt);
+ }
+
+ /**
+ * Removes a point at a given index.
+ *
+ * @param pathIndex The path from whom to remove the point.
+ * @param pointIndex The index of the point to be removed.
+ */
+ public void removePoint(int pathIndex, int pointIndex) {
+ m_impl.removePoint(pathIndex, pointIndex);
+ }
+
+ /**
+ * Returns the number of paths in this multipath.
+ *
+ * @return The number of paths in this multipath.
+ */
+ public int getPathCount() {
+ return m_impl.getPathCount();
+ }
+
+ /**
+ * Returns the number of vertices in a path.
+ *
+ * @param pathIndex The index of the path to return the number of vertices from.
+ * @return The number of vertices in a path.
+ */
+ public int getPathSize(int pathIndex) {
+ return m_impl.getPathSize(pathIndex);
+ }
+
+ /**
+ * Returns the start index of the path.
+ *
+ * @param pathIndex The index of the path to return the start index from.
+ * @return The start index of the path.
+ */
+ public int getPathStart(int pathIndex) {
+ return m_impl.getPathStart(pathIndex);
+ }
+
+ /**
+ * Returns the index immediately following the last index of the path.
+ *
+ * @param pathIndex The index of the path to return the end index from.
+ * @return Integer index after last index of path
+ */
+ public int getPathEnd(int pathIndex) {
+ return m_impl.getPathEnd(pathIndex);
+ }
+
+ /**
+ * Returns the path index from the point index. This is O(log N) operation.
+ *
+ * @param pointIndex The index of the point.
+ * @return The index of the path.
+ */
+ public int getPathIndexFromPointIndex(int pointIndex) {
+ return m_impl.getPathIndexFromPointIndex(pointIndex);
+ }
+
+ /**
+ * Starts a new path at given coordinates.
+ *
+ * @param x The X coordinate of the start point.
+ * @param y The Y coordinate of the start point.
+ */
+ public void startPath(double x, double y) {
+ m_impl.startPath(x, y);
+ }
+
+ void startPath(Point2D point) {
+ m_impl.startPath(point);
+ }
+
+ void startPath(Point3D point) {
+ m_impl.startPath(point);
+ }
+
+ /**
+ * Starts a new path at a point.
+ *
+ * @param point The point to start the path from.
+ */
+ public void startPath(Point point) {
+ m_impl.startPath(point);
+ }
+
+ /**
+ * Adds a line segment from the last point to the given end coordinates.
+ *
+ * @param x The X coordinate to the end point.
+ * @param y The Y coordinate to the end point.
+ */
+ public void lineTo(double x, double y) {
+ m_impl.lineTo(x, y);
+ }
+
+ void lineTo(Point2D endPoint) {
+ m_impl.lineTo(endPoint);
+ }
+
+ void lineTo(Point3D endPoint) {
+ m_impl.lineTo(endPoint);
+ }
+
+ /**
+ * Adds a Line Segment to the given end point.
+ *
+ * @param endPoint The end point to which the newly added line segment should
+ * point.
+ */
+ public void lineTo(Point endPoint) {
+ m_impl.lineTo(endPoint);
+ }
+
+ /**
+ * Adds a Cubic Bezier Segment to the current Path. The Bezier Segment
+ * connects the current last Point and the given endPoint.
+ */
+ void bezierTo(Point2D controlPoint1, Point2D controlPoint2, Point2D endPoint) {
+ m_impl.bezierTo(controlPoint1, controlPoint2, endPoint);
+ }
+
+ /**
+ * Closes the last path of this multipath with a line segment. The closing
+ * segment is a segment that connects the last and the first points of the
+ * path. This is a virtual segment. The first point is not duplicated to
+ * close the path.
+ *
+ * Call this method only for polylines. For polygons this method is
+ * implicitly called for the Polygon class.
+ */
+ public void closePathWithLine() {
+ m_impl.closePathWithLine();
+ }
+
+ /**
+ * Closes last path of the MultiPath with the Bezier Segment.
+ *
+ * The start point of the Bezier is the last point of the path and the last
+ * point of the bezier is the first point of the path.
+ */
+ void closePathWithBezier(Point2D controlPoint1, Point2D controlPoint2) {
+ m_impl.closePathWithBezier(controlPoint1, controlPoint2);
+ }
+
+ /**
+ * Closes last path of the MultiPath with the Arc Segment.
+ */
+ void closePathWithArc() {
+ throw new RuntimeException("not implemented");
+ }
+
+ /**
+ * Closes all open paths by adding an implicit line segment from the end
+ * point to the start point. Call this method only for polylines.For
+ * polygons this method is implicitly called for the Polygon class.
+ */
+ public void closeAllPaths() {
+ m_impl.closeAllPaths();
+ }
+
+ /**
+ * Indicates if the given path is closed (represents a ring). A closed path
+ * has a virtual segment that connects the last and the first points of the
+ * path. The first point is not duplicated to close the path. Polygons
+ * always have all paths closed.
+ *
+ * @param pathIndex The index of the path to check to be closed.
+ * @return TRUE if the given path is closed (represents a Ring).
+ */
+ public boolean isClosedPath(int pathIndex) {
+ return m_impl.isClosedPath(pathIndex);
+ }
+
+ public boolean isClosedPathInXYPlane(int pathIndex) {
+ return m_impl.isClosedPathInXYPlane(pathIndex);
+ }
+
+ /**
+ * Returns TRUE if the given path might have non-linear segments.
+ */
+ boolean hasNonLinearSegments(int pathIndex) {
+ return m_impl.hasNonLinearSegments(pathIndex);
+ }
+
+ /**
+ * Adds a rectangular closed Path to the MultiPathImpl.
+ *
+ * @param envSrc is the source rectangle.
+ * @param bReverse Creates reversed path.
+ */
+ public void addEnvelope(Envelope2D envSrc, boolean bReverse) {
+ m_impl.addEnvelope(envSrc, bReverse);
+ }
+
+ /**
+ * Adds a rectangular closed path to this multipath.
+ *
+ * @param envSrc Is the envelope to add to this mulitpath.
+ * @param bReverse Adds the path reversed (counter-clockwise).
+ */
+ public void addEnvelope(Envelope envSrc, boolean bReverse) {
+ m_impl.addEnvelope(envSrc, bReverse);
+ }
+
+ /**
+ * Returns a SegmentIterator that is set right before the beginning of the
+ * multipath. Calling nextPath() will set the iterator to the first path of
+ * this multipath.
+ *
+ * @return The SegmentIterator for this mulitpath.
+ */
+ public SegmentIterator querySegmentIterator() {
+ return new SegmentIterator(m_impl.querySegmentIterator());
+ }
+
+ /**
+ * Returns a SegmentIterator that is set to a specific vertex of the
+ * MultiPath. The call to nextSegment() will return the segment that starts
+ * at the vertex. Calling PreviousSegment () will return the segment that
+ * starts at the previous vertex.
+ *
+ * @param startVertexIndex The start index of the SegementIterator.
+ * @return The SegmentIterator for this mulitpath at the specified vertex.
+ */
+ public SegmentIterator querySegmentIteratorAtVertex(int startVertexIndex) {
+ return new SegmentIterator(
+ m_impl.querySegmentIteratorAtVertex(startVertexIndex));
+ }
+
+ @Override
+ public void setEmpty() {
+ m_impl.setEmpty();
+ }
+
+ @Override
+ public void applyTransformation(Transformation2D transform) {
+ m_impl.applyTransformation(transform);
+ }
+
+ @Override
+ void applyTransformation(Transformation3D transform) {
+ m_impl.applyTransformation(transform);
+ }
+
+ @Override
+ protected Object _getImpl() {
+ return m_impl;
+ }
+
+ /**
+ * Returns the hash code for the multipath.
+ */
+ @Override
+ public int hashCode() {
+ return m_impl.hashCode();
+ }
+
+ @Override
+ public void getPointByVal(int index, Point outPoint) {
+ m_impl.getPointByVal(index, outPoint);
+ }
+
+ @Override
+ public void setPointByVal(int index, Point point) {
+ m_impl.setPointByVal(index, point);
+ }
+
+ @Override
+ public int getStateFlag() {
+ return m_impl.getStateFlag();
+ }
+
+ @Override
+ public void replaceNaNs(int semantics, double value) {
+ m_impl.replaceNaNs(semantics, value);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/MultiPathImpl.java b/src/main/java/com/esri/core/geometry/MultiPathImpl.java
index a1963aff..c9400ee0 100644
--- a/src/main/java/com/esri/core/geometry/MultiPathImpl.java
+++ b/src/main/java/com/esri/core/geometry/MultiPathImpl.java
@@ -33,31 +33,31 @@ final class MultiPathImpl extends MultiVertexGeometryImpl {
protected double m_cachedLength2D;
protected double m_cachedArea2D;
- protected AttributeStreamOfDbl m_cachedRingAreas2D;
- protected boolean m_bPathStarted;
-
- // Contains starting points of the parts. The size is getPartCount() + 1.
- // First element is 0, last element is equal to the getPointCount().
- protected AttributeStreamOfInt32 m_paths;
- // same size as m_parts. Holds flags for each part (whether the part is
- // closed, etc. See PathFlags)
- protected AttributeStreamOfInt8 m_pathFlags;
- // The segment flags. Size is getPointCount(). This is not a vertex
- // attribute, because we may want to use indexed access later (via an index
- // buffer).
- // Can be NULL if the MultiPathImpl contains straight lines only.
- protected AttributeStreamOfInt8 m_segmentFlags;
- // An index into the m_segmentParams stream. Size is getPointCount(). Can be
- // NULL if the MultiPathImpl contains straight lines only.
- protected AttributeStreamOfInt32 m_segmentParamIndex;
- protected AttributeStreamOfDbl m_segmentParams;
- protected int m_curveParamwritePoint;
- private int m_currentPathIndex;
- private int m_fill_rule = Polygon.FillRule.enumFillRuleOddEven;
-
- static int[] _segmentParamSizes = {0, 0, 6, 0, 8, 0}; // None, Line,
- // Bezier, XXX, Arc,
- // XXX;
+ protected AttributeStreamOfDbl m_cachedRingAreas2D;
+ protected boolean m_bPathStarted;
+
+ // Contains starting points of the parts. The size is getPartCount() + 1.
+ // First element is 0, last element is equal to the getPointCount().
+ protected AttributeStreamOfInt32 m_paths;
+ // same size as m_parts. Holds flags for each part (whether the part is
+ // closed, etc. See PathFlags)
+ protected AttributeStreamOfInt8 m_pathFlags;
+ // The segment flags. Size is getPointCount(). This is not a vertex
+ // attribute, because we may want to use indexed access later (via an index
+ // buffer).
+ // Can be NULL if the MultiPathImpl contains straight lines only.
+ protected AttributeStreamOfInt8 m_segmentFlags;
+ // An index into the m_segmentParams stream. Size is getPointCount(). Can be
+ // NULL if the MultiPathImpl contains straight lines only.
+ protected AttributeStreamOfInt32 m_segmentParamIndex;
+ protected AttributeStreamOfDbl m_segmentParams;
+ protected int m_curveParamwritePoint;
+ private int m_currentPathIndex;
+ private int m_fill_rule = Polygon.FillRule.enumFillRuleOddEven;
+
+ static int[] _segmentParamSizes = { 0, 0, 6, 0, 8, 0 }; // None, Line,
+ // Bezier, XXX, Arc,
+ // XXX;
@Override
public long estimateMemorySize()
@@ -66,8 +66,8 @@ public long estimateMemorySize()
+ (m_envelope != null ? m_envelope.estimateMemorySize() : 0)
+ (m_moveToPoint != null ? m_moveToPoint.estimateMemorySize() : 0)
+ (m_cachedRingAreas2D != null ? m_cachedRingAreas2D.estimateMemorySize() : 0)
- + m_paths.estimateMemorySize()
- + m_pathFlags.estimateMemorySize()
+ + (m_paths != null ? m_paths.estimateMemorySize() : 0)
+ + (m_pathFlags != null ? m_pathFlags.estimateMemorySize() : 0)
+ (m_segmentFlags != null ? m_segmentFlags.estimateMemorySize() : 0)
+ (m_segmentParamIndex != null ? m_segmentParamIndex.estimateMemorySize() : 0)
+ (m_segmentParams != null ? m_segmentParams.estimateMemorySize() : 0);
@@ -77,6 +77,11 @@ public long estimateMemorySize()
size += m_vertexAttributes[i].estimateMemorySize();
}
}
+
+ if (m_accelerators != null) {
+ size += m_accelerators.estimateMemorySize();
+ }
+
return size;
}
@@ -84,2535 +89,2531 @@ public boolean hasNonLinearSegments() {
return m_curveParamwritePoint > 0;
}
- // / Cpp ///
- // Reviewed vs. Native Jan 11, 2011
- public MultiPathImpl(boolean bPolygon) {
- m_bPolygon = bPolygon;
-
- m_bPathStarted = false;
- m_curveParamwritePoint = 0;
- m_cachedLength2D = 0;
- m_cachedArea2D = 0;
- m_pointCount = 0;
- m_description = VertexDescriptionDesignerImpl.getDefaultDescriptor2D();
- m_cachedRingAreas2D = null;
- m_currentPathIndex = 0;
- }
-
- // Reviewed vs. Native Jan 11, 2011
- public MultiPathImpl(boolean bPolygon, VertexDescription description) {
- if (description == null)
- throw new IllegalArgumentException();
-
- m_bPolygon = bPolygon;
-
- m_bPathStarted = false;
- m_curveParamwritePoint = 0;
- m_cachedLength2D = 0;
- m_cachedArea2D = 0;
- m_pointCount = 0;
- m_description = description;
- m_cachedRingAreas2D = null;
- m_currentPathIndex = 0;
- }
-
- // Reviewed vs. Native Jan 11, 2011
- protected void _initPathStartPoint() {
- _touch();
- if (m_moveToPoint == null)
- m_moveToPoint = new Point(m_description);
- else
- m_moveToPoint.assignVertexDescription(m_description);
- }
-
- // Reviewed vs. Native Jan 11, 2011
-
- /**
- * Starts a new Path at the Point.
- */
- public void startPath(double x, double y) {
- Point2D endPoint = new Point2D();
- endPoint.x = x;
- endPoint.y = y;
- startPath(endPoint);
- }
-
- // Reviewed vs. Native Jan 11, 2011
- public void startPath(Point2D point) {
- _initPathStartPoint();
- m_moveToPoint.setXY(point);
- m_bPathStarted = true;
- }
-
- // Reviewed vs. Native Jan 11, 2011
- public void startPath(Point3D point) {
- _initPathStartPoint();
- m_moveToPoint.setXYZ(point);
- assignVertexDescription(m_moveToPoint.getDescription());
- m_bPathStarted = true;
- }
-
- // Reviewed vs. Native Jan 11, 2011
- public void startPath(Point point) {
- if (point.isEmpty())
- throw new IllegalArgumentException();// throw new
- // IllegalArgumentException();
-
- mergeVertexDescription(point.getDescription());
- _initPathStartPoint();
- point.copyTo(m_moveToPoint);
-
- // TODO check MultiPathImpl.cpp comment
- // "//the description will be merged later"
- // assignVertexDescription(m_moveToPoint.getDescription());
- m_bPathStarted = true;
- }
-
- // Reviewed vs. Native Jan 11, 2011
- protected void _beforeNewSegment(int resizeBy) {
- // Called for each new segment being added.
- if (m_bPathStarted) {
- _initPathStartPoint();// make sure the m_movetoPoint exists and has
- // right vertex description
-
- // The new path is started. Need to grow m_parts and m_pathFlags.
- if (m_paths == null) {
- m_paths = (AttributeStreamOfInt32) AttributeStreamBase
- .createIndexStream(2);
- m_paths.write(0, 0);
- m_pathFlags = (AttributeStreamOfInt8) AttributeStreamBase
- .createByteStream(2, (byte) 0);
- } else {
- // _ASSERT(m_parts.size() >= 2);
- m_paths.resize(m_paths.size() + 1, 0);
- m_pathFlags.resize(m_pathFlags.size() + 1, 0);
- }
-
- if (m_bPolygon) {
- // Mark the path as closed
- m_pathFlags.write(m_pathFlags.size() - 2,
- (byte) PathFlags.enumClosed);
- }
-
- resizeBy++; // +1 for the StartPath point.
- }
-
- int oldcount = m_pointCount;
- m_paths.write(m_paths.size() - 1, m_pointCount + resizeBy); // The
- // NotifyModified
- // will
- // update
- // the
- // m_pointCount
- // with this
- // value.
- _resizeImpl(oldcount + resizeBy);
- m_pathFlags.write(m_paths.size() - 1, (byte) 0);
-
- if (m_bPathStarted) {
- setPointByVal(oldcount, m_moveToPoint);// setPoint(oldcount,
- // m_moveToPoint); //finally
- // set the start point to
- // the geometry
- m_bPathStarted = false;
- }
- }
-
- // Reviewed vs. Native Jan 11, 2011
- protected void _finishLineTo() {
- }
-
- // Reviewed vs. Native Jan 11, 2011
-
- /**
- * adds a Line Segment from the last Point to the given endPoint.
- */
- public void lineTo(double x, double y) {
- _beforeNewSegment(1);
- setXY(m_pointCount - 1, x, y);
- _finishLineTo();
- // Point2D endPoint = new Point2D();
- // endPoint.x = x; endPoint.y = y;
- // lineTo(endPoint);
- }
-
- // Reviewed vs. Native Jan 11, 2011
- public void lineTo(Point2D endPoint) {
- _beforeNewSegment(1);
- setXY(m_pointCount - 1, endPoint);
- _finishLineTo();
- }
-
- // Reviewed vs. Native Jan 11, 2011
- public void lineTo(Point3D endPoint) {
- _beforeNewSegment(1);
- setXYZ(m_pointCount - 1, endPoint);
- _finishLineTo();
- }
-
- // Reviewed vs. Native Jan 11, 2011
- public void lineTo(Point endPoint) {
- _beforeNewSegment(1);
- setPointByVal(m_pointCount - 1, endPoint);
- _finishLineTo();
- }
-
- // Reviewed vs. Native Jan 11, 2011
- protected void _initSegmentData(int sz) {
- if (m_segmentParamIndex == null) {
- m_segmentFlags = (AttributeStreamOfInt8) AttributeStreamBase
- .createByteStream(m_pointCount,
- (byte) SegmentFlags.enumLineSeg);
- m_segmentParamIndex = (AttributeStreamOfInt32) AttributeStreamBase
- .createIndexStream(m_pointCount, -1);
- }
-
- int size = m_curveParamwritePoint + sz;
- if (m_segmentParams == null) {
- m_segmentParams = (AttributeStreamOfDbl) AttributeStreamBase
- .createAttributeStreamWithPersistence(
- VertexDescription.Persistence.enumDouble, size);
- } else {
- m_segmentParams.resize(size, 0);
- }
- }
-
- // Reviewed vs. Native Jan 11, 2011
- protected void _finishBezierTo() {
- // _ASSERT(m_segmentFlags != null);
- // _ASSERT(m_segmentParamIndex != null);
-
- m_segmentFlags.write(m_pointCount - 2,
- (byte) SegmentFlags.enumBezierSeg);
- }
-
- // Reviewed vs. Native Jan 11, 2011
-
- /**
- * adds a Cubic Bezier Segment to the current Path. The Bezier Segment
- * connects the current last Point and the given endPoint.
- */
- public void bezierTo(Point2D controlPoint1, Point2D controlPoint2,
- Point2D endPoint) {
- _beforeNewSegment(1);
- setXY(m_pointCount - 1, endPoint);
- double z;
- _initSegmentData(6);
- m_pathFlags.setBits(m_pathFlags.size() - 1,
- (byte) PathFlags.enumHasNonlinearSegments);
- m_segmentParamIndex.write(m_pointCount - 2, m_curveParamwritePoint);
- m_curveParamwritePoint += 6;
- int curveIndex = m_curveParamwritePoint;
- m_segmentParams.write(curveIndex, controlPoint1.x);
- m_segmentParams.write(curveIndex + 1, controlPoint1.y);
- z = 0;// TODO: calculate me.
- m_segmentParams.write(curveIndex + 2, z);
- m_segmentParams.write(curveIndex + 3, controlPoint2.x);
- m_segmentParams.write(curveIndex + 4, controlPoint2.y);
- z = 0;// TODO: calculate me.
- m_segmentParams.write(curveIndex + 5, z);
- _finishBezierTo();
- }
-
- // Reviewed vs. Native Jan 11, 2011
- public void openPath(int pathIndex) {
- _touch();
- if (m_bPolygon)
- throw GeometryException.GeometryInternalError();// do not call this
- // method on a
- // polygon
-
- int pathCount = getPathCount();
- if (pathIndex > getPathCount())
- throw new IllegalArgumentException();
-
- if (m_pathFlags == null)
- throw GeometryException.GeometryInternalError();
-
- m_pathFlags.clearBits(pathIndex, (byte) PathFlags.enumClosed);
- }
-
- public void openPathAndDuplicateStartVertex(int pathIndex) {
- _touch();
- if (m_bPolygon)
- throw GeometryException.GeometryInternalError();// do not call this
- // method on a
- // polygon
-
- int pathCount = getPathCount();
- if (pathIndex > pathCount)
- throw GeometryException.GeometryInternalError();
-
- if (!isClosedPath(pathIndex))
- return;// do not open if open
-
- if (m_pathFlags == null)// if (!m_pathFlags)
- throw GeometryException.GeometryInternalError();
-
- int oldPointCount = m_pointCount;
- int pathIndexStart = getPathStart(pathIndex);
- int pathIndexEnd = getPathEnd(pathIndex);
- _resizeImpl(m_pointCount + 1); // resize does not write into m_paths
- // anymore!
- _verifyAllStreams();
- for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
- if (m_vertexAttributes[iattr] != null)// if
- // (m_vertexAttributes[iattr])
- {
- int semantics = m_description._getSemanticsImpl(iattr);
- int comp = VertexDescription.getComponentCount(semantics);
- m_vertexAttributes[iattr].insertRange(comp * pathIndexEnd,
- m_vertexAttributes[iattr], comp * pathIndexStart, comp,
- true, 1, comp * oldPointCount);
- }
- }
-
- for (int ipath = pathCount; ipath > pathIndex; ipath--) {
- int iend = m_paths.read(ipath);
- m_paths.write(ipath, iend + 1);
- }
-
- m_pathFlags.clearBits(pathIndex, (byte) PathFlags.enumClosed);
- }
-
- // Reviewed vs. Native Jan 11, 2011
- // Major Changes on 16th of January
- public void openAllPathsAndDuplicateStartVertex() {
- _touch();
- if (m_bPolygon)
- throw GeometryException.GeometryInternalError();// do not call this
- // method on a
- // polygon
-
- if (m_pathFlags == null)// if (!m_pathFlags)
- throw GeometryException.GeometryInternalError();
-
- _verifyAllStreams();
-
- int closedPathCount = 0;
- int pathCount = getPathCount();
- for (int i = 0; i < pathCount; i++) {
- if (m_pathFlags.read(i) == (byte) PathFlags.enumClosed) {
- closedPathCount++;
- }
- }
-
- for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
- if (m_vertexAttributes[iattr] != null) {
- int semantics = m_description._getSemanticsImpl(iattr);// int
- // semantics
- // =
- // m_description._getSemanticsImpl(iattr);
- int comp = VertexDescription.getComponentCount(semantics);
- int newSize = comp * (m_pointCount + closedPathCount);
- m_vertexAttributes[iattr].resize(newSize);
-
- int offset = closedPathCount;
- int ipath = pathCount;
- for (int i = m_pointCount - 1; i >= 0; i--) {
- if (i + 1 == m_paths.read(ipath)) {
- ipath--;
- if (m_pathFlags.read(ipath) == (byte) PathFlags.enumClosed) {
- int istart = m_paths.read(ipath);
-
- for (int c = 0; c < comp; c++) {
- double v = m_vertexAttributes[iattr]
- .readAsDbl(comp * istart + c);
- m_vertexAttributes[iattr].writeAsDbl(comp
- * (offset + i) + c, v);
- }
-
- if (--offset == 0)
- break;
- }
- }
-
- for (int c = 0; c < comp; c++) {
- double v = m_vertexAttributes[iattr].readAsDbl(comp * i
- + c);
- m_vertexAttributes[iattr].writeAsDbl(comp
- * (offset + i) + c, v);
- }
- }
- }
- }
-
- int offset = closedPathCount;
- for (int ipath = pathCount; ipath > 0; ipath--) {
- int iend = m_paths.read(ipath);
- m_paths.write(ipath, iend + offset);
-
- if (m_pathFlags.read(ipath - 1) == (byte) PathFlags.enumClosed) {
- m_pathFlags.clearBits(ipath - 1, (byte) PathFlags.enumClosed);
-
- if (--offset == 0) {
- break;
- }
- }
- }
-
- m_pointCount += closedPathCount;
- }
-
- void closePathWithLine(int path_index) {
- // touch_();
- throwIfEmpty();
-
- byte pf = m_pathFlags.read(path_index);
- m_pathFlags.write(path_index, (byte) (pf | PathFlags.enumClosed));
- if (m_segmentFlags != null) {
- int vindex = getPathEnd(path_index) - 1;
- m_segmentFlags.write(vindex, (byte) SegmentFlags.enumLineSeg);
- m_segmentParamIndex.write(vindex, -1);
- }
- }
-
- void closePathWithLine() {
- throwIfEmpty();
- m_bPathStarted = false;
- closePathWithLine(getPathCount() - 1);
- }
-
- // Reviewed vs. Native Jan 11, 2011
-
- /**
- * Closes all open curves by adding an implicit line segment from the end
- * point to the start point.
- */
- public void closeAllPaths() {
- _touch();
- if (m_bPolygon || isEmptyImpl())
- return;
-
- m_bPathStarted = false;
-
- for (int ipath = 0, npart = m_paths.size() - 1; ipath < npart; ipath++) {
- if (isClosedPath(ipath))
- continue;
-
- byte pf = m_pathFlags.read(ipath);
- m_pathFlags.write(ipath, (byte) (pf | PathFlags.enumClosed));
- // if (m_segmentFlags)
- // {
- // m_segmentFlags.write(m_pointCount - 1,
- // (byte)SegmentFlags.LineSeg));
- // m_segmentParamIndex.write(m_pointCount - 1, -1);
- // }
- }
- }
-
- // Reviewed vs. Native Jan 11, 2011
-
- /**
- * Returns the size of the segment data for the given segment type.
- *
- * @param flag is one of the segment flags from the SegmentFlags enum.
- * @return the size of the segment params as the number of doubles.
- */
- public static int getSegmentDataSize(byte flag) {
- return _segmentParamSizes[flag];
- }
-
- // Reviewed vs. Native Jan 11, 2011
-
- /**
- * Closes last path of the MultiPathImpl with the Bezier Segment.
- *
- * The start point of the Bezier is the last point of the path and the last
- * point of the bezier is the first point of the path.
- */
- public void closePathWithBezier(Point2D controlPoint1, Point2D controlPoint2) {
- _touch();
- if (isEmptyImpl())
- throw new GeometryException(
- "Invalid call. This operation cannot be performed on an empty geometry.");
-
- m_bPathStarted = false;
-
- int pathIndex = m_paths.size() - 2;
- byte pf = m_pathFlags.read(pathIndex);
- m_pathFlags
- .write(pathIndex,
- (byte) (pf | PathFlags.enumClosed | PathFlags.enumHasNonlinearSegments));
- _initSegmentData(6);
-
- byte oldType = m_segmentFlags
- .read((byte) ((m_pointCount - 1) & SegmentFlags.enumSegmentMask));
- m_segmentFlags.write(m_pointCount - 1,
- (byte) (SegmentFlags.enumBezierSeg));
-
- int curveIndex = m_curveParamwritePoint;
- if (getSegmentDataSize(oldType) < getSegmentDataSize((byte) SegmentFlags.enumBezierSeg)) {
- m_segmentParamIndex.write(m_pointCount - 1, m_curveParamwritePoint);
- m_curveParamwritePoint += 6;
- } else {
- // there was a closing bezier curve or an arc here. We can reuse the
- // storage.
- curveIndex = m_segmentParamIndex.read(m_pointCount - 1);
- }
-
- double z;
- m_segmentParams.write(curveIndex, controlPoint1.x);
- m_segmentParams.write(curveIndex + 1, controlPoint1.y);
- z = 0;// TODO: calculate me.
- m_segmentParams.write(curveIndex + 2, z);
-
- m_segmentParams.write(curveIndex + 3, controlPoint2.x);
- m_segmentParams.write(curveIndex + 4, controlPoint2.y);
- z = 0;// TODO: calculate me.
- m_segmentParams.write(curveIndex + 5, z);
- }
-
- // Reviewed vs. Native Jan 11, 2011
-
- /**
- * Returns True if the given path is closed (represents a Ring).
- */
- public boolean isClosedPath(int ipath) {
- // Should we make a function called _UpdateClosedPathFlags and call it
- // here?
- return ((byte) (m_pathFlags.read(ipath) & PathFlags.enumClosed)) != 0;
- }
-
- public boolean isClosedPathInXYPlane(int path_index) {
- if (isClosedPath(path_index))
- return true;
- int istart = getPathStart(path_index);
- int iend = getPathEnd(path_index) - 1;
- if (istart > iend)
- return false;
- Point2D ptS = getXY(istart);
- Point2D ptE = getXY(iend);
- return ptS.isEqual(ptE);
- }
-
- // Reviewed vs. Native Jan 11, 2011
-
- /**
- * Returns True if the given path might have non-linear segments.
- */
- public boolean hasNonLinearSegments(int ipath) {
- // Should we make a function called _UpdateHasNonLinearSegmentsFlags and
- // call it here?
- return (m_pathFlags.read(ipath) & PathFlags.enumHasNonlinearSegments) != 0;
- }
-
- // Reviewed vs. Native Jan 11, 2011
- public void addSegment(Segment segment, boolean bStartNewPath) {
- mergeVertexDescription(segment.getDescription());
- if (segment.getType() == Type.Line) {
- Point point = new Point();
- if (bStartNewPath || isEmpty()) {
- segment.queryStart(point);
- startPath(point);
- }
-
- segment.queryEnd(point);
- lineTo(point);
- } else {
- throw GeometryException.GeometryInternalError();
- }
- }
-
- // Reviewed vs. Native Jan 11, 2011
-
- /**
- * adds a rectangular closed Path to the MultiPathImpl.
- *
- * @param envSrc is the source rectangle.
- * @param bReverse Creates reversed path.
- */
- public void addEnvelope(Envelope2D envSrc, boolean bReverse) {
- boolean bWasEmpty = m_pointCount == 0;
-
- startPath(envSrc.xmin, envSrc.ymin);
- if (bReverse) {
- lineTo(envSrc.xmax, envSrc.ymin);
- lineTo(envSrc.xmax, envSrc.ymax);
- lineTo(envSrc.xmin, envSrc.ymax);
- } else {
- lineTo(envSrc.xmin, envSrc.ymax);
- lineTo(envSrc.xmax, envSrc.ymax);
- lineTo(envSrc.xmax, envSrc.ymin);
- }
-
- closePathWithLine();
- m_bPathStarted = false;
-
- if (bWasEmpty && !bReverse) {
- _setDirtyFlag(DirtyFlags.DirtyIsEnvelope, false);// now we no(sic?)
- // the polypath
- // is envelope
- }
- }
-
- // Reviewed vs. Native Jan 11, 2011
-
- /**
- * adds a rectangular closed Path to the MultiPathImpl.
- *
- * @param envSrc is the source rectangle.
- * @param bReverse Creates reversed path.
- */
- public void addEnvelope(Envelope envSrc, boolean bReverse) {
- if (envSrc.isEmpty())
- return;
-
- boolean bWasEmpty = m_pointCount == 0;
- Point pt = new Point(m_description);// getDescription());
- for (int i = 0, n = 4; i < n; i++) {
- int j = bReverse ? n - i - 1 : i;
-
- envSrc.queryCornerByVal(j, pt);
- if (i == 0)
- startPath(pt);
- else
- lineTo(pt);
- }
-
- closePathWithLine();
- m_bPathStarted = false;
-
- if (bWasEmpty && !bReverse)
- _setDirtyFlag(DirtyFlags.DirtyIsEnvelope, false);// now we know the
- // polypath is
- // envelope
- }
-
- // Reviewed vs. Native Jan 11, 2011
- public void add(MultiPathImpl src, boolean bReversePaths) {
- for (int i = 0; i < src.getPathCount(); i++)
- addPath(src, i, !bReversePaths);
- }
-
- public void addPath(MultiPathImpl src, int srcPathIndex, boolean bForward) {
- insertPath(-1, src, srcPathIndex, bForward);
- }
-
- // Reviewed vs. Native Jan 11, 2011 Significant changes to last for loop
- public void addPath(Point2D[] _points, int count, boolean bForward) {
- insertPath(-1, _points, 0, count, bForward);
- }
-
- public void addSegmentsFromPath(MultiPathImpl src, int src_path_index,
- int src_segment_from, int src_segment_count,
- boolean b_start_new_path) {
- if (!b_start_new_path && getPathCount() == 0)
- b_start_new_path = true;
-
- if (src_path_index < 0)
- src_path_index = src.getPathCount() - 1;
-
- if (src_path_index >= src.getPathCount() || src_segment_from < 0
- || src_segment_count < 0
- || src_segment_count > src.getSegmentCount(src_path_index))
- throw new GeometryException("index out of bounds");
-
- if (src_segment_count == 0)
- return;
-
- boolean bIncludesClosingSegment = src.isClosedPath(src_path_index)
- && src_segment_from + src_segment_count == src
- .getSegmentCount(src_path_index);
-
- if (bIncludesClosingSegment && src_segment_count == 1)
- return;// cannot add a closing segment alone.
-
- m_bPathStarted = false;
-
- mergeVertexDescription(src.getDescription());
- int src_point_count = src_segment_count;
- int srcFromPoint = src.getPathStart(src_path_index) + src_segment_from
- + 1;
- if (b_start_new_path)// adding a new path.
- {
- src_point_count++;// add start point.
- srcFromPoint--;
- }
-
- if (bIncludesClosingSegment) {
- src_point_count--;
- }
-
- int oldPointCount = m_pointCount;
- _resizeImpl(m_pointCount + src_point_count);
- _verifyAllStreams();
-
- if (b_start_new_path) {
- if (src_point_count == 0)
- return;// happens when adding a single closing segment to the
- // new path
-
- m_paths.add(m_pointCount);
-
- byte flags = src.m_pathFlags.read(src_path_index);
- flags &= ~(byte) PathFlags.enumCalcMask;// remove calculated flags
-
- if (m_bPolygon)
- flags |= (byte) PathFlags.enumClosed;
-
- m_pathFlags.write(m_pathFlags.size() - 1, flags);
- m_pathFlags.add((byte) 0);
- } else {
- m_paths.write(m_pathFlags.size() - 1, m_pointCount);
- }
-
- // Index_type absoluteIndex = pathStart + before_point_index;
-
- for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
- int semantics = m_description.getSemantics(iattr);
- int comp = VertexDescription.getComponentCount(semantics);
-
- int isrcAttr = src.m_description.getAttributeIndex(semantics);
- if (isrcAttr < 0 || src.m_vertexAttributes[isrcAttr] == null) {// The
- // source
- // does
- // not
- // have
- // the
- // attribute.
- // insert
- // default
- // value
- double v = VertexDescription.getDefaultValue(semantics);
- m_vertexAttributes[iattr].insertRange(comp * oldPointCount, v,
- src_point_count * comp, comp * oldPointCount);
- continue;
- }
-
- // add vertices to the given stream
- boolean b_forward = true;
- m_vertexAttributes[iattr].insertRange(comp * oldPointCount,
- src.m_vertexAttributes[isrcAttr], comp * srcFromPoint,
- src_point_count * comp, b_forward, comp, comp
- * oldPointCount);
- }
-
- if (hasNonLinearSegments()) {
- // TODO: implement me. For example as a while loop over all curves.
- // Replace, calling ReplaceSegment
- throw GeometryException.GeometryInternalError();
- // m_segment_flags->write_range((get_path_start(path_index) +
- // before_point_index + src_point_count), (oldPointCount -
- // get_path_start(path_index) - before_point_index),
- // m_segment_flags, (get_path_start(path_index) +
- // before_point_index), true, 1);
- // m_segment_param_index->write_range((get_path_start(path_index) +
- // before_point_index + src_point_count), (oldPointCount -
- // get_path_start(path_index) - before_point_index),
- // m_segment_param_index, (get_path_start(path_index) +
- // before_point_index), true, 1);
- // for (Index_type i = get_path_start(path_index) +
- // before_point_index, n = get_path_start(path_index) +
- // before_point_index + src_point_count; i < n; i++)
- // {
- // m_segment_flags->write(i, (int8_t)enum_value1(Segment_flags,
- // enum_line_seg));
- // m_segment_param_index->write(i, -1);
- // }
- }
-
- if (src.hasNonLinearSegments(src_path_index)) {
- // TODO: implement me. For example as a while loop over all curves.
- // Replace, calling ReplaceSegment
- throw GeometryException.GeometryInternalError();
- }
-
- notifyModified(DirtyFlags.DirtyCoordinates);
- }
-
- // Reviewed vs. Native Jan 11, 2011
- public void reverseAllPaths() {
- for (int i = 0, n = getPathCount(); i < n; i++) {
- reversePath(i);
- }
- }
-
- // Reviewed vs. Native Jan 11, 2011
- public void reversePath(int pathIndex) {
- _verifyAllStreams();
- int pathCount = getPathCount();
- if (pathIndex >= pathCount)
- throw new IllegalArgumentException();
-
- int reversedPathStart = getPathStart(pathIndex);
- int reversedPathSize = getPathSize(pathIndex);
- int offset = isClosedPath(pathIndex) ? 1 : 0;
-
- // TODO: a bug for the non linear segments here.
- // There could be an issue here if someone explicity closes the path
- // with the same start/end point.
- for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
- if (m_vertexAttributes[iattr] != null) {
- int semantics = m_description._getSemanticsImpl(iattr);
- int comp = VertexDescription.getComponentCount(semantics);
- m_vertexAttributes[iattr].reverseRange(comp
- * (reversedPathStart + offset), comp
- * (reversedPathSize - offset), comp);
- }
- }
-
- notifyModified(DirtyFlags.DirtyCoordinates);
- }
-
- // Reviewed vs. Native Jan 11, 2011
- // TODO: Nonlinearsegments
- public void removePath(int pathIndex) {
- _verifyAllStreams();
- int pathCount = getPathCount();
-
- if (pathIndex < 0)
- pathIndex = pathCount - 1;
-
- if (pathIndex >= pathCount)
- throw new IllegalArgumentException();
-
- boolean bDirtyRingAreas2D = _hasDirtyFlag(DirtyFlags.DirtyRingAreas2D);
-
- int removedPathStart = getPathStart(pathIndex);
- int removedPathSize = getPathSize(pathIndex);
-
- // Remove the attribute values for the path
- for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
- if (m_vertexAttributes[iattr] != null) {
- int semantics = m_description._getSemanticsImpl(iattr);
- int comp = VertexDescription.getComponentCount(semantics);
- m_vertexAttributes[iattr].eraseRange(comp * removedPathStart,
- comp * removedPathSize, comp * m_pointCount);
- }
- }
-
- // Change the start of each path after the removed path
- for (int i = pathIndex + 1; i <= pathCount; i++) {
- int istart = m_paths.read(i);
- m_paths.write(i - 1, istart - removedPathSize);
- }
-
- if (m_pathFlags == null) {
- for (int i = pathIndex + 1; i <= pathCount; i++) {
- byte flags = m_pathFlags.read(i);
- m_pathFlags.write(i - 1, flags);
- }
- }
-
- m_paths.resize(pathCount);
- m_pathFlags.resize(pathCount);
- m_pointCount -= removedPathSize;
- m_reservedPointCount -= removedPathSize;
-
- notifyModified(DirtyFlags.DirtyCoordinates);
- }
-
- // TODO: Nonlinearsegments
- public void insertPath(int pathIndex, MultiPathImpl src, int srcPathIndex,
- boolean bForward) {
- if (src == this)
- throw new IllegalArgumentException();
-
- if (srcPathIndex >= src.getPathCount())
- throw new IllegalArgumentException();
-
- int oldPathCount = getPathCount();
- if (pathIndex > oldPathCount)
- throw new IllegalArgumentException();
-
- if (pathIndex < 0)
- pathIndex = oldPathCount;
-
- if (srcPathIndex < 0)
- srcPathIndex = src.getPathCount() - 1;
-
- m_bPathStarted = false;
-
- mergeVertexDescription(src.m_description);// merge attributes from the
- // source
-
- src._verifyAllStreams();// the source need to be correct.
-
- int srcPathIndexStart = src.getPathStart(srcPathIndex);
- int srcPathSize = src.getPathSize(srcPathIndex);
- int oldPointCount = m_pointCount;
- int offset = src.isClosedPath(srcPathIndex) && !bForward ? 1 : 0;
-
- _resizeImpl(m_pointCount + srcPathSize);
- _verifyAllStreams();
- int pathIndexStart = pathIndex < oldPathCount ? getPathStart(pathIndex)
- : oldPointCount;
-
- // Copy all attribute values.
- for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
- int semantics = m_description._getSemanticsImpl(iattr);
- int isrcAttr = src.m_description.getAttributeIndex(semantics);
-
- int comp = VertexDescription.getComponentCount(semantics);
-
- if (isrcAttr >= 0 && src.m_vertexAttributes[isrcAttr] != null) {
- if (offset != 0)
- m_vertexAttributes[iattr].insertRange(
- pathIndexStart * comp,
- src.m_vertexAttributes[isrcAttr], comp
- * srcPathIndexStart, comp, true, comp, comp
- * oldPointCount);
- m_vertexAttributes[iattr].insertRange((pathIndexStart + offset)
- * comp, src.m_vertexAttributes[isrcAttr], comp
- * (srcPathIndexStart + offset), comp
- * (srcPathSize - offset), bForward, comp, comp
- * (oldPointCount + offset));
- } else {
- // Need to make room for the attributes, so we copy default
- // values in
-
- double v = VertexDescription.getDefaultValue(semantics);
- m_vertexAttributes[iattr].insertRange(pathIndexStart * comp, v,
- comp * srcPathSize, comp * oldPointCount);
- }
- }
-
- int newPointCount = oldPointCount + srcPathSize;
- m_paths.add(newPointCount);
-
- for (int ipath = oldPathCount; ipath >= pathIndex + 1; ipath--) {
- int iend = m_paths.read(ipath - 1);
- m_paths.write(ipath, iend + srcPathSize);
- }
-
- // ========================== todo: NonLinearSegments =================
- if (src.hasNonLinearSegments(srcPathIndex)) {
-
- }
-
- m_pathFlags.add((byte) 0);
-
- // _ASSERT(m_pathFlags.size() == m_paths.size());
-
- for (int ipath = oldPathCount - 1; ipath >= pathIndex + 1; ipath--) {
- byte flags = m_pathFlags.read(ipath);
- flags &= ~(byte) PathFlags.enumCalcMask;// remove calculated flags
- m_pathFlags.write(ipath + 1, flags);
- }
-
- AttributeStreamOfInt8 srcPathFlags = src.getPathFlagsStreamRef();
- byte flags = srcPathFlags.read(srcPathIndex);
- flags &= ~(byte) PathFlags.enumCalcMask;// remove calculated flags
-
- if (m_bPolygon)
- flags |= (byte) PathFlags.enumClosed;
-
- m_pathFlags.write(pathIndex, flags);
- }
-
- public void insertPath(int pathIndex, Point2D[] points, int pointsOffset,
- int count, boolean bForward) {
- int oldPathCount = getPathCount();
- if (pathIndex > oldPathCount)
- throw new IllegalArgumentException();
-
- if (pathIndex < 0)
- pathIndex = oldPathCount;
-
- m_bPathStarted = false;
-
- int oldPointCount = m_pointCount;
-
- // Copy all attribute values.
- if (points != null) {
- _resizeImpl(m_pointCount + count);
- _verifyAllStreams();
-
- int pathStart = pathIndex < oldPathCount ? getPathStart(pathIndex)
- : oldPointCount;
-
- for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
- int semantics = m_description._getSemanticsImpl(iattr);
-
- if (semantics == VertexDescription.Semantics.POSITION) {
- // copy range to make place for new vertices
- m_vertexAttributes[iattr].writeRange(
- 2 * (pathStart + count),
- 2 * (oldPointCount - pathIndex),
- m_vertexAttributes[iattr], 2 * pathStart, true, 2);
-
- AttributeStreamOfDbl position = (AttributeStreamOfDbl) (AttributeStreamBase) getAttributeStreamRef(semantics);
-
- int j = pathStart;
- for (int i = 0; i < count; i++, j++) {
- int index = (bForward ? pointsOffset + i : pointsOffset
- + count - i - 1);
- position.write(2 * j, points[index].x);
- position.write(2 * j + 1, points[index].y);
- }
- } else {
- // Need to make room for the attributes, so we copy default
- // values in
-
- int comp = VertexDescription.getComponentCount(semantics);
- double v = VertexDescription.getDefaultValue(semantics);
- m_vertexAttributes[iattr].insertRange(pathStart * comp, v,
- comp * count, comp * oldPointCount);
- }
- }
- } else {
- _verifyAllStreams();
- }
-
- m_paths.add(m_pointCount);
-
- for (int ipath = oldPathCount; ipath >= pathIndex + 1; ipath--) {
- int iend = m_paths.read(ipath - 1);
- m_paths.write(ipath, iend + count);
- }
-
- m_pathFlags.add((byte) 0);
-
- // _ASSERT(m_pathFlags.size() == m_paths.size());
-
- for (int ipath = oldPathCount - 1; ipath >= pathIndex + 1; ipath--) {
- byte flags = m_pathFlags.read(ipath);
- flags &= ~(byte) PathFlags.enumCalcMask;// remove calculated flags
- m_pathFlags.write(ipath + 1, flags);
- }
-
- if (m_bPolygon)
- m_pathFlags.write(pathIndex, (byte) PathFlags.enumClosed);
- }
-
- public void insertPoints(int pathIndex, int beforePointIndex,
- MultiPathImpl src, int srcPathIndex, int srcPointIndexFrom,
- int srcPointCount, boolean bForward) {
- if (pathIndex < 0)
- pathIndex = getPathCount();
-
- if (srcPathIndex < 0)
- srcPathIndex = src.getPathCount() - 1;
-
- if (pathIndex > getPathCount() || beforePointIndex >= 0
- && beforePointIndex > getPathSize(pathIndex)
- || srcPathIndex >= src.getPathCount()
- || srcPointCount > src.getPathSize(srcPathIndex))
- throw new GeometryException("index out of bounds");
-
- if (srcPointCount == 0)
- return;
-
- mergeVertexDescription(src.m_description);
-
- if (pathIndex == getPathCount())// adding a new path.
- {
- m_paths.add(m_pointCount);
-
- byte flags = src.m_pathFlags.read(srcPathIndex);
- flags &= ~(byte) PathFlags.enumCalcMask;// remove calculated flags
-
- if (!m_bPolygon)
- m_pathFlags.add(flags);
- else
- m_pathFlags.add((byte) (flags | PathFlags.enumClosed));
- }
-
- if (beforePointIndex < 0)
- beforePointIndex = getPathSize(pathIndex);
-
- int oldPointCount = m_pointCount;
- _resizeImpl(m_pointCount + srcPointCount);
- _verifyAllStreams();
- src._verifyAllStreams();
-
- int pathStart = getPathStart(pathIndex);
- int absoluteIndex = pathStart + beforePointIndex;
-
- if (srcPointCount < 0)
- srcPointCount = src.getPathSize(srcPathIndex);
-
- int srcPathStart = src.getPathStart(srcPathIndex);
- int srcAbsoluteIndex = srcPathStart + srcPointCount;
-
- for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
- int semantics = m_description._getSemanticsImpl(iattr);
- int comp = VertexDescription.getComponentCount(semantics);
-
- int isrcAttr = src.m_description.getAttributeIndex(semantics);
- if (isrcAttr < 0 || src.m_vertexAttributes[isrcAttr] == null) // The
- // source
- // does
- // not
- // have
- // the
- // attribute.
- {
- double v = VertexDescription.getDefaultValue(semantics);
- m_vertexAttributes[iattr].insertRange(comp * absoluteIndex, v,
- srcAbsoluteIndex * comp, comp * oldPointCount);
- continue;
- }
-
- // add vertices to the given stream
- m_vertexAttributes[iattr].insertRange(comp
- * (pathStart + beforePointIndex),
- src.m_vertexAttributes[isrcAttr], comp
- * (srcPathStart + srcPointIndexFrom), srcPointCount
- * comp, bForward, comp, comp * oldPointCount);
- }
-
- if (hasNonLinearSegments()) {// TODO: probably a bug here when a new
- // path is added.
- m_segmentFlags.writeRange((getPathStart(pathIndex)
- + beforePointIndex + srcPointCount), (oldPointCount
- - getPathStart(pathIndex) - beforePointIndex),
- m_segmentFlags,
- (getPathStart(pathIndex) + beforePointIndex), true, 1);
- m_segmentParamIndex.writeRange((getPathStart(pathIndex)
- + beforePointIndex + srcPointCount), (oldPointCount
- - getPathStart(pathIndex) - beforePointIndex),
- m_segmentParamIndex,
- (getPathStart(pathIndex) + beforePointIndex), true, 1);
- for (int i = getPathStart(pathIndex) + beforePointIndex, n = getPathStart(pathIndex)
- + beforePointIndex + srcPointCount; i < n; i++) {
- m_segmentFlags.write(i, (byte) SegmentFlags.enumLineSeg);
- m_segmentParamIndex.write(i, -1);
- }
- }
-
- if (src.hasNonLinearSegments(srcPathIndex)) {
- // TODO: implement me. For example as a while loop over all curves.
- // Replace, calling ReplaceSegment
- throw GeometryException.GeometryInternalError();
- }
-
- for (int ipath = pathIndex + 1, npaths = getPathCount(); ipath <= npaths; ipath++) {
- int num = m_paths.read(ipath);
- m_paths.write(ipath, num + srcPointCount);
- }
- }
-
- public void insertPoints(int pathIndex, int beforePointIndex,
- Point2D[] src, int srcPointIndexFrom, int srcPointCount,
- boolean bForward) {
- if (pathIndex < 0)
- pathIndex = getPathCount();
-
- if (pathIndex > getPathCount()
- || beforePointIndex > getPathSize(pathIndex)
- || srcPointIndexFrom < 0 || srcPointCount > src.length)
- throw new GeometryException("index out of bounds");
-
- if (srcPointCount == 0)
- return;
-
- if (pathIndex == getPathCount())// adding a new path.
- {
- m_paths.add(m_pointCount);
-
- if (!m_bPolygon)
- m_pathFlags.add((byte) 0);
- else
- m_pathFlags.add((byte) PathFlags.enumClosed);
- }
-
- if (beforePointIndex < 0)
- beforePointIndex = getPathSize(pathIndex);
-
- _verifyAllStreams();
- int oldPointCount = m_pointCount;
- _resizeImpl(m_pointCount + srcPointCount);
- _verifyAllStreams();
- for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
- int semantics = m_description._getSemanticsImpl(iattr);
- int comp = VertexDescription.getComponentCount(semantics);
- // copy range to make place for new vertices
- m_vertexAttributes[iattr]
- .writeRange(
- comp
- * (getPathStart(pathIndex)
- + beforePointIndex + srcPointCount),
- (oldPointCount - getPathStart(pathIndex) - beforePointIndex)
- * comp,
- m_vertexAttributes[iattr],
- comp * (getPathStart(pathIndex) + beforePointIndex),
- true, comp);
-
- if (iattr == 0) {
- // add vertices to the given stream
- ((AttributeStreamOfDbl) (AttributeStreamBase) m_vertexAttributes[iattr])
- .writeRange(comp
- * (getPathStart(pathIndex) + beforePointIndex),
- srcPointCount, src, srcPointIndexFrom, bForward);
- } else {
- double v = VertexDescription.getDefaultValue(semantics);
- m_vertexAttributes[iattr].setRange(v,
- (getPathStart(pathIndex) + beforePointIndex) * comp,
- srcPointCount * comp);
- }
- }
-
- if (hasNonLinearSegments()) {
- m_segmentFlags.writeRange((getPathStart(pathIndex)
- + beforePointIndex + srcPointCount), (oldPointCount
- - getPathStart(pathIndex) - beforePointIndex),
- m_segmentFlags,
- (getPathStart(pathIndex) + beforePointIndex), true, 1);
- m_segmentParamIndex.writeRange((getPathStart(pathIndex)
- + beforePointIndex + srcPointCount), (oldPointCount
- - getPathStart(pathIndex) - beforePointIndex),
- m_segmentParamIndex,
- (getPathStart(pathIndex) + beforePointIndex), true, 1);
- m_segmentFlags.setRange((byte) SegmentFlags.enumLineSeg,
- getPathStart(pathIndex) + beforePointIndex, srcPointCount);
- m_segmentParamIndex.setRange(-1, getPathStart(pathIndex)
- + beforePointIndex, srcPointCount);
- }
-
- for (int ipath = pathIndex + 1, npaths = getPathCount(); ipath <= npaths; ipath++) {
- m_paths.write(ipath, m_paths.read(ipath) + srcPointCount);
- }
- }
-
- public void insertPoint(int pathIndex, int beforePointIndex, Point2D pt) {
- int pathCount = getPathCount();
-
- if (pathIndex < 0)
- pathIndex = getPathCount();
-
- if (pathIndex >= pathCount || beforePointIndex > getPathSize(pathIndex))
- throw new GeometryException("index out of bounds");
-
- if (pathIndex == getPathCount())// adding a new path.
- {
- m_paths.add(m_pointCount);
-
- if (!m_bPolygon)
- m_pathFlags.add((byte) 0);
- else
- m_pathFlags.add((byte) PathFlags.enumClosed);
- }
-
- if (beforePointIndex < 0)
- beforePointIndex = getPathSize(pathIndex);
-
- int oldPointCount = m_pointCount;
- _resizeImpl(m_pointCount + 1);
- _verifyAllStreams();
-
- int pathStart = getPathStart(pathIndex);
-
- ((AttributeStreamOfDbl) (AttributeStreamBase) m_vertexAttributes[0])
- .insert(2 * (pathStart + beforePointIndex), pt,
- 2 * oldPointCount);
-
- for (int iattr = 1, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
- int semantics = m_description._getSemanticsImpl(iattr);
- int comp = VertexDescription.getComponentCount(semantics);
-
- // Need to make room for the attribute, so we copy a default value
- // in
- double v = VertexDescription.getDefaultValue(semantics);
- m_vertexAttributes[iattr].insertRange(comp
- * (pathStart + beforePointIndex), v, comp, comp
- * oldPointCount);
- }
-
- for (int ipath = pathIndex + 1, npaths = pathCount; ipath <= npaths; ipath++) {
- m_paths.write(ipath, m_paths.read(ipath) + 1);
- }
- }
-
- public void insertPoint(int pathIndex, int beforePointIndex, Point pt) {
- int pathCount = getPathCount();
-
- if (pathIndex < 0)
- pathIndex = getPathCount();
-
- if (pathIndex >= pathCount || beforePointIndex > getPathSize(pathIndex))
- throw new GeometryException("index out of bounds");
-
- if (pathIndex == getPathCount())// adding a new path.
- {
- m_paths.add(m_pointCount);
-
- if (!m_bPolygon)
- m_pathFlags.add((byte) 0);
- else
- m_pathFlags.add((byte) PathFlags.enumClosed);
- }
-
- if (beforePointIndex < 0)
- beforePointIndex = getPathSize(pathIndex);
-
- mergeVertexDescription(pt.getDescription());
- int oldPointCount = m_pointCount;
- _resizeImpl(m_pointCount + 1);
- _verifyAllStreams();
-
- int pathStart = getPathStart(pathIndex);
-
- for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
- int semantics = m_description._getSemanticsImpl(iattr);
- int comp = VertexDescription.getComponentCount(semantics);
-
- if (pt.hasAttribute(semantics)) {
- m_vertexAttributes[iattr].insertAttributes(comp
- * (pathStart + beforePointIndex), pt, semantics, comp
- * oldPointCount);
- } else {
- // Need to make room for the attribute, so we copy a default
- // value in
- double v = VertexDescription.getDefaultValue(semantics);
- m_vertexAttributes[iattr].insertRange(comp
- * (pathStart + beforePointIndex), v, comp, comp
- * oldPointCount);
- }
- }
+ // / Cpp ///
+ // Reviewed vs. Native Jan 11, 2011
+ public MultiPathImpl(boolean bPolygon) {
+ m_bPolygon = bPolygon;
+
+ m_bPathStarted = false;
+ m_curveParamwritePoint = 0;
+ m_cachedLength2D = 0;
+ m_cachedArea2D = 0;
+ m_pointCount = 0;
+ m_description = VertexDescriptionDesignerImpl.getDefaultDescriptor2D();
+ m_cachedRingAreas2D = null;
+ m_currentPathIndex = 0;
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ public MultiPathImpl(boolean bPolygon, VertexDescription description) {
+ if (description == null)
+ throw new IllegalArgumentException();
+
+ m_bPolygon = bPolygon;
+
+ m_bPathStarted = false;
+ m_curveParamwritePoint = 0;
+ m_cachedLength2D = 0;
+ m_cachedArea2D = 0;
+ m_pointCount = 0;
+ m_description = description;
+ m_cachedRingAreas2D = null;
+ m_currentPathIndex = 0;
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ protected void _initPathStartPoint() {
+ _touch();
+ if (m_moveToPoint == null)
+ m_moveToPoint = new Point(m_description);
+ else
+ m_moveToPoint.assignVertexDescription(m_description);
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ /**
+ * Starts a new Path at the Point.
+ */
+ public void startPath(double x, double y) {
+ Point2D endPoint = new Point2D();
+ endPoint.x = x;
+ endPoint.y = y;
+ startPath(endPoint);
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ public void startPath(Point2D point) {
+ _initPathStartPoint();
+ m_moveToPoint.setXY(point);
+ m_bPathStarted = true;
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ public void startPath(Point3D point) {
+ _initPathStartPoint();
+ m_moveToPoint.setXYZ(point);
+ assignVertexDescription(m_moveToPoint.getDescription());
+ m_bPathStarted = true;
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ public void startPath(Point point) {
+ if (point.isEmpty())
+ throw new IllegalArgumentException();// throw new
+ // IllegalArgumentException();
+
+ mergeVertexDescription(point.getDescription());
+ _initPathStartPoint();
+ point.copyTo(m_moveToPoint);
+
+ // TODO check MultiPathImpl.cpp comment
+ // "//the description will be merged later"
+ // assignVertexDescription(m_moveToPoint.getDescription());
+ m_bPathStarted = true;
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ protected void _beforeNewSegment(int resizeBy) {
+ // Called for each new segment being added.
+ if (m_bPathStarted) {
+ _initPathStartPoint();// make sure the m_movetoPoint exists and has
+ // right vertex description
+
+ // The new path is started. Need to grow m_parts and m_pathFlags.
+ if (m_paths == null) {
+ m_paths = (AttributeStreamOfInt32) AttributeStreamBase
+ .createIndexStream(2);
+ m_paths.write(0, 0);
+ m_pathFlags = (AttributeStreamOfInt8) AttributeStreamBase
+ .createByteStream(2, (byte) 0);
+ } else {
+ // _ASSERT(m_parts.size() >= 2);
+ m_paths.resize(m_paths.size() + 1, 0);
+ m_pathFlags.resize(m_pathFlags.size() + 1, 0);
+ }
+
+ if (m_bPolygon) {
+ // Mark the path as closed
+ m_pathFlags.write(m_pathFlags.size() - 2,
+ (byte) PathFlags.enumClosed);
+ }
+
+ resizeBy++; // +1 for the StartPath point.
+ }
+
+ int oldcount = m_pointCount;
+ m_paths.write(m_paths.size() - 1, m_pointCount + resizeBy); // The
+ // NotifyModified
+ // will
+ // update
+ // the
+ // m_pointCount
+ // with this
+ // value.
+ _resizeImpl(oldcount + resizeBy);
+ m_pathFlags.write(m_paths.size() - 1, (byte) 0);
+
+ if (m_bPathStarted) {
+ setPointByVal(oldcount, m_moveToPoint);// setPoint(oldcount,
+ // m_moveToPoint); //finally
+ // set the start point to
+ // the geometry
+ m_bPathStarted = false;
+ }
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ protected void _finishLineTo() {
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ /**
+ * adds a Line Segment from the last Point to the given endPoint.
+ */
+ public void lineTo(double x, double y) {
+ _beforeNewSegment(1);
+ setXY(m_pointCount - 1, x, y);
+ _finishLineTo();
+ // Point2D endPoint = new Point2D();
+ // endPoint.x = x; endPoint.y = y;
+ // lineTo(endPoint);
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ public void lineTo(Point2D endPoint) {
+ _beforeNewSegment(1);
+ setXY(m_pointCount - 1, endPoint);
+ _finishLineTo();
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ public void lineTo(Point3D endPoint) {
+ _beforeNewSegment(1);
+ setXYZ(m_pointCount - 1, endPoint);
+ _finishLineTo();
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ public void lineTo(Point endPoint) {
+ _beforeNewSegment(1);
+ setPointByVal(m_pointCount - 1, endPoint);
+ _finishLineTo();
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ protected void _initSegmentData(int sz) {
+ if (m_segmentParamIndex == null) {
+ m_segmentFlags = (AttributeStreamOfInt8) AttributeStreamBase
+ .createByteStream(m_pointCount,
+ (byte) SegmentFlags.enumLineSeg);
+ m_segmentParamIndex = (AttributeStreamOfInt32) AttributeStreamBase
+ .createIndexStream(m_pointCount, -1);
+ }
+
+ int size = m_curveParamwritePoint + sz;
+ if (m_segmentParams == null) {
+ m_segmentParams = (AttributeStreamOfDbl) AttributeStreamBase
+ .createAttributeStreamWithPersistence(
+ VertexDescription.Persistence.enumDouble, size);
+ } else {
+ m_segmentParams.resize(size, 0);
+ }
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ protected void _finishBezierTo() {
+ // _ASSERT(m_segmentFlags != null);
+ // _ASSERT(m_segmentParamIndex != null);
+
+ m_segmentFlags.write(m_pointCount - 2,
+ (byte) SegmentFlags.enumBezierSeg);
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ /**
+ * adds a Cubic Bezier Segment to the current Path. The Bezier Segment
+ * connects the current last Point and the given endPoint.
+ */
+ public void bezierTo(Point2D controlPoint1, Point2D controlPoint2,
+ Point2D endPoint) {
+ _beforeNewSegment(1);
+ setXY(m_pointCount - 1, endPoint);
+ double z;
+ _initSegmentData(6);
+ m_pathFlags.setBits(m_pathFlags.size() - 1,
+ (byte) PathFlags.enumHasNonlinearSegments);
+ m_segmentParamIndex.write(m_pointCount - 2, m_curveParamwritePoint);
+ m_curveParamwritePoint += 6;
+ int curveIndex = m_curveParamwritePoint;
+ m_segmentParams.write(curveIndex, controlPoint1.x);
+ m_segmentParams.write(curveIndex + 1, controlPoint1.y);
+ z = 0;// TODO: calculate me.
+ m_segmentParams.write(curveIndex + 2, z);
+ m_segmentParams.write(curveIndex + 3, controlPoint2.x);
+ m_segmentParams.write(curveIndex + 4, controlPoint2.y);
+ z = 0;// TODO: calculate me.
+ m_segmentParams.write(curveIndex + 5, z);
+ _finishBezierTo();
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ public void openPath(int pathIndex) {
+ _touch();
+ if (m_bPolygon)
+ throw GeometryException.GeometryInternalError();// do not call this
+ // method on a
+ // polygon
+
+ int pathCount = getPathCount();
+ if (pathIndex > getPathCount())
+ throw new IllegalArgumentException();
+
+ if (m_pathFlags == null)
+ throw GeometryException.GeometryInternalError();
+
+ m_pathFlags.clearBits(pathIndex, (byte) PathFlags.enumClosed);
+ }
+
+ public void openPathAndDuplicateStartVertex(int pathIndex) {
+ _touch();
+ if (m_bPolygon)
+ throw GeometryException.GeometryInternalError();// do not call this
+ // method on a
+ // polygon
+
+ int pathCount = getPathCount();
+ if (pathIndex > pathCount)
+ throw GeometryException.GeometryInternalError();
+
+ if (!isClosedPath(pathIndex))
+ return;// do not open if open
+
+ if (m_pathFlags == null)// if (!m_pathFlags)
+ throw GeometryException.GeometryInternalError();
+
+ int oldPointCount = m_pointCount;
+ int pathIndexStart = getPathStart(pathIndex);
+ int pathIndexEnd = getPathEnd(pathIndex);
+ _resizeImpl(m_pointCount + 1); // resize does not write into m_paths
+ // anymore!
+ _verifyAllStreams();
+ for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
+ if (m_vertexAttributes[iattr] != null)// if
+ // (m_vertexAttributes[iattr])
+ {
+ int semantics = m_description._getSemanticsImpl(iattr);
+ int comp = VertexDescription.getComponentCount(semantics);
+ m_vertexAttributes[iattr].insertRange(comp * pathIndexEnd,
+ m_vertexAttributes[iattr], comp * pathIndexStart, comp,
+ true, 1, comp * oldPointCount);
+ }
+ }
+
+ for (int ipath = pathCount; ipath > pathIndex; ipath--) {
+ int iend = m_paths.read(ipath);
+ m_paths.write(ipath, iend + 1);
+ }
+
+ m_pathFlags.clearBits(pathIndex, (byte) PathFlags.enumClosed);
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ // Major Changes on 16th of January
+ public void openAllPathsAndDuplicateStartVertex() {
+ _touch();
+ if (m_bPolygon)
+ throw GeometryException.GeometryInternalError();// do not call this
+ // method on a
+ // polygon
+
+ if (m_pathFlags == null)// if (!m_pathFlags)
+ throw GeometryException.GeometryInternalError();
+
+ _verifyAllStreams();
+
+ int closedPathCount = 0;
+ int pathCount = getPathCount();
+ for (int i = 0; i < pathCount; i++) {
+ if (m_pathFlags.read(i) == (byte) PathFlags.enumClosed) {
+ closedPathCount++;
+ }
+ }
+
+ for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
+ if (m_vertexAttributes[iattr] != null) {
+ int semantics = m_description._getSemanticsImpl(iattr);// int
+ // semantics
+ // =
+ // m_description._getSemanticsImpl(iattr);
+ int comp = VertexDescription.getComponentCount(semantics);
+ int newSize = comp * (m_pointCount + closedPathCount);
+ m_vertexAttributes[iattr].resize(newSize);
+
+ int offset = closedPathCount;
+ int ipath = pathCount;
+ for (int i = m_pointCount - 1; i >= 0; i--) {
+ if (i + 1 == m_paths.read(ipath)) {
+ ipath--;
+ if (m_pathFlags.read(ipath) == (byte) PathFlags.enumClosed) {
+ int istart = m_paths.read(ipath);
+
+ for (int c = 0; c < comp; c++) {
+ double v = m_vertexAttributes[iattr]
+ .readAsDbl(comp * istart + c);
+ m_vertexAttributes[iattr].writeAsDbl(comp
+ * (offset + i) + c, v);
+ }
+
+ if (--offset == 0)
+ break;
+ }
+ }
+
+ for (int c = 0; c < comp; c++) {
+ double v = m_vertexAttributes[iattr].readAsDbl(comp * i
+ + c);
+ m_vertexAttributes[iattr].writeAsDbl(comp
+ * (offset + i) + c, v);
+ }
+ }
+ }
+ }
+
+ int offset = closedPathCount;
+ for (int ipath = pathCount; ipath > 0; ipath--) {
+ int iend = m_paths.read(ipath);
+ m_paths.write(ipath, iend + offset);
+
+ if (m_pathFlags.read(ipath - 1) == (byte) PathFlags.enumClosed) {
+ m_pathFlags.clearBits(ipath - 1, (byte) PathFlags.enumClosed);
+
+ if (--offset == 0) {
+ break;
+ }
+ }
+ }
+
+ m_pointCount += closedPathCount;
+ }
+
+ void closePathWithLine(int path_index) {
+ // touch_();
+ throwIfEmpty();
+
+ byte pf = m_pathFlags.read(path_index);
+ m_pathFlags.write(path_index, (byte) (pf | PathFlags.enumClosed));
+ if (m_segmentFlags != null) {
+ int vindex = getPathEnd(path_index) - 1;
+ m_segmentFlags.write(vindex, (byte) SegmentFlags.enumLineSeg);
+ m_segmentParamIndex.write(vindex, -1);
+ }
+ }
+
+ void closePathWithLine() {
+ throwIfEmpty();
+ m_bPathStarted = false;
+ closePathWithLine(getPathCount() - 1);
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ /**
+ * Closes all open curves by adding an implicit line segment from the end
+ * point to the start point.
+ */
+ public void closeAllPaths() {
+ _touch();
+ if (m_bPolygon || isEmptyImpl())
+ return;
+
+ m_bPathStarted = false;
+
+ for (int ipath = 0, npart = m_paths.size() - 1; ipath < npart; ipath++) {
+ if (isClosedPath(ipath))
+ continue;
+
+ byte pf = m_pathFlags.read(ipath);
+ m_pathFlags.write(ipath, (byte) (pf | PathFlags.enumClosed));
+ // if (m_segmentFlags)
+ // {
+ // m_segmentFlags.write(m_pointCount - 1,
+ // (byte)SegmentFlags.LineSeg));
+ // m_segmentParamIndex.write(m_pointCount - 1, -1);
+ // }
+ }
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ /**
+ * Returns the size of the segment data for the given segment type.
+ *
+ * @param flag
+ * is one of the segment flags from the SegmentFlags enum.
+ * @return the size of the segment params as the number of doubles.
+ */
+ public static int getSegmentDataSize(byte flag) {
+ return _segmentParamSizes[flag];
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ /**
+ * Closes last path of the MultiPathImpl with the Bezier Segment.
+ *
+ * The start point of the Bezier is the last point of the path and the last
+ * point of the bezier is the first point of the path.
+ */
+ public void closePathWithBezier(Point2D controlPoint1, Point2D controlPoint2) {
+ _touch();
+ if (isEmptyImpl())
+ throw new GeometryException(
+ "Invalid call. This operation cannot be performed on an empty geometry.");
+
+ m_bPathStarted = false;
+
+ int pathIndex = m_paths.size() - 2;
+ byte pf = m_pathFlags.read(pathIndex);
+ m_pathFlags
+ .write(pathIndex,
+ (byte) (pf | PathFlags.enumClosed | PathFlags.enumHasNonlinearSegments));
+ _initSegmentData(6);
+
+ byte oldType = m_segmentFlags
+ .read((byte) ((m_pointCount - 1) & SegmentFlags.enumSegmentMask));
+ m_segmentFlags.write(m_pointCount - 1,
+ (byte) (SegmentFlags.enumBezierSeg));
+
+ int curveIndex = m_curveParamwritePoint;
+ if (getSegmentDataSize(oldType) < getSegmentDataSize((byte) SegmentFlags.enumBezierSeg)) {
+ m_segmentParamIndex.write(m_pointCount - 1, m_curveParamwritePoint);
+ m_curveParamwritePoint += 6;
+ } else {
+ // there was a closing bezier curve or an arc here. We can reuse the
+ // storage.
+ curveIndex = m_segmentParamIndex.read(m_pointCount - 1);
+ }
+
+ double z;
+ m_segmentParams.write(curveIndex, controlPoint1.x);
+ m_segmentParams.write(curveIndex + 1, controlPoint1.y);
+ z = 0;// TODO: calculate me.
+ m_segmentParams.write(curveIndex + 2, z);
+
+ m_segmentParams.write(curveIndex + 3, controlPoint2.x);
+ m_segmentParams.write(curveIndex + 4, controlPoint2.y);
+ z = 0;// TODO: calculate me.
+ m_segmentParams.write(curveIndex + 5, z);
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ /**
+ * Returns True if the given path is closed (represents a Ring).
+ */
+ public boolean isClosedPath(int ipath) {
+ // Should we make a function called _UpdateClosedPathFlags and call it
+ // here?
+ return ((byte) (m_pathFlags.read(ipath) & PathFlags.enumClosed)) != 0;
+ }
+
+ public boolean isClosedPathInXYPlane(int path_index) {
+ if (isClosedPath(path_index))
+ return true;
+ int istart = getPathStart(path_index);
+ int iend = getPathEnd(path_index) - 1;
+ if (istart > iend)
+ return false;
+ Point2D ptS = getXY(istart);
+ Point2D ptE = getXY(iend);
+ return ptS.isEqual(ptE);
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ /**
+ * Returns True if the given path might have non-linear segments.
+ */
+ public boolean hasNonLinearSegments(int ipath) {
+ // Should we make a function called _UpdateHasNonLinearSegmentsFlags and
+ // call it here?
+ return (m_pathFlags.read(ipath) & PathFlags.enumHasNonlinearSegments) != 0;
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ public void addSegment(Segment segment, boolean bStartNewPath) {
+ mergeVertexDescription(segment.getDescription());
+ if (segment.getType() == Type.Line) {
+ Point point = new Point();
+ if (bStartNewPath || isEmpty()) {
+ segment.queryStart(point);
+ startPath(point);
+ }
+
+ segment.queryEnd(point);
+ lineTo(point);
+ } else {
+ throw GeometryException.GeometryInternalError();
+ }
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ /**
+ * adds a rectangular closed Path to the MultiPathImpl.
+ *
+ * @param envSrc
+ * is the source rectangle.
+ * @param bReverse
+ * Creates reversed path.
+ */
+ public void addEnvelope(Envelope2D envSrc, boolean bReverse) {
+ boolean bWasEmpty = m_pointCount == 0;
+
+ startPath(envSrc.xmin, envSrc.ymin);
+ if (bReverse) {
+ lineTo(envSrc.xmax, envSrc.ymin);
+ lineTo(envSrc.xmax, envSrc.ymax);
+ lineTo(envSrc.xmin, envSrc.ymax);
+ } else {
+ lineTo(envSrc.xmin, envSrc.ymax);
+ lineTo(envSrc.xmax, envSrc.ymax);
+ lineTo(envSrc.xmax, envSrc.ymin);
+ }
+
+ closePathWithLine();
+ m_bPathStarted = false;
+
+ if (bWasEmpty && !bReverse) {
+ _setDirtyFlag(DirtyFlags.DirtyIsEnvelope, false);// now we no(sic?)
+ // the polypath
+ // is envelope
+ }
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ /**
+ * adds a rectangular closed Path to the MultiPathImpl.
+ *
+ * @param envSrc
+ * is the source rectangle.
+ * @param bReverse
+ * Creates reversed path.
+ */
+ public void addEnvelope(Envelope envSrc, boolean bReverse) {
+ if (envSrc.isEmpty())
+ return;
+
+ boolean bWasEmpty = m_pointCount == 0;
+ Point pt = new Point(m_description);// getDescription());
+ for (int i = 0, n = 4; i < n; i++) {
+ int j = bReverse ? n - i - 1 : i;
+
+ envSrc.queryCornerByVal(j, pt);
+ if (i == 0)
+ startPath(pt);
+ else
+ lineTo(pt);
+ }
+
+ closePathWithLine();
+ m_bPathStarted = false;
+
+ if (bWasEmpty && !bReverse)
+ _setDirtyFlag(DirtyFlags.DirtyIsEnvelope, false);// now we know the
+ // polypath is
+ // envelope
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ public void add(MultiPathImpl src, boolean bReversePaths) {
+ for (int i = 0; i < src.getPathCount(); i++)
+ addPath(src, i, !bReversePaths);
+ }
+
+ public void addPath(MultiPathImpl src, int srcPathIndex, boolean bForward) {
+ insertPath(-1, src, srcPathIndex, bForward);
+ }
+
+ // Reviewed vs. Native Jan 11, 2011 Significant changes to last for loop
+ public void addPath(Point2D[] _points, int count, boolean bForward) {
+ insertPath(-1, _points, 0, count, bForward);
+ }
+
+ public void addSegmentsFromPath(MultiPathImpl src, int src_path_index,
+ int src_segment_from, int src_segment_count,
+ boolean b_start_new_path) {
+ if (!b_start_new_path && getPathCount() == 0)
+ b_start_new_path = true;
+
+ if (src_path_index < 0)
+ src_path_index = src.getPathCount() - 1;
+
+ if (src_path_index >= src.getPathCount() || src_segment_from < 0
+ || src_segment_count < 0
+ || src_segment_count > src.getSegmentCount(src_path_index))
+ throw new GeometryException("index out of bounds");
+
+ if (src_segment_count == 0)
+ return;
+
+ boolean bIncludesClosingSegment = src.isClosedPath(src_path_index)
+ && src_segment_from + src_segment_count == src
+ .getSegmentCount(src_path_index);
+
+ if (bIncludesClosingSegment && src_segment_count == 1)
+ return;// cannot add a closing segment alone.
+
+ m_bPathStarted = false;
+
+ mergeVertexDescription(src.getDescription());
+ int src_point_count = src_segment_count;
+ int srcFromPoint = src.getPathStart(src_path_index) + src_segment_from
+ + 1;
+ if (b_start_new_path)// adding a new path.
+ {
+ src_point_count++;// add start point.
+ srcFromPoint--;
+ }
+
+ if (bIncludesClosingSegment) {
+ src_point_count--;
+ }
+
+ int oldPointCount = m_pointCount;
+ _resizeImpl(m_pointCount + src_point_count);
+ _verifyAllStreams();
+
+ if (b_start_new_path) {
+ if (src_point_count == 0)
+ return;// happens when adding a single closing segment to the
+ // new path
+
+ m_paths.add(m_pointCount);
+
+ byte flags = src.m_pathFlags.read(src_path_index);
+ flags &= ~(byte) PathFlags.enumCalcMask;// remove calculated flags
+
+ if (m_bPolygon)
+ flags |= (byte) PathFlags.enumClosed;
+
+ m_pathFlags.write(m_pathFlags.size() - 1, flags);
+ m_pathFlags.add((byte) 0);
+ } else {
+ m_paths.write(m_pathFlags.size() - 1, m_pointCount);
+ }
+
+ // Index_type absoluteIndex = pathStart + before_point_index;
+
+ for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
+ int semantics = m_description.getSemantics(iattr);
+ int comp = VertexDescription.getComponentCount(semantics);
+
+ int isrcAttr = src.m_description.getAttributeIndex(semantics);
+ if (isrcAttr < 0 || src.m_vertexAttributes[isrcAttr] == null) {// The
+ // source
+ // does
+ // not
+ // have
+ // the
+ // attribute.
+ // insert
+ // default
+ // value
+ double v = VertexDescription.getDefaultValue(semantics);
+ m_vertexAttributes[iattr].insertRange(comp * oldPointCount, v,
+ src_point_count * comp, comp * oldPointCount);
+ continue;
+ }
+
+ // add vertices to the given stream
+ boolean b_forward = true;
+ m_vertexAttributes[iattr].insertRange(comp * oldPointCount,
+ src.m_vertexAttributes[isrcAttr], comp * srcFromPoint,
+ src_point_count * comp, b_forward, comp, comp
+ * oldPointCount);
+ }
+
+ if (hasNonLinearSegments()) {
+ // TODO: implement me. For example as a while loop over all curves.
+ // Replace, calling ReplaceSegment
+ throw GeometryException.GeometryInternalError();
+ // m_segment_flags->write_range((get_path_start(path_index) +
+ // before_point_index + src_point_count), (oldPointCount -
+ // get_path_start(path_index) - before_point_index),
+ // m_segment_flags, (get_path_start(path_index) +
+ // before_point_index), true, 1);
+ // m_segment_param_index->write_range((get_path_start(path_index) +
+ // before_point_index + src_point_count), (oldPointCount -
+ // get_path_start(path_index) - before_point_index),
+ // m_segment_param_index, (get_path_start(path_index) +
+ // before_point_index), true, 1);
+ // for (Index_type i = get_path_start(path_index) +
+ // before_point_index, n = get_path_start(path_index) +
+ // before_point_index + src_point_count; i < n; i++)
+ // {
+ // m_segment_flags->write(i, (int8_t)enum_value1(Segment_flags,
+ // enum_line_seg));
+ // m_segment_param_index->write(i, -1);
+ // }
+ }
+
+ if (src.hasNonLinearSegments(src_path_index)) {
+ // TODO: implement me. For example as a while loop over all curves.
+ // Replace, calling ReplaceSegment
+ throw GeometryException.GeometryInternalError();
+ }
+
+ notifyModified(DirtyFlags.DirtyCoordinates);
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ public void reverseAllPaths() {
+ for (int i = 0, n = getPathCount(); i < n; i++) {
+ reversePath(i);
+ }
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ public void reversePath(int pathIndex) {
+ _verifyAllStreams();
+ int pathCount = getPathCount();
+ if (pathIndex >= pathCount)
+ throw new IllegalArgumentException();
+
+ int reversedPathStart = getPathStart(pathIndex);
+ int reversedPathSize = getPathSize(pathIndex);
+ int offset = isClosedPath(pathIndex) ? 1 : 0;
+
+ // TODO: a bug for the non linear segments here.
+ // There could be an issue here if someone explicity closes the path
+ // with the same start/end point.
+ for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
+ if (m_vertexAttributes[iattr] != null) {
+ int semantics = m_description._getSemanticsImpl(iattr);
+ int comp = VertexDescription.getComponentCount(semantics);
+ m_vertexAttributes[iattr].reverseRange(comp
+ * (reversedPathStart + offset), comp
+ * (reversedPathSize - offset), comp);
+ }
+ }
+
+ notifyModified(DirtyFlags.DirtyCoordinates);
+ }
+
+ // Reviewed vs. Native Jan 11, 2011
+ // TODO: Nonlinearsegments
+ public void removePath(int pathIndex) {
+ _verifyAllStreams();
+ int pathCount = getPathCount();
+
+ if (pathIndex < 0)
+ pathIndex = pathCount - 1;
+
+ if (pathIndex >= pathCount)
+ throw new IllegalArgumentException();
+
+ boolean bDirtyRingAreas2D = _hasDirtyFlag(DirtyFlags.DirtyRingAreas2D);
+
+ int removedPathStart = getPathStart(pathIndex);
+ int removedPathSize = getPathSize(pathIndex);
+
+ // Remove the attribute values for the path
+ for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
+ if (m_vertexAttributes[iattr] != null) {
+ int semantics = m_description._getSemanticsImpl(iattr);
+ int comp = VertexDescription.getComponentCount(semantics);
+ m_vertexAttributes[iattr].eraseRange(comp * removedPathStart,
+ comp * removedPathSize, comp * m_pointCount);
+ }
+ }
+
+ // Change the start of each path after the removed path
+ for (int i = pathIndex + 1; i <= pathCount; i++) {
+ int istart = m_paths.read(i);
+ m_paths.write(i - 1, istart - removedPathSize);
+ }
+
+ if (m_pathFlags == null) {
+ for (int i = pathIndex + 1; i <= pathCount; i++) {
+ byte flags = m_pathFlags.read(i);
+ m_pathFlags.write(i - 1, flags);
+ }
+ }
+
+ m_paths.resize(pathCount);
+ m_pathFlags.resize(pathCount);
+ m_pointCount -= removedPathSize;
+ m_reservedPointCount -= removedPathSize;
+
+ notifyModified(DirtyFlags.DirtyCoordinates);
+ }
+
+ // TODO: Nonlinearsegments
+ public void insertPath(int pathIndex, MultiPathImpl src, int srcPathIndex,
+ boolean bForward) {
+ if (src == this)
+ throw new IllegalArgumentException();
+
+ if (srcPathIndex >= src.getPathCount())
+ throw new IllegalArgumentException();
+
+ int oldPathCount = getPathCount();
+ if (pathIndex > oldPathCount)
+ throw new IllegalArgumentException();
+
+ if (pathIndex < 0)
+ pathIndex = oldPathCount;
+
+ if (srcPathIndex < 0)
+ srcPathIndex = src.getPathCount() - 1;
+
+ m_bPathStarted = false;
+
+ mergeVertexDescription(src.m_description);// merge attributes from the
+ // source
+
+ src._verifyAllStreams();// the source need to be correct.
+
+ int srcPathIndexStart = src.getPathStart(srcPathIndex);
+ int srcPathSize = src.getPathSize(srcPathIndex);
+ int oldPointCount = m_pointCount;
+ int offset = src.isClosedPath(srcPathIndex) && !bForward ? 1 : 0;
+
+ _resizeImpl(m_pointCount + srcPathSize);
+ _verifyAllStreams();
+ int pathIndexStart = pathIndex < oldPathCount ? getPathStart(pathIndex)
+ : oldPointCount;
+
+ // Copy all attribute values.
+ for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
+ int semantics = m_description._getSemanticsImpl(iattr);
+ int isrcAttr = src.m_description.getAttributeIndex(semantics);
+
+ int comp = VertexDescription.getComponentCount(semantics);
+
+ if (isrcAttr >= 0 && src.m_vertexAttributes[isrcAttr] != null) {
+ if (offset != 0)
+ m_vertexAttributes[iattr].insertRange(
+ pathIndexStart * comp,
+ src.m_vertexAttributes[isrcAttr], comp
+ * srcPathIndexStart, comp, true, comp, comp
+ * oldPointCount);
+ m_vertexAttributes[iattr].insertRange((pathIndexStart + offset)
+ * comp, src.m_vertexAttributes[isrcAttr], comp
+ * (srcPathIndexStart + offset), comp
+ * (srcPathSize - offset), bForward, comp, comp
+ * (oldPointCount + offset));
+ } else {
+ // Need to make room for the attributes, so we copy default
+ // values in
+
+ double v = VertexDescription.getDefaultValue(semantics);
+ m_vertexAttributes[iattr].insertRange(pathIndexStart * comp, v,
+ comp * srcPathSize, comp * oldPointCount);
+ }
+ }
+
+ int newPointCount = oldPointCount + srcPathSize;
+ m_paths.add(newPointCount);
+
+ for (int ipath = oldPathCount; ipath >= pathIndex + 1; ipath--) {
+ int iend = m_paths.read(ipath - 1);
+ m_paths.write(ipath, iend + srcPathSize);
+ }
+
+ // ========================== todo: NonLinearSegments =================
+ if (src.hasNonLinearSegments(srcPathIndex)) {
+
+ }
+
+ m_pathFlags.add((byte) 0);
+
+ // _ASSERT(m_pathFlags.size() == m_paths.size());
+
+ for (int ipath = oldPathCount - 1; ipath >= pathIndex + 1; ipath--) {
+ byte flags = m_pathFlags.read(ipath);
+ flags &= ~(byte) PathFlags.enumCalcMask;// remove calculated flags
+ m_pathFlags.write(ipath + 1, flags);
+ }
+
+ AttributeStreamOfInt8 srcPathFlags = src.getPathFlagsStreamRef();
+ byte flags = srcPathFlags.read(srcPathIndex);
+ flags &= ~(byte) PathFlags.enumCalcMask;// remove calculated flags
+
+ if (m_bPolygon)
+ flags |= (byte) PathFlags.enumClosed;
+
+ m_pathFlags.write(pathIndex, flags);
+ }
+
+ public void insertPath(int pathIndex, Point2D[] points, int pointsOffset,
+ int count, boolean bForward) {
+ int oldPathCount = getPathCount();
+ if (pathIndex > oldPathCount)
+ throw new IllegalArgumentException();
+
+ if (pathIndex < 0)
+ pathIndex = oldPathCount;
+
+ m_bPathStarted = false;
+
+ int oldPointCount = m_pointCount;
+
+ // Copy all attribute values.
+ if (points != null) {
+ _resizeImpl(m_pointCount + count);
+ _verifyAllStreams();
+
+ int pathStart = pathIndex < oldPathCount ? getPathStart(pathIndex)
+ : oldPointCount;
+
+ for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
+ int semantics = m_description._getSemanticsImpl(iattr);
+
+ if (semantics == VertexDescription.Semantics.POSITION) {
+ // copy range to make place for new vertices
+ m_vertexAttributes[iattr].writeRange(
+ 2 * (pathStart + count),
+ 2 * (oldPointCount - pathIndex),
+ m_vertexAttributes[iattr], 2 * pathStart, true, 2);
+
+ AttributeStreamOfDbl position = (AttributeStreamOfDbl) (AttributeStreamBase) getAttributeStreamRef(semantics);
+
+ int j = pathStart;
+ for (int i = 0; i < count; i++, j++) {
+ int index = (bForward ? pointsOffset + i : pointsOffset
+ + count - i - 1);
+ position.write(2 * j, points[index].x);
+ position.write(2 * j + 1, points[index].y);
+ }
+ } else {
+ // Need to make room for the attributes, so we copy default
+ // values in
+
+ int comp = VertexDescription.getComponentCount(semantics);
+ double v = VertexDescription.getDefaultValue(semantics);
+ m_vertexAttributes[iattr].insertRange(pathStart * comp, v,
+ comp * count, comp * oldPointCount);
+ }
+ }
+ } else {
+ _verifyAllStreams();
+ }
+
+ m_paths.add(m_pointCount);
+
+ for (int ipath = oldPathCount; ipath >= pathIndex + 1; ipath--) {
+ int iend = m_paths.read(ipath - 1);
+ m_paths.write(ipath, iend + count);
+ }
+
+ m_pathFlags.add((byte) 0);
+
+ // _ASSERT(m_pathFlags.size() == m_paths.size());
+
+ for (int ipath = oldPathCount - 1; ipath >= pathIndex + 1; ipath--) {
+ byte flags = m_pathFlags.read(ipath);
+ flags &= ~(byte) PathFlags.enumCalcMask;// remove calculated flags
+ m_pathFlags.write(ipath + 1, flags);
+ }
+
+ if (m_bPolygon)
+ m_pathFlags.write(pathIndex, (byte) PathFlags.enumClosed);
+ }
+
+ public void insertPoints(int pathIndex, int beforePointIndex,
+ MultiPathImpl src, int srcPathIndex, int srcPointIndexFrom,
+ int srcPointCount, boolean bForward) {
+ if (pathIndex < 0)
+ pathIndex = getPathCount();
+
+ if (srcPathIndex < 0)
+ srcPathIndex = src.getPathCount() - 1;
+
+ if (pathIndex > getPathCount() || beforePointIndex >= 0
+ && beforePointIndex > getPathSize(pathIndex)
+ || srcPathIndex >= src.getPathCount()
+ || srcPointCount > src.getPathSize(srcPathIndex))
+ throw new GeometryException("index out of bounds");
+
+ if (srcPointCount == 0)
+ return;
+
+ mergeVertexDescription(src.m_description);
+
+ if (pathIndex == getPathCount())// adding a new path.
+ {
+ m_paths.add(m_pointCount);
+
+ byte flags = src.m_pathFlags.read(srcPathIndex);
+ flags &= ~(byte) PathFlags.enumCalcMask;// remove calculated flags
+
+ if (!m_bPolygon)
+ m_pathFlags.add(flags);
+ else
+ m_pathFlags.add((byte) (flags | PathFlags.enumClosed));
+ }
+
+ if (beforePointIndex < 0)
+ beforePointIndex = getPathSize(pathIndex);
+
+ int oldPointCount = m_pointCount;
+ _resizeImpl(m_pointCount + srcPointCount);
+ _verifyAllStreams();
+ src._verifyAllStreams();
+
+ int pathStart = getPathStart(pathIndex);
+ int absoluteIndex = pathStart + beforePointIndex;
+
+ if (srcPointCount < 0)
+ srcPointCount = src.getPathSize(srcPathIndex);
+
+ int srcPathStart = src.getPathStart(srcPathIndex);
+ int srcAbsoluteIndex = srcPathStart + srcPointCount;
+
+ for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
+ int semantics = m_description._getSemanticsImpl(iattr);
+ int comp = VertexDescription.getComponentCount(semantics);
+
+ int isrcAttr = src.m_description.getAttributeIndex(semantics);
+ if (isrcAttr < 0 || src.m_vertexAttributes[isrcAttr] == null) // The
+ // source
+ // does
+ // not
+ // have
+ // the
+ // attribute.
+ {
+ double v = VertexDescription.getDefaultValue(semantics);
+ m_vertexAttributes[iattr].insertRange(comp * absoluteIndex, v,
+ srcAbsoluteIndex * comp, comp * oldPointCount);
+ continue;
+ }
+
+ // add vertices to the given stream
+ m_vertexAttributes[iattr].insertRange(comp
+ * (pathStart + beforePointIndex),
+ src.m_vertexAttributes[isrcAttr], comp
+ * (srcPathStart + srcPointIndexFrom), srcPointCount
+ * comp, bForward, comp, comp * oldPointCount);
+ }
+
+ if (hasNonLinearSegments()) {// TODO: probably a bug here when a new
+ // path is added.
+ m_segmentFlags.writeRange((getPathStart(pathIndex)
+ + beforePointIndex + srcPointCount), (oldPointCount
+ - getPathStart(pathIndex) - beforePointIndex),
+ m_segmentFlags,
+ (getPathStart(pathIndex) + beforePointIndex), true, 1);
+ m_segmentParamIndex.writeRange((getPathStart(pathIndex)
+ + beforePointIndex + srcPointCount), (oldPointCount
+ - getPathStart(pathIndex) - beforePointIndex),
+ m_segmentParamIndex,
+ (getPathStart(pathIndex) + beforePointIndex), true, 1);
+ for (int i = getPathStart(pathIndex) + beforePointIndex, n = getPathStart(pathIndex)
+ + beforePointIndex + srcPointCount; i < n; i++) {
+ m_segmentFlags.write(i, (byte) SegmentFlags.enumLineSeg);
+ m_segmentParamIndex.write(i, -1);
+ }
+ }
+
+ if (src.hasNonLinearSegments(srcPathIndex)) {
+ // TODO: implement me. For example as a while loop over all curves.
+ // Replace, calling ReplaceSegment
+ throw GeometryException.GeometryInternalError();
+ }
+
+ for (int ipath = pathIndex + 1, npaths = getPathCount(); ipath <= npaths; ipath++) {
+ int num = m_paths.read(ipath);
+ m_paths.write(ipath, num + srcPointCount);
+ }
+ }
+
+ public void insertPoints(int pathIndex, int beforePointIndex,
+ Point2D[] src, int srcPointIndexFrom, int srcPointCount,
+ boolean bForward) {
+ if (pathIndex < 0)
+ pathIndex = getPathCount();
+
+ if (pathIndex > getPathCount()
+ || beforePointIndex > getPathSize(pathIndex)
+ || srcPointIndexFrom < 0 || srcPointCount > src.length)
+ throw new GeometryException("index out of bounds");
+
+ if (srcPointCount == 0)
+ return;
+
+ if (pathIndex == getPathCount())// adding a new path.
+ {
+ m_paths.add(m_pointCount);
+
+ if (!m_bPolygon)
+ m_pathFlags.add((byte) 0);
+ else
+ m_pathFlags.add((byte) PathFlags.enumClosed);
+ }
- for (int ipath = pathIndex + 1, npaths = pathCount; ipath <= npaths; ipath++) {
- m_paths.write(ipath, m_paths.read(ipath) + 1);
- }
+ if (beforePointIndex < 0)
+ beforePointIndex = getPathSize(pathIndex);
+
+ _verifyAllStreams();
+ int oldPointCount = m_pointCount;
+ _resizeImpl(m_pointCount + srcPointCount);
+ _verifyAllStreams();
+ for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
+ int semantics = m_description._getSemanticsImpl(iattr);
+ int comp = VertexDescription.getComponentCount(semantics);
+ // copy range to make place for new vertices
+ m_vertexAttributes[iattr]
+ .writeRange(
+ comp
+ * (getPathStart(pathIndex)
+ + beforePointIndex + srcPointCount),
+ (oldPointCount - getPathStart(pathIndex) - beforePointIndex)
+ * comp,
+ m_vertexAttributes[iattr],
+ comp * (getPathStart(pathIndex) + beforePointIndex),
+ true, comp);
+
+ if (iattr == 0) {
+ // add vertices to the given stream
+ ((AttributeStreamOfDbl) (AttributeStreamBase) m_vertexAttributes[iattr])
+ .writeRange(comp
+ * (getPathStart(pathIndex) + beforePointIndex),
+ srcPointCount, src, srcPointIndexFrom, bForward);
+ } else {
+ double v = VertexDescription.getDefaultValue(semantics);
+ m_vertexAttributes[iattr].setRange(v,
+ (getPathStart(pathIndex) + beforePointIndex) * comp,
+ srcPointCount * comp);
+ }
+ }
- notifyModified(DirtyFlags.DirtyCoordinates);
- }
+ if (hasNonLinearSegments()) {
+ m_segmentFlags.writeRange((getPathStart(pathIndex)
+ + beforePointIndex + srcPointCount), (oldPointCount
+ - getPathStart(pathIndex) - beforePointIndex),
+ m_segmentFlags,
+ (getPathStart(pathIndex) + beforePointIndex), true, 1);
+ m_segmentParamIndex.writeRange((getPathStart(pathIndex)
+ + beforePointIndex + srcPointCount), (oldPointCount
+ - getPathStart(pathIndex) - beforePointIndex),
+ m_segmentParamIndex,
+ (getPathStart(pathIndex) + beforePointIndex), true, 1);
+ m_segmentFlags.setRange((byte) SegmentFlags.enumLineSeg,
+ getPathStart(pathIndex) + beforePointIndex, srcPointCount);
+ m_segmentParamIndex.setRange(-1, getPathStart(pathIndex)
+ + beforePointIndex, srcPointCount);
+ }
- public void removePoint(int pathIndex, int pointIndex) {
- int pathCount = getPathCount();
+ for (int ipath = pathIndex + 1, npaths = getPathCount(); ipath <= npaths; ipath++) {
+ m_paths.write(ipath, m_paths.read(ipath) + srcPointCount);
+ }
+ }
- if (pathIndex < 0)
- pathIndex = pathCount - 1;
+ public void insertPoint(int pathIndex, int beforePointIndex, Point2D pt) {
+ int pathCount = getPathCount();
- if (pathIndex >= pathCount || pointIndex >= getPathSize(pathIndex))
- throw new GeometryException("index out of bounds");
+ if (pathIndex < 0)
+ pathIndex = getPathCount();
- _verifyAllStreams();
+ if (pathIndex >= pathCount || beforePointIndex > getPathSize(pathIndex))
+ throw new GeometryException("index out of bounds");
- int pathStart = getPathStart(pathIndex);
+ if (pathIndex == getPathCount())// adding a new path.
+ {
+ m_paths.add(m_pointCount);
- if (pointIndex < 0)
- pointIndex = getPathSize(pathIndex) - 1;
+ if (!m_bPolygon)
+ m_pathFlags.add((byte) 0);
+ else
+ m_pathFlags.add((byte) PathFlags.enumClosed);
+ }
- int absoluteIndex = pathStart + pointIndex;
+ if (beforePointIndex < 0)
+ beforePointIndex = getPathSize(pathIndex);
- // Remove the attribute values for the path
- for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
- if (m_vertexAttributes[iattr] != null) {
- int semantics = m_description._getSemanticsImpl(iattr);
- int comp = VertexDescription.getComponentCount(semantics);
- m_vertexAttributes[iattr].eraseRange(comp * absoluteIndex,
- comp, comp * m_pointCount);
- }
- }
+ int oldPointCount = m_pointCount;
+ _resizeImpl(m_pointCount + 1);
+ _verifyAllStreams();
- for (int ipath = pathCount; ipath >= pathIndex + 1; ipath--) {
- int iend = m_paths.read(ipath);
- m_paths.write(ipath, iend - 1);
- }
+ int pathStart = getPathStart(pathIndex);
- m_pointCount--;
- m_reservedPointCount--;
- notifyModified(DirtyFlags.DirtyCoordinates);
- }
+ ((AttributeStreamOfDbl) (AttributeStreamBase) m_vertexAttributes[0])
+ .insert(2 * (pathStart + beforePointIndex), pt,
+ 2 * oldPointCount);
- public double calculatePathLength2D(int pathIndex) /* const */ {
- SegmentIteratorImpl segIter = querySegmentIteratorAtVertex(getPathStart(pathIndex));
+ for (int iattr = 1, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
+ int semantics = m_description._getSemanticsImpl(iattr);
+ int comp = VertexDescription.getComponentCount(semantics);
- MathUtils.KahanSummator len = new MathUtils.KahanSummator(0);
- while (segIter.hasNextSegment()) {
- len.add(segIter.nextSegment().calculateLength2D());
- }
+ // Need to make room for the attribute, so we copy a default value
+ // in
+ double v = VertexDescription.getDefaultValue(semantics);
+ m_vertexAttributes[iattr].insertRange(comp
+ * (pathStart + beforePointIndex), v, comp, comp
+ * oldPointCount);
+ }
- return len.getResult();
- }
+ for (int ipath = pathIndex + 1, npaths = pathCount; ipath <= npaths; ipath++) {
+ m_paths.write(ipath, m_paths.read(ipath) + 1);
+ }
+ }
- double calculateSubLength2D(int from_path_index, int from_point_index,
- int to_path_index, int to_point_index) {
- int absolute_from_index = getPathStart(from_path_index)
- + from_point_index;
- int absolute_to_index = getPathStart(to_path_index) + to_point_index;
+ public void insertPoint(int pathIndex, int beforePointIndex, Point pt) {
+ int pathCount = getPathCount();
- if (absolute_to_index < absolute_from_index || absolute_from_index < 0
- || absolute_to_index > getPointCount() - 1)
- throw new IllegalArgumentException();
+ if (pathIndex < 0)
+ pathIndex = getPathCount();
- SegmentIteratorImpl seg_iter = querySegmentIterator();
+ if (pathIndex >= pathCount || beforePointIndex > getPathSize(pathIndex))
+ throw new GeometryException("index out of bounds");
- double sub_length = 0.0;
+ if (pathIndex == getPathCount())// adding a new path.
+ {
+ m_paths.add(m_pointCount);
- seg_iter.resetToVertex(absolute_from_index);
+ if (!m_bPolygon)
+ m_pathFlags.add((byte) 0);
+ else
+ m_pathFlags.add((byte) PathFlags.enumClosed);
+ }
- do {
- while (seg_iter.hasNextSegment()) {
- Segment segment = seg_iter.nextSegment();
+ if (beforePointIndex < 0)
+ beforePointIndex = getPathSize(pathIndex);
+
+ mergeVertexDescription(pt.getDescription());
+ int oldPointCount = m_pointCount;
+ _resizeImpl(m_pointCount + 1);
+ _verifyAllStreams();
+
+ int pathStart = getPathStart(pathIndex);
+
+ for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
+ int semantics = m_description._getSemanticsImpl(iattr);
+ int comp = VertexDescription.getComponentCount(semantics);
+
+ if (pt.hasAttribute(semantics)) {
+ m_vertexAttributes[iattr].insertAttributes(comp
+ * (pathStart + beforePointIndex), pt, semantics, comp
+ * oldPointCount);
+ } else {
+ // Need to make room for the attribute, so we copy a default
+ // value in
+ double v = VertexDescription.getDefaultValue(semantics);
+ m_vertexAttributes[iattr].insertRange(comp
+ * (pathStart + beforePointIndex), v, comp, comp
+ * oldPointCount);
+ }
+ }
- if (seg_iter.getStartPointIndex() == absolute_to_index)
- break;
+ for (int ipath = pathIndex + 1, npaths = pathCount; ipath <= npaths; ipath++) {
+ m_paths.write(ipath, m_paths.read(ipath) + 1);
+ }
- double segment_length = segment.calculateLength2D();
- sub_length += segment_length;
- }
+ notifyModified(DirtyFlags.DirtyCoordinates);
+ }
- if (seg_iter.getStartPointIndex() == absolute_to_index)
- break;
+ public void removePoint(int pathIndex, int pointIndex) {
+ int pathCount = getPathCount();
- } while (seg_iter.nextPath());
+ if (pathIndex < 0)
+ pathIndex = pathCount - 1;
- return sub_length;
- }
+ if (pathIndex >= pathCount || pointIndex >= getPathSize(pathIndex))
+ throw new GeometryException("index out of bounds");
- double calculateSubLength2D(int path_index, int from_point_index,
- int to_point_index) {
- int absolute_from_index = getPathStart(path_index) + from_point_index;
- int absolute_to_index = getPathStart(path_index) + to_point_index;
+ _verifyAllStreams();
- if (absolute_from_index < 0 || absolute_to_index > getPointCount() - 1)
- throw new IllegalArgumentException();
+ int pathStart = getPathStart(pathIndex);
- SegmentIteratorImpl seg_iter = querySegmentIterator();
+ if (pointIndex < 0)
+ pointIndex = getPathSize(pathIndex) - 1;
- if (absolute_from_index > absolute_to_index) {
- if (!isClosedPath(path_index))
- throw new IllegalArgumentException(
- "cannot iterate across an open path");
+ int absoluteIndex = pathStart + pointIndex;
- seg_iter.setCirculator(true);
- }
+ // Remove the attribute values for the path
+ for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
+ if (m_vertexAttributes[iattr] != null) {
+ int semantics = m_description._getSemanticsImpl(iattr);
+ int comp = VertexDescription.getComponentCount(semantics);
+ m_vertexAttributes[iattr].eraseRange(comp * absoluteIndex,
+ comp, comp * m_pointCount);
+ }
+ }
- double prev_length = 0.0;
- double sub_length = 0.0;
+ for (int ipath = pathCount; ipath >= pathIndex + 1; ipath--) {
+ int iend = m_paths.read(ipath);
+ m_paths.write(ipath, iend - 1);
+ }
- seg_iter.resetToVertex(absolute_from_index);
+ m_pointCount--;
+ m_reservedPointCount--;
+ notifyModified(DirtyFlags.DirtyCoordinates);
+ }
- do {
- assert (seg_iter.hasNextSegment());
- sub_length += prev_length;
- Segment segment = seg_iter.nextSegment();
- prev_length = segment.calculateLength2D();
+ public double calculatePathLength2D(int pathIndex) /* const */
+ {
+ SegmentIteratorImpl segIter = querySegmentIteratorAtVertex(getPathStart(pathIndex));
- } while (seg_iter.getStartPointIndex() != absolute_to_index);
+ MathUtils.KahanSummator len = new MathUtils.KahanSummator(0);
+ while (segIter.hasNextSegment()) {
+ len.add(segIter.nextSegment().calculateLength2D());
+ }
- return sub_length;
- }
+ return len.getResult();
+ }
- @Override
- public Geometry getBoundary() {
- return Boundary.calculate(this, null);
- }
+ double calculateSubLength2D(int from_path_index, int from_point_index,
+ int to_path_index, int to_point_index) {
+ int absolute_from_index = getPathStart(from_path_index)
+ + from_point_index;
+ int absolute_to_index = getPathStart(to_path_index) + to_point_index;
- // TODO: Add code fore interpolation type (none and angular)
- void interpolateAttributes(int from_path_index, int from_point_index,
- int to_path_index, int to_point_index) {
- for (int ipath = from_path_index; ipath < to_path_index - 1; ipath++) {
- if (isClosedPath(ipath))
- throw new IllegalArgumentException(
- "cannot interpolate across closed paths");
- }
+ if (absolute_to_index < absolute_from_index || absolute_from_index < 0
+ || absolute_to_index > getPointCount() - 1)
+ throw new IllegalArgumentException();
- int nattr = m_description.getAttributeCount();
+ SegmentIteratorImpl seg_iter = querySegmentIterator();
- if (nattr == 1)
- return; // only has position
+ double sub_length = 0.0;
- double sub_length = calculateSubLength2D(from_path_index,
- from_point_index, to_path_index, to_point_index);
+ seg_iter.resetToVertex(absolute_from_index);
- if (sub_length == 0.0)
- return;
+ do {
+ while (seg_iter.hasNextSegment()) {
+ Segment segment = seg_iter.nextSegment();
- for (int iattr = 1; iattr < nattr; iattr++) {
- int semantics = m_description.getSemantics(iattr);
+ if (seg_iter.getStartPointIndex() == absolute_to_index)
+ break;
- int interpolation = VertexDescription.getInterpolation(semantics);
- if (interpolation == VertexDescription.Interpolation.ANGULAR)
- continue;
+ double segment_length = segment.calculateLength2D();
+ sub_length += segment_length;
+ }
- int components = VertexDescription.getComponentCount(semantics);
+ if (seg_iter.getStartPointIndex() == absolute_to_index)
+ break;
- for (int ordinate = 0; ordinate < components; ordinate++)
- interpolateAttributes_(semantics, from_path_index,
- from_point_index, to_path_index, to_point_index,
- sub_length, ordinate);
- }
- }
+ } while (seg_iter.nextPath());
- // TODO: Add code for interpolation type (none and angular)
- void interpolateAttributesForSemantics(int semantics, int from_path_index,
- int from_point_index, int to_path_index, int to_point_index) {
- if (semantics == VertexDescription.Semantics.POSITION)
- return;
+ return sub_length;
+ }
- if (!hasAttribute(semantics))
- throw new IllegalArgumentException(
- "does not have the given attribute");
+ double calculateSubLength2D(int path_index, int from_point_index,
+ int to_point_index) {
+ int absolute_from_index = getPathStart(path_index) + from_point_index;
+ int absolute_to_index = getPathStart(path_index) + to_point_index;
- int interpolation = VertexDescription.getInterpolation(semantics);
- if (interpolation == VertexDescription.Interpolation.ANGULAR)
- throw new IllegalArgumentException(
- "not implemented for the given semantics");
+ if (absolute_from_index < 0 || absolute_to_index > getPointCount() - 1)
+ throw new IllegalArgumentException();
- for (int ipath = from_path_index; ipath < to_path_index - 1; ipath++) {
- if (isClosedPath(ipath))
- throw new IllegalArgumentException(
- "cannot interpolate across closed paths");
- }
+ SegmentIteratorImpl seg_iter = querySegmentIterator();
- double sub_length = calculateSubLength2D(from_path_index,
- from_point_index, to_path_index, to_point_index);
+ if (absolute_from_index > absolute_to_index) {
+ if (!isClosedPath(path_index))
+ throw new IllegalArgumentException(
+ "cannot iterate across an open path");
- if (sub_length == 0.0)
- return;
+ seg_iter.setCirculator(true);
+ }
- int components = VertexDescription.getComponentCount(semantics);
+ double prev_length = 0.0;
+ double sub_length = 0.0;
- for (int ordinate = 0; ordinate < components; ordinate++)
- interpolateAttributes_(semantics, from_path_index,
- from_point_index, to_path_index, to_point_index,
- sub_length, ordinate);
- }
+ seg_iter.resetToVertex(absolute_from_index);
- void interpolateAttributes(int path_index, int from_point_index,
- int to_point_index) {
- int nattr = m_description.getAttributeCount();
+ do {
+ assert (seg_iter.hasNextSegment());
+ sub_length += prev_length;
+ Segment segment = seg_iter.nextSegment();
+ prev_length = segment.calculateLength2D();
- if (nattr == 1)
- return; // only has position
+ } while (seg_iter.getStartPointIndex() != absolute_to_index);
- double sub_length = calculateSubLength2D(path_index, from_point_index,
- to_point_index);
+ return sub_length;
+ }
- if (sub_length == 0.0)
- return;
+ @Override
+ public Geometry getBoundary() {
+ return Boundary.calculate(this, null);
+ }
- for (int iattr = 1; iattr < nattr; iattr++) {
- int semantics = m_description.getSemantics(iattr);
+ // TODO: Add code fore interpolation type (none and angular)
+ void interpolateAttributes(int from_path_index, int from_point_index,
+ int to_path_index, int to_point_index) {
+ for (int ipath = from_path_index; ipath < to_path_index - 1; ipath++) {
+ if (isClosedPath(ipath))
+ throw new IllegalArgumentException(
+ "cannot interpolate across closed paths");
+ }
- int interpolation = VertexDescription.getInterpolation(semantics);
- if (interpolation == VertexDescription.Interpolation.ANGULAR)
- continue;
+ int nattr = m_description.getAttributeCount();
- int components = VertexDescription.getComponentCount(semantics);
+ if (nattr == 1)
+ return; // only has position
- for (int ordinate = 0; ordinate < components; ordinate++)
- interpolateAttributes_(semantics, path_index, from_point_index,
- to_point_index, sub_length, ordinate);
- }
- }
+ double sub_length = calculateSubLength2D(from_path_index,
+ from_point_index, to_path_index, to_point_index);
- void interpolateAttributesForSemantics(int semantics, int path_index,
- int from_point_index, int to_point_index) {
- if (semantics == VertexDescription.Semantics.POSITION)
- return;
+ if (sub_length == 0.0)
+ return;
- if (!hasAttribute(semantics))
- throw new IllegalArgumentException(
- "does not have the given attribute");
+ for (int iattr = 1; iattr < nattr; iattr++) {
+ int semantics = m_description.getSemantics(iattr);
- int interpolation = VertexDescription.getInterpolation(semantics);
- if (interpolation == VertexDescription.Interpolation.ANGULAR)
- throw new IllegalArgumentException(
- "not implemented for the given semantics");
+ int interpolation = VertexDescription.getInterpolation(semantics);
+ if (interpolation == VertexDescription.Interpolation.ANGULAR)
+ continue;
- double sub_length = calculateSubLength2D(path_index, from_point_index,
- to_point_index);
+ int components = VertexDescription.getComponentCount(semantics);
- if (sub_length == 0.0)
- return;
+ for (int ordinate = 0; ordinate < components; ordinate++)
+ interpolateAttributes_(semantics, from_path_index,
+ from_point_index, to_path_index, to_point_index,
+ sub_length, ordinate);
+ }
+ }
- int components = VertexDescription.getComponentCount(semantics);
+ // TODO: Add code for interpolation type (none and angular)
+ void interpolateAttributesForSemantics(int semantics, int from_path_index,
+ int from_point_index, int to_path_index, int to_point_index) {
+ if (semantics == VertexDescription.Semantics.POSITION)
+ return;
+
+ if (!hasAttribute(semantics))
+ throw new IllegalArgumentException(
+ "does not have the given attribute");
+
+ int interpolation = VertexDescription.getInterpolation(semantics);
+ if (interpolation == VertexDescription.Interpolation.ANGULAR)
+ throw new IllegalArgumentException(
+ "not implemented for the given semantics");
+
+ for (int ipath = from_path_index; ipath < to_path_index - 1; ipath++) {
+ if (isClosedPath(ipath))
+ throw new IllegalArgumentException(
+ "cannot interpolate across closed paths");
+ }
- for (int ordinate = 0; ordinate < components; ordinate++)
- interpolateAttributes_(semantics, path_index, from_point_index,
- to_point_index, sub_length, ordinate);
- }
+ double sub_length = calculateSubLength2D(from_path_index,
+ from_point_index, to_path_index, to_point_index);
- // TODO: Add code fore interpolation type (none and angular)
- void interpolateAttributes_(int semantics, int from_path_index,
- int from_point_index, int to_path_index, int to_point_index,
- double sub_length, int ordinate) {
- SegmentIteratorImpl seg_iter = querySegmentIterator();
-
- int absolute_from_index = getPathStart(from_path_index)
- + from_point_index;
- int absolute_to_index = getPathStart(to_path_index) + to_point_index;
+ if (sub_length == 0.0)
+ return;
- double from_attribute = getAttributeAsDbl(semantics,
- absolute_from_index, ordinate);
- double to_attribute = getAttributeAsDbl(semantics, absolute_to_index,
- ordinate);
- double interpolated_attribute = from_attribute;
- double cumulative_length = 0.0;
+ int components = VertexDescription.getComponentCount(semantics);
- seg_iter.resetToVertex(absolute_from_index);
+ for (int ordinate = 0; ordinate < components; ordinate++)
+ interpolateAttributes_(semantics, from_path_index,
+ from_point_index, to_path_index, to_point_index,
+ sub_length, ordinate);
+ }
- do {
- if (seg_iter.hasNextSegment()) {
- seg_iter.nextSegment();
-
- if (seg_iter.getStartPointIndex() == absolute_to_index)
- return;
-
- setAttribute(semantics, seg_iter.getStartPointIndex(),
- ordinate, interpolated_attribute);
-
- seg_iter.previousSegment();
-
- do {
- Segment segment = seg_iter.nextSegment();
-
- if (seg_iter.getEndPointIndex() == absolute_to_index)
- return;
-
- double segment_length = segment.calculateLength2D();
- cumulative_length += segment_length;
- double t = cumulative_length / sub_length;
- interpolated_attribute = MathUtils.lerp(from_attribute, to_attribute, t);
-
- if (!seg_iter.isClosingSegment())
- setAttribute(semantics, seg_iter.getEndPointIndex(),
- ordinate, interpolated_attribute);
-
- } while (seg_iter.hasNextSegment());
- }
-
- } while (seg_iter.nextPath());
- }
-
- void interpolateAttributes_(int semantics, int path_index,
- int from_point_index, int to_point_index, double sub_length,
- int ordinate) {
- assert (m_bPolygon);
- SegmentIteratorImpl seg_iter = querySegmentIterator();
-
- int absolute_from_index = getPathStart(path_index) + from_point_index;
- int absolute_to_index = getPathStart(path_index) + to_point_index;
-
- if (absolute_to_index == absolute_from_index)
- return;
-
- double from_attribute = getAttributeAsDbl(semantics,
- absolute_from_index, ordinate);
- double to_attribute = getAttributeAsDbl(semantics, absolute_to_index,
- ordinate);
- double cumulative_length = 0.0;
-
- seg_iter.resetToVertex(absolute_from_index);
- seg_iter.setCirculator(true);
-
- double prev_interpolated_attribute = from_attribute;
-
- do {
- Segment segment = seg_iter.nextSegment();
- setAttribute(semantics, seg_iter.getStartPointIndex(), ordinate,
- prev_interpolated_attribute);
-
- double segment_length = segment.calculateLength2D();
- cumulative_length += segment_length;
- double t = cumulative_length / sub_length;
- prev_interpolated_attribute = MathUtils.lerp(from_attribute, to_attribute, t);
-
- } while (seg_iter.getEndPointIndex() != absolute_to_index);
- }
-
- @Override
- public void setEmpty() {
- m_curveParamwritePoint = 0;
- m_bPathStarted = false;
- m_paths = null;
- m_pathFlags = null;
- m_segmentParamIndex = null;
- m_segmentFlags = null;
- m_segmentParams = null;
- _setEmptyImpl();
- }
-
- @Override
- public void applyTransformation(Transformation2D transform) {
- applyTransformation(transform, -1);
- }
-
- public void applyTransformation(Transformation2D transform, int pathIndex) {
- if (isEmpty())
- return;
-
- if (transform.isIdentity())
- return;
-
- _verifyAllStreams();
- AttributeStreamOfDbl points = (AttributeStreamOfDbl) m_vertexAttributes[0];
- Point2D ptStart = new Point2D();
- Point2D ptControl = new Point2D();
-
- boolean bHasNonLinear;
- int fistIdx;
- int lastIdx;
- if (pathIndex < 0) {
- bHasNonLinear = hasNonLinearSegments();
- fistIdx = 0;
- lastIdx = m_pointCount;
- } else {
- bHasNonLinear = hasNonLinearSegments(pathIndex);
- fistIdx = getPathStart(pathIndex);
- lastIdx = getPathEnd(pathIndex);
- }
-
- for (int ipoint = fistIdx; ipoint < lastIdx; ipoint++) {
- ptStart.x = points.read(ipoint * 2);
- ptStart.y = points.read(ipoint * 2 + 1);
-
- if (bHasNonLinear) {
- int segIndex = m_segmentParamIndex.read(ipoint);
- if (segIndex >= 0) {
- int segmentType = (int) m_segmentFlags.read(ipoint);
- int type = segmentType & SegmentFlags.enumSegmentMask;
- switch (type) {
- case SegmentFlags.enumBezierSeg: {
- ptControl.x = m_segmentParams.read(segIndex);
- ptControl.y = m_segmentParams.read(segIndex + 1);
- transform.transform(ptControl, ptControl);
- m_segmentParams.write(segIndex, ptControl.x);
- m_segmentParams.write(segIndex + 1, ptControl.y);
-
- ptControl.x = m_segmentParams.read(segIndex + 3);
- ptControl.y = m_segmentParams.read(segIndex + 4);
- transform.transform(ptControl, ptControl);
- m_segmentParams.write(segIndex + 3, ptControl.x);
- m_segmentParams.write(segIndex + 4, ptControl.y);
- }
- break;
- case SegmentFlags.enumArcSeg:
- throw GeometryException.GeometryInternalError();
-
- }
- }
- }
-
- transform.transform(ptStart, ptStart);
- points.write(ipoint * 2, ptStart.x);
- points.write(ipoint * 2 + 1, ptStart.y);
- }
-
- notifyModified(DirtyFlags.DirtyCoordinates);
- // REFACTOR: reset the exact envelope only and transform the loose
- // envelope
- }
-
- @Override
- public void applyTransformation(Transformation3D transform) {
- if (isEmpty())
- return;
-
- addAttribute(VertexDescription.Semantics.Z);
- _verifyAllStreams();
- AttributeStreamOfDbl points = (AttributeStreamOfDbl) m_vertexAttributes[0];
- AttributeStreamOfDbl zs = (AttributeStreamOfDbl) m_vertexAttributes[1];
- Point3D ptStart = new Point3D();
- Point3D ptControl = new Point3D();
- boolean bHasNonLinear = hasNonLinearSegments();
- for (int ipoint = 0; ipoint < m_pointCount; ipoint++) {
- ptStart.x = points.read(ipoint * 2);
- ptStart.y = points.read(ipoint * 2 + 1);
- ptStart.z = zs.read(ipoint);
-
- if (bHasNonLinear) {
- int segIndex = m_segmentParamIndex.read(ipoint);
- if (segIndex >= 0) {
- int segmentType = (int) m_segmentFlags.read(ipoint);
- int type = segmentType & (int) SegmentFlags.enumSegmentMask;
- switch (type) {
- case SegmentFlags.enumBezierSeg: {
- ptControl.x = m_segmentParams.read(segIndex);
- ptControl.y = m_segmentParams.read(segIndex + 1);
- ptControl.z = m_segmentParams.read(segIndex + 2);
- ptControl = transform.transform(ptControl);
- m_segmentParams.write(segIndex, ptControl.x);
- m_segmentParams.write(segIndex + 1, ptControl.y);
- m_segmentParams.write(segIndex + 1, ptControl.z);
-
- ptControl.x = m_segmentParams.read(segIndex + 3);
- ptControl.y = m_segmentParams.read(segIndex + 4);
- ptControl.z = m_segmentParams.read(segIndex + 5);
- ptControl = transform.transform(ptControl);
- m_segmentParams.write(segIndex + 3, ptControl.x);
- m_segmentParams.write(segIndex + 4, ptControl.y);
- m_segmentParams.write(segIndex + 5, ptControl.z);
- }
- break;
- case SegmentFlags.enumArcSeg:
- throw GeometryException.GeometryInternalError();
-
- }
- }
- }
-
- ptStart = transform.transform(ptStart);
- points.write(ipoint * 2, ptStart.x);
- points.write(ipoint * 2 + 1, ptStart.y);
- zs.write(ipoint, ptStart.z);
- }
-
- // REFACTOR: reset the exact envelope only and transform the loose
- // envelope
-
- notifyModified(DirtyFlags.DirtyCoordinates);
- }
-
- @Override
- protected void _verifyStreamsImpl() {
- if (m_paths == null) {
- m_paths = (AttributeStreamOfInt32) AttributeStreamBase
- .createIndexStream(1, 0);
- m_pathFlags = (AttributeStreamOfInt8) AttributeStreamBase
- .createByteStream(1, (byte) 0);
- }
-
- if (m_segmentFlags != null) {
- m_segmentFlags.resize(m_reservedPointCount,
- (byte) SegmentFlags.enumLineSeg);
- m_segmentParamIndex.resize(m_reservedPointCount, -1);
- }
- }
-
- @Override
- void _copyToImpl(MultiVertexGeometryImpl dst) {
- MultiPathImpl dstPoly = (MultiPathImpl) dst;
- dstPoly.m_bPathStarted = false;
- dstPoly.m_curveParamwritePoint = m_curveParamwritePoint;
- dstPoly.m_fill_rule = m_fill_rule;
-
- if (m_paths != null)
- dstPoly.m_paths = new AttributeStreamOfInt32(m_paths);
- else
- dstPoly.m_paths = null;
-
- if (m_pathFlags != null)
- dstPoly.m_pathFlags = new AttributeStreamOfInt8(m_pathFlags);
- else
- dstPoly.m_pathFlags = null;
-
- if (m_segmentParamIndex != null)
- dstPoly.m_segmentParamIndex = new AttributeStreamOfInt32(
- m_segmentParamIndex);
- else
- dstPoly.m_segmentParamIndex = null;
-
- if (m_segmentFlags != null)
- dstPoly.m_segmentFlags = new AttributeStreamOfInt8(m_segmentFlags);
- else
- dstPoly.m_segmentFlags = null;
-
- if (m_segmentParams != null)
- dstPoly.m_segmentParams = new AttributeStreamOfDbl(m_segmentParams);
- else
- dstPoly.m_segmentParams = null;
-
- dstPoly.m_cachedLength2D = m_cachedLength2D;
- dstPoly.m_cachedArea2D = m_cachedArea2D;
-
- if (!_hasDirtyFlag(DirtyFlags.DirtyRingAreas2D)) {
- dstPoly.m_cachedRingAreas2D = (AttributeStreamOfDbl) m_cachedRingAreas2D;
- } else
- dstPoly.m_cachedRingAreas2D = null;
-
- }
-
- @Override
- public double calculateLength2D() {
- if (!_hasDirtyFlag(DirtyFlags.DirtyLength2D)) {
- return m_cachedLength2D;
- }
-
- SegmentIteratorImpl segIter = querySegmentIterator();
- MathUtils.KahanSummator len = new MathUtils.KahanSummator(0);
- while (segIter.nextPath()) {
- while (segIter.hasNextSegment()) {
- len.add(segIter.nextSegment().calculateLength2D());
- }
- }
-
- m_cachedLength2D = len.getResult();
- _setDirtyFlag(DirtyFlags.DirtyLength2D, false);
-
- return len.getResult();
- }
-
- @Override
- public boolean equals(Object other) {
- if (other == this)
- return true;
-
- if (!(other instanceof MultiPathImpl))
- return false;
-
- if (!super.equals(other))
- return false;
-
- MultiPathImpl otherMultiPath = (MultiPathImpl) other;
-
- int pathCount = getPathCount();
- int pathCountOther = otherMultiPath.getPathCount();
-
- if (pathCount != pathCountOther)
- return false;
-
- if (pathCount > 0 && m_paths != null
- && !m_paths.equals(otherMultiPath.m_paths, 0, pathCount + 1))
- return false;
-
- if (m_fill_rule != otherMultiPath.m_fill_rule)
- return false;
-
- {
- // Note: OGC flags do not participate in the equals operation by
- // design.
- // Because for the polygon pathFlags will have all enum_closed set,
- // we do not need to compare this stream. Only for polyline.
- // Polyline does not have OGC flags set.
- if (!m_bPolygon) {
- if (m_pathFlags != null
- && !m_pathFlags.equals(otherMultiPath.m_pathFlags, 0,
- pathCount))
- return false;
- }
- }
-
- return super.equals(other);
- }
-
- /**
- * Returns a SegmentIterator that set to a specific vertex of the
- * MultiPathImpl. The call to NextSegment will return the segment that
- * starts at the vertex. Call to PreviousSegment will return the segment
- * that starts at the previous vertex.
- */
- public SegmentIteratorImpl querySegmentIteratorAtVertex(int startVertexIndex) {
- if (startVertexIndex < 0 || startVertexIndex >= getPointCount())
- throw new IndexOutOfBoundsException();
-
- SegmentIteratorImpl iter = new SegmentIteratorImpl(this,
- startVertexIndex);
- return iter;
- }
-
- // void QuerySegmentIterator(int fromVertex, SegmentIterator iterator);
- public SegmentIteratorImpl querySegmentIterator() {
- return new SegmentIteratorImpl(this);
- }
-
- @Override
- public void _updateXYImpl(boolean bExact) {
- super._updateXYImpl(bExact);
- boolean bHasCurves = hasNonLinearSegments();
- if (bHasCurves) {
- SegmentIteratorImpl segIter = querySegmentIterator();
- while (segIter.nextPath()) {
- while (segIter.hasNextSegment()) {
- Segment curve = segIter.nextCurve();
- if (curve != null) {
- Envelope2D env2D = new Envelope2D();
- curve.queryEnvelope2D(env2D);
- m_envelope.merge(env2D);
- } else
- break;
- }
- }
- }
- }
-
- @Override
- void calculateEnvelope2D(Envelope2D env, boolean bExact) {
- super.calculateEnvelope2D(env, bExact);
- boolean bHasCurves = hasNonLinearSegments();
- if (bHasCurves) {
- SegmentIteratorImpl segIter = querySegmentIterator();
- while (segIter.nextPath()) {
- while (segIter.hasNextSegment()) {
- Segment curve = segIter.nextCurve();
- if (curve != null) {
- Envelope2D env2D = new Envelope2D();
- curve.queryEnvelope2D(env2D);
- env.merge(env2D);
- } else
- break;
- }
- }
- }
- }
-
- @Override
- public void _notifyModifiedAllImpl() {
- if (m_paths == null || m_paths.size() == 0)// if (m_paths == null ||
- // !m_paths.size())
- m_pointCount = 0;
- else
- m_pointCount = m_paths.read(m_paths.size() - 1);
- }
-
- @Override
- public double calculateArea2D() {
- if (!m_bPolygon)
- return 0.0;
-
- _updateRingAreas2D();
-
- return m_cachedArea2D;
- }
-
- /**
- * Returns True if the ring is an exterior ring. Valid only for simple
- * polygons.
- */
- public boolean isExteriorRing(int ringIndex) {
- if (!m_bPolygon)
- return false;
-
- if (!_hasDirtyFlag(DirtyFlags.DirtyOGCFlags))
- return (m_pathFlags.read(ringIndex) & (byte) PathFlags.enumOGCStartPolygon) != 0;
-
- _updateRingAreas2D();
- return m_cachedRingAreas2D.read(ringIndex) > 0;
- // Should we make a function called _UpdateHasNonLinearSegmentsFlags and
- // call it here?
- }
-
- public double calculateRingArea2D(int pathIndex) {
- if (!m_bPolygon)
- return 0.0;
-
- _updateRingAreas2D();
-
- return m_cachedRingAreas2D.read(pathIndex);
- }
-
- public void _updateRingAreas2D() {
- if (_hasDirtyFlag(DirtyFlags.DirtyRingAreas2D)) {
- int pathCount = getPathCount();
-
- if (m_cachedRingAreas2D == null)
- m_cachedRingAreas2D = new AttributeStreamOfDbl(pathCount);
- else if (m_cachedRingAreas2D.size() != pathCount)
- m_cachedRingAreas2D.resize(pathCount);
-
- MathUtils.KahanSummator totalArea = new MathUtils.KahanSummator(0);
- MathUtils.KahanSummator pathArea = new MathUtils.KahanSummator(0);
- Point2D pt = new Point2D();
- int ipath = 0;
- SegmentIteratorImpl segIter = querySegmentIterator();
- while (segIter.nextPath()) {
- pathArea.reset();
- getXY(getPathStart(segIter.getPathIndex()), pt);// get the area
- // calculation
- // origin to be
- // the origin of
- // the ring.
- while (segIter.hasNextSegment()) {
- pathArea.add(segIter.nextSegment()._calculateArea2DHelper(
- pt.x, pt.y));
- }
-
- totalArea.add(pathArea.getResult());
-
- int i = ipath++;
- m_cachedRingAreas2D.write(i, pathArea.getResult());
- }
-
- m_cachedArea2D = totalArea.getResult();
- _setDirtyFlag(DirtyFlags.DirtyRingAreas2D, false);
- }
- }
-
- int getOGCPolygonCount() {
- if (!m_bPolygon)
- return 0;
-
- _updateOGCFlags();
-
- int polygonCount = 0;
- int partCount = getPathCount();
- for (int ipart = 0; ipart < partCount; ipart++) {
- if (((int) m_pathFlags.read(ipart) & (int) PathFlags.enumOGCStartPolygon) != 0)
- polygonCount++;
- }
-
- return polygonCount;
- }
-
- protected void _updateOGCFlags() {
- if (_hasDirtyFlag(DirtyFlags.DirtyOGCFlags)) {
- _updateRingAreas2D();
-
- int pathCount = getPathCount();
- if (pathCount > 0 && (m_pathFlags == null || m_pathFlags.size() < pathCount))
- m_pathFlags = (AttributeStreamOfInt8) AttributeStreamBase
- .createByteStream(pathCount + 1);
-
- int firstSign = 1;
- for (int ipath = 0; ipath < pathCount; ipath++) {
- double area = m_cachedRingAreas2D.read(ipath);
- if (ipath == 0)
- firstSign = area > 0 ? 1 : -1;
- if (area * firstSign > 0.0)
- m_pathFlags.setBits(ipath,
- (byte) PathFlags.enumOGCStartPolygon);
- else
- m_pathFlags.clearBits(ipath,
- (byte) PathFlags.enumOGCStartPolygon);
- }
- _setDirtyFlag(DirtyFlags.DirtyOGCFlags, false);
- }
- }
-
- public int getPathIndexFromPointIndex(int pointIndex) {
- int positionHint = m_currentPathIndex;// in case of multithreading
- // thiswould simply produce an
- // invalid value
- int pathCount = getPathCount();
-
- // Try using the hint position first to get the path index.
- if (positionHint >= 0 && positionHint < pathCount) {
- if (pointIndex < getPathEnd(positionHint)) {
- if (pointIndex >= getPathStart(positionHint))
- return positionHint;
- positionHint--;
- } else {
- positionHint++;
- }
-
- if (positionHint >= 0 && positionHint < pathCount) {
- if (pointIndex >= getPathStart(positionHint)
- && pointIndex < getPathEnd(positionHint)) {
- m_currentPathIndex = positionHint;
- return positionHint;
- }
- }
- }
-
- if (pathCount < 5) {// TODO: time the performance to choose when to use
- // linear search.
- for (int i = 0; i < pathCount; i++) {
- if (pointIndex < getPathEnd(i)) {
- m_currentPathIndex = i;
- return i;
- }
- }
- throw new GeometryException("corrupted geometry");
- }
-
- // Do binary search:
- int minPathIndex = 0;
- int maxPathIndex = pathCount - 1;
- while (maxPathIndex > minPathIndex) {
- int mid = minPathIndex + ((maxPathIndex - minPathIndex) >> 1);
- int pathStart = getPathStart(mid);
- if (pointIndex < pathStart)
- maxPathIndex = mid - 1;
- else {
- int pathEnd = getPathEnd(mid);
- if (pointIndex >= pathEnd)
- minPathIndex = mid + 1;
- else {
- m_currentPathIndex = mid;
- return mid;
- }
- }
- }
-
- m_currentPathIndex = minPathIndex;
- return minPathIndex;
- }
-
- int getHighestPointIndex(int path_index) {
- assert (path_index >= 0 && path_index < getPathCount());
-
- AttributeStreamOfDbl position = (AttributeStreamOfDbl) (getAttributeStreamRef(VertexDescription.Semantics.POSITION));
- AttributeStreamOfInt32 paths = (AttributeStreamOfInt32) (getPathStreamRef());
-
- int path_end = getPathEnd(path_index);
- int path_start = getPathStart(path_index);
- int max_index = -1;
- Point2D max_point = new Point2D(), pt = new Point2D();
- max_point.y = NumberUtils.negativeInf();
- max_point.x = NumberUtils.negativeInf();
-
- for (int i = path_start + 0; i < path_end; i++) {
- position.read(2 * i, pt);
- if (max_point.compare(pt) == -1) {
- max_index = i;
- max_point.setCoords(pt);
- }
- }
-
- return max_index;
- }
-
- /**
- * Returns total segment count in the MultiPathImpl.
- */
- public int getSegmentCount() {
- int segCount = getPointCount();
- if (!m_bPolygon) {
- segCount -= getPathCount();
- for (int i = 0, n = getPathCount(); i < n; i++)
- if (isClosedPath(i))
- segCount++;
- }
-
- return segCount;
- }
-
- public int getSegmentCount(int path_index) {
- int segCount = getPathSize(path_index);
- if (!isClosedPath(path_index))
- segCount--;
- return segCount;
- }
-
- // HEADER defintions
- @Override
- public Geometry createInstance() {
- return new MultiPathImpl(m_bPolygon, getDescription());
- }
-
- @Override
- public int getDimension() {
- return m_bPolygon ? 2 : 1;
- }
-
- @Override
- public Geometry.Type getType() {
- return m_bPolygon ? Type.Polygon : Type.Polyline;
- }
-
- /**
- * Returns True if the class is envelope. THis is not an exact method. Only
- * addEnvelope makes this true.
- */
- public boolean isEnvelope() {
- return !_hasDirtyFlag(DirtyFlags.DirtyIsEnvelope);
- }
-
- /**
- * Returns a reference to the AttributeStream of MultiPathImpl parts
- * (Paths).
- *
- * For the non empty MultiPathImpl, that stream contains start points of the
- * MultiPathImpl curves. In addition, the last element is the total point
- * count. The number of vertices in a given part is parts[i + 1] - parts[i].
- */
- public AttributeStreamOfInt32 getPathStreamRef() {
- throwIfEmpty();
- return m_paths;
- }
-
- /**
- * sets a reference to an AttributeStream of MultiPathImpl paths (Paths).
- */
- public void setPathStreamRef(AttributeStreamOfInt32 paths) {
- m_paths = paths;
- notifyModified(DirtyFlags.DirtyAll);
- }
-
- /**
- * Returns a reference to the AttributeStream of Segment flags (SegmentFlags
- * flags). Can be NULL when no non-linear segments are present.
- *
- * Segment flags indicate what kind of segment originates (starts) on the
- * given point. The last vertices of open Path parts has enumNone flag.
- */
- public AttributeStreamOfInt8 getSegmentFlagsStreamRef() {
- throwIfEmpty();
- return m_segmentFlags;
- }
-
- /**
- * Returns a reference to the AttributeStream of Path flags (PathFlags
- * flags).
- *
- * Each start point of a path has a flag set to indicate if the Path is open
- * or closed.
- */
- public AttributeStreamOfInt8 getPathFlagsStreamRef() {
- throwIfEmpty();
- return m_pathFlags;
- }
-
- /**
- * sets a reference to an AttributeStream of Path flags (PathFlags flags).
- */
- public void setPathFlagsStreamRef(AttributeStreamOfInt8 pathFlags) {
- m_pathFlags = pathFlags;
- notifyModified(DirtyFlags.DirtyAll);
- }
-
- public AttributeStreamOfInt32 getSegmentIndexStreamRef() {
- throwIfEmpty();
- return m_segmentParamIndex;
- }
-
- public AttributeStreamOfDbl getSegmentDataStreamRef() {
- throwIfEmpty();
- return m_segmentParams;
- }
-
- public int getPathCount() {
- return (m_paths != null) ? m_paths.size() - 1 : 0;
- }
-
- public int getPathEnd(int partIndex) {
- return m_paths.read(partIndex + 1);
- }
-
- public int getPathSize(int partIndex) {
- return m_paths.read(partIndex + 1) - m_paths.read(partIndex);
- }
-
- public int getPathStart(int partIndex) {
- return m_paths.read(partIndex);
- }
-
- @Override
- public Object _getImpl() {
- return this;
- }
-
- public void setDirtyOGCFlags(boolean bYesNo) {
- _setDirtyFlag(DirtyFlags.DirtyOGCFlags, bYesNo);
- }
-
- public boolean hasDirtyOGCStartFlags() {
- return _hasDirtyFlag(DirtyFlags.DirtyOGCFlags);
- }
-
- public void setDirtyRingAreas2D(boolean bYesNo) {
- _setDirtyFlag(DirtyFlags.DirtyRingAreas2D, bYesNo);
- }
-
- public boolean hasDirtyRingAreas2D() {
- return _hasDirtyFlag(DirtyFlags.DirtyRingAreas2D);
- }
-
- public void setRingAreasStreamRef(AttributeStreamOfDbl ringAreas) {
- m_cachedRingAreas2D = ringAreas;
- _setDirtyFlag(DirtyFlags.DirtyRingAreas2D, false);
- }
-
- // HEADER defintions
-
- // // TODO check this against current implementation in native
- // public void notifyModified(int flags)
- // {
- // if(flags == DirtyFlags.DirtyAll)
- // {
- // m_reservedPointCount = -1;
- // _notifyModifiedAllImpl();
- // }
- // m_flagsMask |= flags;
- // _clearAccelerators();
- //
- //
- // // ROHIT's implementation
- // // if (m_paths == null || 0 == m_paths.size())
- // // m_pointCount = 0;
- // // else
- // // m_pointCount = m_paths.read(m_paths.size() - 1);
- // //
- // // super.notifyModified(flags);
- // }
-
- @Override
- public boolean _buildRasterizedGeometryAccelerator(double toleranceXY,
- GeometryAccelerationDegree accelDegree) {
- if (m_accelerators == null)// (!m_accelerators)
- {
- m_accelerators = new GeometryAccelerators();
- }
-
- int rasterSize = RasterizedGeometry2D
- .rasterSizeFromAccelerationDegree(accelDegree);
- RasterizedGeometry2D rgeom = m_accelerators.getRasterizedGeometry();
- if (rgeom != null) {
- if (rgeom.getToleranceXY() < toleranceXY
- || rasterSize > rgeom.getRasterSize()) {
- m_accelerators._setRasterizedGeometry(null);
- } else
- return true;
- }
-
- rgeom = RasterizedGeometry2D.create(this, toleranceXY, rasterSize);
- m_accelerators._setRasterizedGeometry(rgeom);
- //rgeom.dbgSaveToBitmap("c:/temp/ddd.bmp");
- return true;
- }
-
- @Override
- public int hashCode() {
- int hashCode = super.hashCode();
-
- if (!isEmptyImpl()) {
- int pathCount = getPathCount();
-
- if (m_paths != null)
- m_paths.calculateHashImpl(hashCode, 0, pathCount + 1);
-
- if (m_pathFlags != null)
- m_pathFlags.calculateHashImpl(hashCode, 0, pathCount);
- }
-
- return hashCode;
- }
-
- public byte getSegmentFlags(int ivertex) {
- if (m_segmentFlags != null)
- return m_segmentFlags.read(ivertex);
- else
- return (byte) SegmentFlags.enumLineSeg;
- }
-
- public void getSegment(int startVertexIndex, SegmentBuffer segBuffer,
- boolean bStripAttributes) {
- int ipath = getPathIndexFromPointIndex(startVertexIndex);
- if (startVertexIndex == getPathEnd(ipath) - 1 && !isClosedPath(ipath))
- throw new GeometryException("index out of bounds");
-
- _verifyAllStreams();
- AttributeStreamOfInt8 segFlagStream = getSegmentFlagsStreamRef();
- int segFlag = SegmentFlags.enumLineSeg;
- if (segFlagStream != null)
- segFlag = segFlagStream.read(startVertexIndex)
- & SegmentFlags.enumSegmentMask;
-
- switch (segFlag) {
- case SegmentFlags.enumLineSeg:
- segBuffer.createLine();
- break;
- case SegmentFlags.enumBezierSeg:
- throw GeometryException.GeometryInternalError();
- case SegmentFlags.enumArcSeg:
- throw GeometryException.GeometryInternalError();
- default:
- throw GeometryException.GeometryInternalError();
- }
-
- Segment currentSegment = segBuffer.get();
- if (!bStripAttributes)
- currentSegment.assignVertexDescription(m_description);
- else
- currentSegment
- .assignVertexDescription(VertexDescriptionDesignerImpl
- .getDefaultDescriptor2D());
-
- int endVertexIndex;
- if (startVertexIndex == getPathEnd(ipath) - 1 && isClosedPath(ipath)) {
- endVertexIndex = getPathStart(ipath);
- } else
- endVertexIndex = startVertexIndex + 1;
-
- Point2D pt = new Point2D();
- getXY(startVertexIndex, pt);
- currentSegment.setStartXY(pt);
- getXY(endVertexIndex, pt);
- currentSegment.setEndXY(pt);
-
- if (!bStripAttributes) {
- for (int i = 1, nattr = m_description.getAttributeCount(); i < nattr; i++) {
- int semantics = m_description._getSemanticsImpl(i);
- int ncomp = VertexDescription.getComponentCount(semantics);
- for (int ord = 0; ord < ncomp; ord++) {
- double vs = getAttributeAsDbl(semantics, startVertexIndex,
- ord);
- currentSegment.setStartAttribute(semantics, ord, vs);
- double ve = getAttributeAsDbl(semantics, endVertexIndex,
- ord);
- currentSegment.setEndAttribute(semantics, ord, ve);
- }
- }
- }
- }
-
- void queryPathEnvelope2D(int path_index, Envelope2D envelope) {
- if (path_index >= getPathCount())
- throw new IllegalArgumentException();
-
- if (isEmpty()) {
- envelope.setEmpty();
- return;
- }
-
- if (hasNonLinearSegments(path_index)) {
- throw new GeometryException("not implemented");
- } else {
- AttributeStreamOfDbl stream = (AttributeStreamOfDbl) getAttributeStreamRef(VertexDescription.Semantics.POSITION);
- Point2D pt = new Point2D();
- Envelope2D env = new Envelope2D();
- env.setEmpty();
- for (int i = getPathStart(path_index), iend = getPathEnd(path_index); i < iend; i++) {
- stream.read(2 * i, pt);
- env.merge(pt);
- }
- envelope.setCoords(env);
- }
- }
-
- public void queryLoosePathEnvelope2D(int path_index, Envelope2D envelope) {
- if (path_index >= getPathCount())
- throw new IllegalArgumentException();
-
- if (isEmpty()) {
- envelope.setEmpty();
- return;
- }
-
- if (hasNonLinearSegments(path_index)) {
- throw new GeometryException("not implemented");
- } else {
- AttributeStreamOfDbl stream = (AttributeStreamOfDbl) getAttributeStreamRef(VertexDescription.Semantics.POSITION);
- Point2D pt = new Point2D();
- Envelope2D env = new Envelope2D();
- env.setEmpty();
- for (int i = getPathStart(path_index), iend = getPathEnd(path_index); i < iend; i++) {
- stream.read(2 * i, pt);
- env.merge(pt);
- }
- envelope.setCoords(env);
- }
- }
-
- @Override
- public boolean _buildQuadTreeAccelerator(GeometryAccelerationDegree d) {
- if (m_accelerators == null)// (!m_accelerators)
- {
- m_accelerators = new GeometryAccelerators();
- }
-
- if (d == GeometryAccelerationDegree.enumMild || getPointCount() < 16)
- return false;
-
- QuadTreeImpl quad_tree_impl = InternalUtils.buildQuadTree(this);
- m_accelerators._setQuadTree(quad_tree_impl);
-
- return true;
- }
-
- boolean _buildQuadTreeForPathsAccelerator(GeometryAccelerationDegree degree) {
- if (m_accelerators == null) {
- m_accelerators = new GeometryAccelerators();
- }
-
- // TODO: when less than two envelopes - no need to this.
-
- if (m_accelerators.getQuadTreeForPaths() != null)
- return true;
-
- m_accelerators._setQuadTreeForPaths(null);
- QuadTreeImpl quad_tree_impl = InternalUtils.buildQuadTreeForPaths(this);
- m_accelerators._setQuadTreeForPaths(quad_tree_impl);
-
- return true;
- }
-
- void setFillRule(int rule) {
- assert (m_bPolygon);
- m_fill_rule = rule;
- }
-
- int getFillRule() {
- return m_fill_rule;
- }
-
- void clearDirtyOGCFlags() {
- _setDirtyFlag(DirtyFlags.DirtyOGCFlags, false);
- }
+ void interpolateAttributes(int path_index, int from_point_index,
+ int to_point_index) {
+ int nattr = m_description.getAttributeCount();
+
+ if (nattr == 1)
+ return; // only has position
+
+ double sub_length = calculateSubLength2D(path_index, from_point_index,
+ to_point_index);
+
+ if (sub_length == 0.0)
+ return;
+
+ for (int iattr = 1; iattr < nattr; iattr++) {
+ int semantics = m_description.getSemantics(iattr);
+
+ int interpolation = VertexDescription.getInterpolation(semantics);
+ if (interpolation == VertexDescription.Interpolation.ANGULAR)
+ continue;
+
+ int components = VertexDescription.getComponentCount(semantics);
+
+ for (int ordinate = 0; ordinate < components; ordinate++)
+ interpolateAttributes_(semantics, path_index, from_point_index,
+ to_point_index, sub_length, ordinate);
+ }
+ }
+
+ void interpolateAttributesForSemantics(int semantics, int path_index,
+ int from_point_index, int to_point_index) {
+ if (semantics == VertexDescription.Semantics.POSITION)
+ return;
+
+ if (!hasAttribute(semantics))
+ throw new IllegalArgumentException(
+ "does not have the given attribute");
+
+ int interpolation = VertexDescription.getInterpolation(semantics);
+ if (interpolation == VertexDescription.Interpolation.ANGULAR)
+ throw new IllegalArgumentException(
+ "not implemented for the given semantics");
+
+ double sub_length = calculateSubLength2D(path_index, from_point_index,
+ to_point_index);
+
+ if (sub_length == 0.0)
+ return;
+
+ int components = VertexDescription.getComponentCount(semantics);
+
+ for (int ordinate = 0; ordinate < components; ordinate++)
+ interpolateAttributes_(semantics, path_index, from_point_index,
+ to_point_index, sub_length, ordinate);
+ }
+
+ // TODO: Add code fore interpolation type (none and angular)
+ void interpolateAttributes_(int semantics, int from_path_index,
+ int from_point_index, int to_path_index, int to_point_index,
+ double sub_length, int ordinate) {
+ SegmentIteratorImpl seg_iter = querySegmentIterator();
+
+ int absolute_from_index = getPathStart(from_path_index)
+ + from_point_index;
+ int absolute_to_index = getPathStart(to_path_index) + to_point_index;
+
+ double from_attribute = getAttributeAsDbl(semantics,
+ absolute_from_index, ordinate);
+ double to_attribute = getAttributeAsDbl(semantics, absolute_to_index,
+ ordinate);
+ double interpolated_attribute = from_attribute;
+ double cumulative_length = 0.0;
+
+ seg_iter.resetToVertex(absolute_from_index);
+
+ do {
+ if (seg_iter.hasNextSegment()) {
+ seg_iter.nextSegment();
+
+ if (seg_iter.getStartPointIndex() == absolute_to_index)
+ return;
+
+ setAttribute(semantics, seg_iter.getStartPointIndex(),
+ ordinate, interpolated_attribute);
+
+ seg_iter.previousSegment();
+
+ do {
+ Segment segment = seg_iter.nextSegment();
+
+ if (seg_iter.getEndPointIndex() == absolute_to_index)
+ return;
+
+ double segment_length = segment.calculateLength2D();
+ cumulative_length += segment_length;
+ double t = cumulative_length / sub_length;
+ interpolated_attribute = MathUtils.lerp(from_attribute, to_attribute, t);
+
+ if (!seg_iter.isClosingSegment())
+ setAttribute(semantics, seg_iter.getEndPointIndex(),
+ ordinate, interpolated_attribute);
+
+ } while (seg_iter.hasNextSegment());
+ }
+
+ } while (seg_iter.nextPath());
+ }
+
+ void interpolateAttributes_(int semantics, int path_index,
+ int from_point_index, int to_point_index, double sub_length,
+ int ordinate) {
+ assert (m_bPolygon);
+ SegmentIteratorImpl seg_iter = querySegmentIterator();
+
+ int absolute_from_index = getPathStart(path_index) + from_point_index;
+ int absolute_to_index = getPathStart(path_index) + to_point_index;
+
+ if (absolute_to_index == absolute_from_index)
+ return;
+
+ double from_attribute = getAttributeAsDbl(semantics,
+ absolute_from_index, ordinate);
+ double to_attribute = getAttributeAsDbl(semantics, absolute_to_index,
+ ordinate);
+ double cumulative_length = 0.0;
+
+ seg_iter.resetToVertex(absolute_from_index);
+ seg_iter.setCirculator(true);
+
+ double prev_interpolated_attribute = from_attribute;
+
+ do {
+ Segment segment = seg_iter.nextSegment();
+ setAttribute(semantics, seg_iter.getStartPointIndex(), ordinate,
+ prev_interpolated_attribute);
+
+ double segment_length = segment.calculateLength2D();
+ cumulative_length += segment_length;
+ double t = cumulative_length / sub_length;
+ prev_interpolated_attribute = MathUtils.lerp(from_attribute, to_attribute, t);
+
+ } while (seg_iter.getEndPointIndex() != absolute_to_index);
+ }
+
+ @Override
+ public void setEmpty() {
+ m_curveParamwritePoint = 0;
+ m_bPathStarted = false;
+ m_paths = null;
+ m_pathFlags = null;
+ m_segmentParamIndex = null;
+ m_segmentFlags = null;
+ m_segmentParams = null;
+ _setEmptyImpl();
+ }
+
+ @Override
+ public void applyTransformation(Transformation2D transform) {
+ applyTransformation(transform, -1);
+ }
+
+ public void applyTransformation(Transformation2D transform, int pathIndex) {
+ if (isEmpty())
+ return;
+
+ if (transform.isIdentity())
+ return;
+
+ _verifyAllStreams();
+ AttributeStreamOfDbl points = (AttributeStreamOfDbl) m_vertexAttributes[0];
+ Point2D ptStart = new Point2D();
+ Point2D ptControl = new Point2D();
+
+ boolean bHasNonLinear;
+ int fistIdx;
+ int lastIdx;
+ if (pathIndex < 0) {
+ bHasNonLinear = hasNonLinearSegments();
+ fistIdx = 0;
+ lastIdx = m_pointCount;
+ } else {
+ bHasNonLinear = hasNonLinearSegments(pathIndex);
+ fistIdx = getPathStart(pathIndex);
+ lastIdx = getPathEnd(pathIndex);
+ }
+
+ for (int ipoint = fistIdx; ipoint < lastIdx; ipoint++) {
+ ptStart.x = points.read(ipoint * 2);
+ ptStart.y = points.read(ipoint * 2 + 1);
+
+ if (bHasNonLinear) {
+ int segIndex = m_segmentParamIndex.read(ipoint);
+ if (segIndex >= 0) {
+ int segmentType = (int) m_segmentFlags.read(ipoint);
+ int type = segmentType & SegmentFlags.enumSegmentMask;
+ switch (type) {
+ case SegmentFlags.enumBezierSeg: {
+ ptControl.x = m_segmentParams.read(segIndex);
+ ptControl.y = m_segmentParams.read(segIndex + 1);
+ transform.transform(ptControl, ptControl);
+ m_segmentParams.write(segIndex, ptControl.x);
+ m_segmentParams.write(segIndex + 1, ptControl.y);
+
+ ptControl.x = m_segmentParams.read(segIndex + 3);
+ ptControl.y = m_segmentParams.read(segIndex + 4);
+ transform.transform(ptControl, ptControl);
+ m_segmentParams.write(segIndex + 3, ptControl.x);
+ m_segmentParams.write(segIndex + 4, ptControl.y);
+ }
+ break;
+ case SegmentFlags.enumArcSeg:
+ throw GeometryException.GeometryInternalError();
+
+ }
+ }
+ }
+
+ transform.transform(ptStart, ptStart);
+ points.write(ipoint * 2, ptStart.x);
+ points.write(ipoint * 2 + 1, ptStart.y);
+ }
+
+ notifyModified(DirtyFlags.DirtyCoordinates);
+ // REFACTOR: reset the exact envelope only and transform the loose
+ // envelope
+ }
+
+ @Override
+ public void applyTransformation(Transformation3D transform) {
+ if (isEmpty())
+ return;
+
+ addAttribute(VertexDescription.Semantics.Z);
+ _verifyAllStreams();
+ AttributeStreamOfDbl points = (AttributeStreamOfDbl) m_vertexAttributes[0];
+ AttributeStreamOfDbl zs = (AttributeStreamOfDbl) m_vertexAttributes[1];
+ Point3D ptStart = new Point3D();
+ Point3D ptControl = new Point3D();
+ boolean bHasNonLinear = hasNonLinearSegments();
+ for (int ipoint = 0; ipoint < m_pointCount; ipoint++) {
+ ptStart.x = points.read(ipoint * 2);
+ ptStart.y = points.read(ipoint * 2 + 1);
+ ptStart.z = zs.read(ipoint);
+
+ if (bHasNonLinear) {
+ int segIndex = m_segmentParamIndex.read(ipoint);
+ if (segIndex >= 0) {
+ int segmentType = (int) m_segmentFlags.read(ipoint);
+ int type = segmentType & (int) SegmentFlags.enumSegmentMask;
+ switch (type) {
+ case SegmentFlags.enumBezierSeg: {
+ ptControl.x = m_segmentParams.read(segIndex);
+ ptControl.y = m_segmentParams.read(segIndex + 1);
+ ptControl.z = m_segmentParams.read(segIndex + 2);
+ ptControl = transform.transform(ptControl);
+ m_segmentParams.write(segIndex, ptControl.x);
+ m_segmentParams.write(segIndex + 1, ptControl.y);
+ m_segmentParams.write(segIndex + 1, ptControl.z);
+
+ ptControl.x = m_segmentParams.read(segIndex + 3);
+ ptControl.y = m_segmentParams.read(segIndex + 4);
+ ptControl.z = m_segmentParams.read(segIndex + 5);
+ ptControl = transform.transform(ptControl);
+ m_segmentParams.write(segIndex + 3, ptControl.x);
+ m_segmentParams.write(segIndex + 4, ptControl.y);
+ m_segmentParams.write(segIndex + 5, ptControl.z);
+ }
+ break;
+ case SegmentFlags.enumArcSeg:
+ throw GeometryException.GeometryInternalError();
+
+ }
+ }
+ }
+
+ ptStart = transform.transform(ptStart);
+ points.write(ipoint * 2, ptStart.x);
+ points.write(ipoint * 2 + 1, ptStart.y);
+ zs.write(ipoint, ptStart.z);
+ }
+
+ // REFACTOR: reset the exact envelope only and transform the loose
+ // envelope
+
+ notifyModified(DirtyFlags.DirtyCoordinates);
+ }
+
+ @Override
+ protected void _verifyStreamsImpl() {
+ if (m_paths == null) {
+ m_paths = (AttributeStreamOfInt32) AttributeStreamBase
+ .createIndexStream(1, 0);
+ m_pathFlags = (AttributeStreamOfInt8) AttributeStreamBase
+ .createByteStream(1, (byte) 0);
+ }
+
+ if (m_segmentFlags != null) {
+ m_segmentFlags.resize(m_reservedPointCount,
+ (byte) SegmentFlags.enumLineSeg);
+ m_segmentParamIndex.resize(m_reservedPointCount, -1);
+ }
+ }
+
+ @Override
+ void _copyToImpl(MultiVertexGeometryImpl dst) {
+ MultiPathImpl dstPoly = (MultiPathImpl) dst;
+ dstPoly.m_bPathStarted = false;
+ dstPoly.m_curveParamwritePoint = m_curveParamwritePoint;
+ dstPoly.m_fill_rule = m_fill_rule;
+
+ if (m_paths != null)
+ dstPoly.m_paths = new AttributeStreamOfInt32(m_paths);
+ else
+ dstPoly.m_paths = null;
+
+ if (m_pathFlags != null)
+ dstPoly.m_pathFlags = new AttributeStreamOfInt8(m_pathFlags);
+ else
+ dstPoly.m_pathFlags = null;
+
+ if (m_segmentParamIndex != null)
+ dstPoly.m_segmentParamIndex = new AttributeStreamOfInt32(
+ m_segmentParamIndex);
+ else
+ dstPoly.m_segmentParamIndex = null;
+
+ if (m_segmentFlags != null)
+ dstPoly.m_segmentFlags = new AttributeStreamOfInt8(m_segmentFlags);
+ else
+ dstPoly.m_segmentFlags = null;
+
+ if (m_segmentParams != null)
+ dstPoly.m_segmentParams = new AttributeStreamOfDbl(m_segmentParams);
+ else
+ dstPoly.m_segmentParams = null;
+
+ dstPoly.m_cachedLength2D = m_cachedLength2D;
+ dstPoly.m_cachedArea2D = m_cachedArea2D;
+
+ if (!_hasDirtyFlag(DirtyFlags.DirtyRingAreas2D)) {
+ dstPoly.m_cachedRingAreas2D = (AttributeStreamOfDbl) m_cachedRingAreas2D;
+ } else
+ dstPoly.m_cachedRingAreas2D = null;
+
+ }
+
+ @Override
+ public double calculateLength2D() {
+ if (!_hasDirtyFlag(DirtyFlags.DirtyLength2D)) {
+ return m_cachedLength2D;
+ }
+
+ SegmentIteratorImpl segIter = querySegmentIterator();
+ MathUtils.KahanSummator len = new MathUtils.KahanSummator(0);
+ while (segIter.nextPath()) {
+ while (segIter.hasNextSegment()) {
+ len.add(segIter.nextSegment().calculateLength2D());
+ }
+ }
+
+ m_cachedLength2D = len.getResult();
+ _setDirtyFlag(DirtyFlags.DirtyLength2D, false);
+
+ return len.getResult();
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this)
+ return true;
+
+ if (!(other instanceof MultiPathImpl))
+ return false;
+
+ if (!super.equals(other))
+ return false;
+
+ MultiPathImpl otherMultiPath = (MultiPathImpl) other;
+
+ int pathCount = getPathCount();
+ int pathCountOther = otherMultiPath.getPathCount();
+
+ if (pathCount != pathCountOther)
+ return false;
+
+ if (pathCount > 0 && m_paths != null
+ && !m_paths.equals(otherMultiPath.m_paths, 0, pathCount + 1))
+ return false;
+
+ if (m_fill_rule != otherMultiPath.m_fill_rule)
+ return false;
+
+ {
+ // Note: OGC flags do not participate in the equals operation by
+ // design.
+ // Because for the polygon pathFlags will have all enum_closed set,
+ // we do not need to compare this stream. Only for polyline.
+ // Polyline does not have OGC flags set.
+ if (!m_bPolygon) {
+ if (m_pathFlags != null
+ && !m_pathFlags.equals(otherMultiPath.m_pathFlags, 0,
+ pathCount))
+ return false;
+ }
+ }
+
+ return super.equals(other);
+ }
+
+ /**
+ * Returns a SegmentIterator that set to a specific vertex of the
+ * MultiPathImpl. The call to NextSegment will return the segment that
+ * starts at the vertex. Call to PreviousSegment will return the segment
+ * that starts at the previous vertex.
+ */
+ public SegmentIteratorImpl querySegmentIteratorAtVertex(int startVertexIndex) {
+ if (startVertexIndex < 0 || startVertexIndex >= getPointCount())
+ throw new IndexOutOfBoundsException();
+
+ SegmentIteratorImpl iter = new SegmentIteratorImpl(this,
+ startVertexIndex);
+ return iter;
+ }
+
+ // void QuerySegmentIterator(int fromVertex, SegmentIterator iterator);
+ public SegmentIteratorImpl querySegmentIterator() {
+ return new SegmentIteratorImpl(this);
+ }
+
+ @Override
+ public void _updateXYImpl(boolean bExact) {
+ super._updateXYImpl(bExact);
+ boolean bHasCurves = hasNonLinearSegments();
+ if (bHasCurves) {
+ SegmentIteratorImpl segIter = querySegmentIterator();
+ while (segIter.nextPath()) {
+ while (segIter.hasNextSegment()) {
+ Segment curve = segIter.nextCurve();
+ if (curve != null) {
+ Envelope2D env2D = new Envelope2D();
+ curve.queryEnvelope2D(env2D);
+ m_envelope.merge(env2D);
+ } else
+ break;
+ }
+ }
+ }
+ }
+
+ @Override
+ void calculateEnvelope2D(Envelope2D env, boolean bExact) {
+ super.calculateEnvelope2D(env, bExact);
+ boolean bHasCurves = hasNonLinearSegments();
+ if (bHasCurves) {
+ SegmentIteratorImpl segIter = querySegmentIterator();
+ while (segIter.nextPath()) {
+ while (segIter.hasNextSegment()) {
+ Segment curve = segIter.nextCurve();
+ if (curve != null) {
+ Envelope2D env2D = new Envelope2D();
+ curve.queryEnvelope2D(env2D);
+ env.merge(env2D);
+ } else
+ break;
+ }
+ }
+ }
+ }
+
+ @Override
+ public void _notifyModifiedAllImpl() {
+ if (m_paths == null || m_paths.size() == 0)// if (m_paths == null ||
+ // !m_paths.size())
+ m_pointCount = 0;
+ else
+ m_pointCount = m_paths.read(m_paths.size() - 1);
+ }
+
+ @Override
+ public double calculateArea2D() {
+ if (!m_bPolygon)
+ return 0.0;
+
+ _updateRingAreas2D();
+
+ return m_cachedArea2D;
+ }
+
+ /**
+ * Returns True if the ring is an exterior ring. Valid only for simple
+ * polygons.
+ */
+ public boolean isExteriorRing(int ringIndex) {
+ if (!m_bPolygon)
+ return false;
+
+ if (!_hasDirtyFlag(DirtyFlags.DirtyOGCFlags))
+ return (m_pathFlags.read(ringIndex) & (byte) PathFlags.enumOGCStartPolygon) != 0;
+
+ _updateRingAreas2D();
+ return m_cachedRingAreas2D.read(ringIndex) > 0;
+ // Should we make a function called _UpdateHasNonLinearSegmentsFlags and
+ // call it here?
+ }
+
+ public double calculateRingArea2D(int pathIndex) {
+ if (!m_bPolygon)
+ return 0.0;
+
+ _updateRingAreas2D();
+
+ return m_cachedRingAreas2D.read(pathIndex);
+ }
+
+ public void _updateRingAreas2D() {
+ if (_hasDirtyFlag(DirtyFlags.DirtyRingAreas2D)) {
+ int pathCount = getPathCount();
+
+ if (m_cachedRingAreas2D == null)
+ m_cachedRingAreas2D = new AttributeStreamOfDbl(pathCount);
+ else if (m_cachedRingAreas2D.size() != pathCount)
+ m_cachedRingAreas2D.resize(pathCount);
+
+ MathUtils.KahanSummator totalArea = new MathUtils.KahanSummator(0);
+ MathUtils.KahanSummator pathArea = new MathUtils.KahanSummator(0);
+ Point2D pt = new Point2D();
+ int ipath = 0;
+ SegmentIteratorImpl segIter = querySegmentIterator();
+ while (segIter.nextPath()) {
+ pathArea.reset();
+ getXY(getPathStart(segIter.getPathIndex()), pt);// get the area
+ // calculation
+ // origin to be
+ // the origin of
+ // the ring.
+ while (segIter.hasNextSegment()) {
+ pathArea.add(segIter.nextSegment()._calculateArea2DHelper(
+ pt.x, pt.y));
+ }
+
+ totalArea.add(pathArea.getResult());
+
+ int i = ipath++;
+ m_cachedRingAreas2D.write(i, pathArea.getResult());
+ }
+
+ m_cachedArea2D = totalArea.getResult();
+ _setDirtyFlag(DirtyFlags.DirtyRingAreas2D, false);
+ }
+ }
+
+ int getOGCPolygonCount() {
+ if (!m_bPolygon)
+ return 0;
+
+ _updateOGCFlags();
+
+ int polygonCount = 0;
+ int partCount = getPathCount();
+ for (int ipart = 0; ipart < partCount; ipart++) {
+ if (((int) m_pathFlags.read(ipart) & (int) PathFlags.enumOGCStartPolygon) != 0)
+ polygonCount++;
+ }
+
+ return polygonCount;
+ }
+
+ protected void _updateOGCFlags() {
+ if (_hasDirtyFlag(DirtyFlags.DirtyOGCFlags)) {
+ _updateRingAreas2D();
+
+ int pathCount = getPathCount();
+ if (pathCount > 0 && (m_pathFlags == null || m_pathFlags.size() < pathCount))
+ m_pathFlags = (AttributeStreamOfInt8) AttributeStreamBase
+ .createByteStream(pathCount + 1);
+
+ int firstSign = 1;
+ for (int ipath = 0; ipath < pathCount; ipath++) {
+ double area = m_cachedRingAreas2D.read(ipath);
+ if (ipath == 0)
+ firstSign = area > 0 ? 1 : -1;
+ if (area * firstSign > 0.0)
+ m_pathFlags.setBits(ipath,
+ (byte) PathFlags.enumOGCStartPolygon);
+ else
+ m_pathFlags.clearBits(ipath,
+ (byte) PathFlags.enumOGCStartPolygon);
+ }
+ _setDirtyFlag(DirtyFlags.DirtyOGCFlags, false);
+ }
+ }
+
+ public int getPathIndexFromPointIndex(int pointIndex) {
+ int positionHint = m_currentPathIndex;// in case of multithreading
+ // thiswould simply produce an
+ // invalid value
+ int pathCount = getPathCount();
+
+ // Try using the hint position first to get the path index.
+ if (positionHint >= 0 && positionHint < pathCount) {
+ if (pointIndex < getPathEnd(positionHint)) {
+ if (pointIndex >= getPathStart(positionHint))
+ return positionHint;
+ positionHint--;
+ } else {
+ positionHint++;
+ }
+
+ if (positionHint >= 0 && positionHint < pathCount) {
+ if (pointIndex >= getPathStart(positionHint)
+ && pointIndex < getPathEnd(positionHint)) {
+ m_currentPathIndex = positionHint;
+ return positionHint;
+ }
+ }
+ }
+
+ if (pathCount < 5) {// TODO: time the performance to choose when to use
+ // linear search.
+ for (int i = 0; i < pathCount; i++) {
+ if (pointIndex < getPathEnd(i)) {
+ m_currentPathIndex = i;
+ return i;
+ }
+ }
+ throw new GeometryException("corrupted geometry");
+ }
+
+ // Do binary search:
+ int minPathIndex = 0;
+ int maxPathIndex = pathCount - 1;
+ while (maxPathIndex > minPathIndex) {
+ int mid = minPathIndex + ((maxPathIndex - minPathIndex) >> 1);
+ int pathStart = getPathStart(mid);
+ if (pointIndex < pathStart)
+ maxPathIndex = mid - 1;
+ else {
+ int pathEnd = getPathEnd(mid);
+ if (pointIndex >= pathEnd)
+ minPathIndex = mid + 1;
+ else {
+ m_currentPathIndex = mid;
+ return mid;
+ }
+ }
+ }
+
+ m_currentPathIndex = minPathIndex;
+ return minPathIndex;
+ }
+
+ int getHighestPointIndex(int path_index) {
+ assert (path_index >= 0 && path_index < getPathCount());
+
+ AttributeStreamOfDbl position = (AttributeStreamOfDbl) (getAttributeStreamRef(VertexDescription.Semantics.POSITION));
+ AttributeStreamOfInt32 paths = (AttributeStreamOfInt32) (getPathStreamRef());
+
+ int path_end = getPathEnd(path_index);
+ int path_start = getPathStart(path_index);
+ int max_index = -1;
+ Point2D max_point = new Point2D(), pt = new Point2D();
+ max_point.y = NumberUtils.negativeInf();
+ max_point.x = NumberUtils.negativeInf();
+
+ for (int i = path_start + 0; i < path_end; i++) {
+ position.read(2 * i, pt);
+ if (max_point.compare(pt) == -1) {
+ max_index = i;
+ max_point.setCoords(pt);
+ }
+ }
+
+ return max_index;
+ }
+
+ /**
+ * Returns total segment count in the MultiPathImpl.
+ */
+ public int getSegmentCount() {
+ int segCount = getPointCount();
+ if (!m_bPolygon) {
+ segCount -= getPathCount();
+ for (int i = 0, n = getPathCount(); i < n; i++)
+ if (isClosedPath(i))
+ segCount++;
+ }
+
+ return segCount;
+ }
+
+ public int getSegmentCount(int path_index) {
+ int segCount = getPathSize(path_index);
+ if (!isClosedPath(path_index))
+ segCount--;
+ return segCount;
+ }
+
+ // HEADER defintions
+ @Override
+ public Geometry createInstance() {
+ return new MultiPathImpl(m_bPolygon, getDescription());
+ }
+
+ @Override
+ public int getDimension() {
+ return m_bPolygon ? 2 : 1;
+ }
+
+ @Override
+ public Geometry.Type getType() {
+ return m_bPolygon ? Type.Polygon : Type.Polyline;
+ }
+
+ /**
+ * Returns True if the class is envelope. THis is not an exact method. Only
+ * addEnvelope makes this true.
+ */
+ public boolean isEnvelope() {
+ return !_hasDirtyFlag(DirtyFlags.DirtyIsEnvelope);
+ }
+
+ /**
+ * Returns a reference to the AttributeStream of MultiPathImpl parts
+ * (Paths).
+ *
+ * For the non empty MultiPathImpl, that stream contains start points of the
+ * MultiPathImpl curves. In addition, the last element is the total point
+ * count. The number of vertices in a given part is parts[i + 1] - parts[i].
+ */
+ public AttributeStreamOfInt32 getPathStreamRef() {
+ throwIfEmpty();
+ return m_paths;
+ }
+
+ /**
+ * sets a reference to an AttributeStream of MultiPathImpl paths (Paths).
+ */
+ public void setPathStreamRef(AttributeStreamOfInt32 paths) {
+ m_paths = paths;
+ notifyModified(DirtyFlags.DirtyAll);
+ }
+
+ /**
+ * Returns a reference to the AttributeStream of Segment flags (SegmentFlags
+ * flags). Can be NULL when no non-linear segments are present.
+ *
+ * Segment flags indicate what kind of segment originates (starts) on the
+ * given point. The last vertices of open Path parts has enumNone flag.
+ */
+ public AttributeStreamOfInt8 getSegmentFlagsStreamRef() {
+ throwIfEmpty();
+ return m_segmentFlags;
+ }
+
+ /**
+ * Returns a reference to the AttributeStream of Path flags (PathFlags
+ * flags).
+ *
+ * Each start point of a path has a flag set to indicate if the Path is open
+ * or closed.
+ */
+ public AttributeStreamOfInt8 getPathFlagsStreamRef() {
+ throwIfEmpty();
+ return m_pathFlags;
+ }
+
+ /**
+ * sets a reference to an AttributeStream of Path flags (PathFlags flags).
+ */
+ public void setPathFlagsStreamRef(AttributeStreamOfInt8 pathFlags) {
+ m_pathFlags = pathFlags;
+ notifyModified(DirtyFlags.DirtyAll);
+ }
+
+ public AttributeStreamOfInt32 getSegmentIndexStreamRef() {
+ throwIfEmpty();
+ return m_segmentParamIndex;
+ }
+
+ public AttributeStreamOfDbl getSegmentDataStreamRef() {
+ throwIfEmpty();
+ return m_segmentParams;
+ }
+
+ public int getPathCount() {
+ return (m_paths != null) ? m_paths.size() - 1 : 0;
+ }
+
+ public int getPathEnd(int partIndex) {
+ return m_paths.read(partIndex + 1);
+ }
+
+ public int getPathSize(int partIndex) {
+ return m_paths.read(partIndex + 1) - m_paths.read(partIndex);
+ }
+
+ public int getPathStart(int partIndex) {
+ return m_paths.read(partIndex);
+ }
+
+ @Override
+ public Object _getImpl() {
+ return this;
+ }
+
+ public void setDirtyOGCFlags(boolean bYesNo) {
+ _setDirtyFlag(DirtyFlags.DirtyOGCFlags, bYesNo);
+ }
+
+ public boolean hasDirtyOGCStartFlags() {
+ return _hasDirtyFlag(DirtyFlags.DirtyOGCFlags);
+ }
+
+ public void setDirtyRingAreas2D(boolean bYesNo) {
+ _setDirtyFlag(DirtyFlags.DirtyRingAreas2D, bYesNo);
+ }
+
+ public boolean hasDirtyRingAreas2D() {
+ return _hasDirtyFlag(DirtyFlags.DirtyRingAreas2D);
+ }
+
+ public void setRingAreasStreamRef(AttributeStreamOfDbl ringAreas) {
+ m_cachedRingAreas2D = ringAreas;
+ _setDirtyFlag(DirtyFlags.DirtyRingAreas2D, false);
+ }
+
+ // HEADER defintions
+
+ // // TODO check this against current implementation in native
+ // public void notifyModified(int flags)
+ // {
+ // if(flags == DirtyFlags.DirtyAll)
+ // {
+ // m_reservedPointCount = -1;
+ // _notifyModifiedAllImpl();
+ // }
+ // m_flagsMask |= flags;
+ // _clearAccelerators();
+ //
+ //
+ // // ROHIT's implementation
+ // // if (m_paths == null || 0 == m_paths.size())
+ // // m_pointCount = 0;
+ // // else
+ // // m_pointCount = m_paths.read(m_paths.size() - 1);
+ // //
+ // // super.notifyModified(flags);
+ // }
+
+ @Override
+ public boolean _buildRasterizedGeometryAccelerator(double toleranceXY,
+ GeometryAccelerationDegree accelDegree) {
+ if (m_accelerators == null)// (!m_accelerators)
+ {
+ m_accelerators = new GeometryAccelerators();
+ }
+
+ int rasterSize = RasterizedGeometry2D
+ .rasterSizeFromAccelerationDegree(accelDegree);
+ RasterizedGeometry2D rgeom = m_accelerators.getRasterizedGeometry();
+ if (rgeom != null) {
+ if (rgeom.getToleranceXY() < toleranceXY
+ || rasterSize > rgeom.getRasterSize()) {
+ m_accelerators._setRasterizedGeometry(null);
+ } else
+ return true;
+ }
+
+ rgeom = RasterizedGeometry2D.create(this, toleranceXY, rasterSize);
+ m_accelerators._setRasterizedGeometry(rgeom);
+ //rgeom.dbgSaveToBitmap("c:/temp/ddd.bmp");
+ return true;
+ }
+
+ @Override
+ public int hashCode() {
+ int hashCode = super.hashCode();
+
+ if (!isEmptyImpl()) {
+ int pathCount = getPathCount();
+
+ if (m_paths != null)
+ m_paths.calculateHashImpl(hashCode, 0, pathCount + 1);
+
+ if (m_pathFlags != null)
+ m_pathFlags.calculateHashImpl(hashCode, 0, pathCount);
+ }
+
+ return hashCode;
+ }
+
+ public byte getSegmentFlags(int ivertex) {
+ if (m_segmentFlags != null)
+ return m_segmentFlags.read(ivertex);
+ else
+ return (byte) SegmentFlags.enumLineSeg;
+ }
+
+ public void getSegment(int startVertexIndex, SegmentBuffer segBuffer,
+ boolean bStripAttributes) {
+ int ipath = getPathIndexFromPointIndex(startVertexIndex);
+ if (startVertexIndex == getPathEnd(ipath) - 1 && !isClosedPath(ipath))
+ throw new GeometryException("index out of bounds");
+
+ _verifyAllStreams();
+ AttributeStreamOfInt8 segFlagStream = getSegmentFlagsStreamRef();
+ int segFlag = SegmentFlags.enumLineSeg;
+ if (segFlagStream != null)
+ segFlag = segFlagStream.read(startVertexIndex)
+ & SegmentFlags.enumSegmentMask;
+
+ switch (segFlag) {
+ case SegmentFlags.enumLineSeg:
+ segBuffer.createLine();
+ break;
+ case SegmentFlags.enumBezierSeg:
+ throw GeometryException.GeometryInternalError();
+ case SegmentFlags.enumArcSeg:
+ throw GeometryException.GeometryInternalError();
+ default:
+ throw GeometryException.GeometryInternalError();
+ }
+
+ Segment currentSegment = segBuffer.get();
+ if (!bStripAttributes)
+ currentSegment.assignVertexDescription(m_description);
+ else
+ currentSegment
+ .assignVertexDescription(VertexDescriptionDesignerImpl
+ .getDefaultDescriptor2D());
+
+ int endVertexIndex;
+ if (startVertexIndex == getPathEnd(ipath) - 1 && isClosedPath(ipath)) {
+ endVertexIndex = getPathStart(ipath);
+ } else
+ endVertexIndex = startVertexIndex + 1;
+
+ Point2D pt = new Point2D();
+ getXY(startVertexIndex, pt);
+ currentSegment.setStartXY(pt);
+ getXY(endVertexIndex, pt);
+ currentSegment.setEndXY(pt);
+
+ if (!bStripAttributes) {
+ for (int i = 1, nattr = m_description.getAttributeCount(); i < nattr; i++) {
+ int semantics = m_description._getSemanticsImpl(i);
+ int ncomp = VertexDescription.getComponentCount(semantics);
+ for (int ord = 0; ord < ncomp; ord++) {
+ double vs = getAttributeAsDbl(semantics, startVertexIndex,
+ ord);
+ currentSegment.setStartAttribute(semantics, ord, vs);
+ double ve = getAttributeAsDbl(semantics, endVertexIndex,
+ ord);
+ currentSegment.setEndAttribute(semantics, ord, ve);
+ }
+ }
+ }
+ }
+
+ void queryPathEnvelope2D(int path_index, Envelope2D envelope) {
+ if (path_index >= getPathCount())
+ throw new IllegalArgumentException();
+
+ if (isEmpty()) {
+ envelope.setEmpty();
+ return;
+ }
+
+ if (hasNonLinearSegments(path_index)) {
+ throw new GeometryException("not implemented");
+ } else {
+ AttributeStreamOfDbl stream = (AttributeStreamOfDbl) getAttributeStreamRef(VertexDescription.Semantics.POSITION);
+ Point2D pt = new Point2D();
+ Envelope2D env = new Envelope2D();
+ env.setEmpty();
+ for (int i = getPathStart(path_index), iend = getPathEnd(path_index); i < iend; i++) {
+ stream.read(2 * i, pt);
+ env.merge(pt);
+ }
+ envelope.setCoords(env);
+ }
+ }
+
+ public void queryLoosePathEnvelope2D(int path_index, Envelope2D envelope) {
+ if (path_index >= getPathCount())
+ throw new IllegalArgumentException();
+
+ if (isEmpty()) {
+ envelope.setEmpty();
+ return;
+ }
+
+ if (hasNonLinearSegments(path_index)) {
+ throw new GeometryException("not implemented");
+ } else {
+ AttributeStreamOfDbl stream = (AttributeStreamOfDbl) getAttributeStreamRef(VertexDescription.Semantics.POSITION);
+ Point2D pt = new Point2D();
+ Envelope2D env = new Envelope2D();
+ env.setEmpty();
+ for (int i = getPathStart(path_index), iend = getPathEnd(path_index); i < iend; i++) {
+ stream.read(2 * i, pt);
+ env.merge(pt);
+ }
+ envelope.setCoords(env);
+ }
+ }
+
+ @Override
+ public boolean _buildQuadTreeAccelerator(GeometryAccelerationDegree d) {
+ if (m_accelerators == null)// (!m_accelerators)
+ {
+ m_accelerators = new GeometryAccelerators();
+ }
+
+ if (d == GeometryAccelerationDegree.enumMild || getPointCount() < 16)
+ return false;
+
+ QuadTreeImpl quad_tree_impl = InternalUtils.buildQuadTree(this);
+ m_accelerators._setQuadTree(quad_tree_impl);
+
+ return true;
+ }
+
+ boolean _buildQuadTreeForPathsAccelerator(GeometryAccelerationDegree degree) {
+ if (m_accelerators == null) {
+ m_accelerators = new GeometryAccelerators();
+ }
+
+ // TODO: when less than two envelopes - no need to this.
+
+ if (m_accelerators.getQuadTreeForPaths() != null)
+ return true;
+
+ m_accelerators._setQuadTreeForPaths(null);
+ QuadTreeImpl quad_tree_impl = InternalUtils.buildQuadTreeForPaths(this);
+ m_accelerators._setQuadTreeForPaths(quad_tree_impl);
+
+ return true;
+ }
+
+ void setFillRule(int rule) {
+ assert (m_bPolygon);
+ m_fill_rule = rule;
+ }
+
+ int getFillRule() {
+ return m_fill_rule;
+ }
+
+ void clearDirtyOGCFlags() {
+ _setDirtyFlag(DirtyFlags.DirtyOGCFlags, false);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/MultiPoint.java b/src/main/java/com/esri/core/geometry/MultiPoint.java
index 43f40642..bcdae5ac 100644
--- a/src/main/java/com/esri/core/geometry/MultiPoint.java
+++ b/src/main/java/com/esri/core/geometry/MultiPoint.java
@@ -35,221 +35,220 @@
* essential characteristic of the point set.
*/
public class MultiPoint extends MultiVertexGeometry implements
- Serializable {
-
- private static final long serialVersionUID = 2L;
-
- private MultiPointImpl m_impl;
-
- /**
- * Creates a new empty multipoint.
- */
- public MultiPoint() {
- m_impl = new MultiPointImpl();
- }
-
- public MultiPoint(VertexDescription description) {
- m_impl = new MultiPointImpl(description);
- }
-
- @Override
- public double getAttributeAsDbl(int semantics, int index, int ordinate) {
- return m_impl.getAttributeAsDbl(semantics, index, ordinate);
- }
-
- @Override
- public int getAttributeAsInt(int semantics, int index, int ordinate) {
- return m_impl.getAttributeAsInt(semantics, index, ordinate);
- }
-
- @Override
- public Point getPoint(int index) {
- return m_impl.getPoint(index);
- }
-
- @Override
- public int getPointCount() {
- return m_impl.getPointCount();
- }
-
- @Override
- public Point2D getXY(int index) {
- return m_impl.getXY(index);
- }
-
- @Override
- public void getXY(int index, Point2D pt) {
- m_impl.getXY(index, pt);
- }
-
- @Override
- Point3D getXYZ(int index) {
- return m_impl.getXYZ(index);
- }
-
- @Override
- public void queryCoordinates(Point2D[] dst) {
- m_impl.queryCoordinates(dst);
- }
-
- @Override
- public void queryCoordinates(Point[] dst) {
- m_impl.queryCoordinates(dst);
- }
-
- @Override
- protected Object _getImpl() {
- return m_impl;
- }
-
- /**
- * Adds a point multipoint.
- *
- * @param point The Point to be added to this multipoint.
- */
- public void add(Point point) {
- m_impl.add(point);
- }
-
- /**
- * Adds a point with the specified X, Y coordinates to this multipoint.
- *
- * @param x The new Point's X coordinate.
- * @param y The new Point's Y coordinate.
- */
- public void add(double x, double y) {
- m_impl.add(x, y);
- }
-
- /**
- * Adds a point with the specified X, Y coordinates to this multipoint.
- *
- * @param pt the point to add
- */
- public void add(Point2D pt) {
- m_impl.add(pt.x, pt.y);
- }
-
- /**
- * Adds a 3DPoint with the specified X, Y, Z coordinates to this multipoint.
- *
- * @param x The new Point's X coordinate.
- * @param y The new Point's Y coordinate.
- * @param z The new Point's Z coordinate.
- */
- void add(double x, double y, double z) {
- m_impl.add(x, y, z);
- }
-
- /**
- * Appends points from another multipoint at the end of this multipoint.
- *
- * @param src The mulitpoint to append to this multipoint.
- * @param srcFrom The start index in the source multipoint from which to start
- * appending points.
- * @param srcTo The end index in the source multipoint right after the last
- * point to be appended. Use -1 to indicate the rest of the
- * source multipoint.
- */
- public void add(MultiVertexGeometry src, int srcFrom, int srcTo) {
- m_impl.add((MultiVertexGeometryImpl) src._getImpl(), srcFrom, srcTo);
- }
-
- void addPoints(Point2D[] points) {
- m_impl.addPoints(points);
- }
-
- void addPoints(Point[] points) {
- m_impl.addPoints(points);
- }
-
- /**
- * Inserts a point to this multipoint.
- *
- * @param beforePointIndex The index right before the new point to insert.
- * @param pt The point to insert.
- */
- public void insertPoint(int beforePointIndex, Point pt) {
- m_impl.insertPoint(beforePointIndex, pt);
- } // inserts a point. The point is connected with Lines
-
- /**
- * Removes a point from this multipoint.
- *
- * @param pointIndex The index of the point to be removed.
- */
- public void removePoint(int pointIndex) {
- m_impl.removePoint(pointIndex);
- }
-
- /**
- * Resizes the multipoint to have the given size.
- *
- * @param pointCount - The number of points in this multipoint.
- */
- public void resize(int pointCount) {
- m_impl.resize(pointCount);
- }
-
- @Override
- void queryCoordinates(Point3D[] dst) {
- m_impl.queryCoordinates(dst);
- }
-
- @Override
- public void setAttribute(int semantics, int index, int ordinate,
- double value) {
- m_impl.setAttribute(semantics, index, ordinate, value);
- }
-
- @Override
- public void setAttribute(int semantics, int index, int ordinate, int value) {
- m_impl.setAttribute(semantics, index, ordinate, value);
- }
-
- @Override
- public void setPoint(int index, Point pointSrc) {
- m_impl.setPoint(index, pointSrc);
- }
-
- @Override
- public void setXY(int index, Point2D pt) {
- m_impl.setXY(index, pt);
- }
-
- @Override
- void setXYZ(int index, Point3D pt) {
- m_impl.setXYZ(index, pt);
- }
-
- @Override
- public void applyTransformation(Transformation2D transform) {
- m_impl.applyTransformation(transform);
- }
-
- @Override
- void applyTransformation(Transformation3D transform) {
- m_impl.applyTransformation(transform);
- }
-
- @Override
- public void copyTo(Geometry dst) {
- m_impl.copyTo((Geometry) dst._getImpl());
- }
-
- @Override
- public Geometry createInstance() {
- return new MultiPoint(getDescription());
- }
-
- @Override
- public int getDimension() {
- return 0;
- }
-
- @Override
- public long estimateMemorySize()
- {
+ Serializable {
+
+ private static final long serialVersionUID = 2L;
+
+ private MultiPointImpl m_impl;
+
+ /**
+ * Creates a new empty multipoint.
+ */
+ public MultiPoint() {
+ m_impl = new MultiPointImpl();
+ }
+
+ public MultiPoint(VertexDescription description) {
+ m_impl = new MultiPointImpl(description);
+ }
+
+ @Override
+ public double getAttributeAsDbl(int semantics, int index, int ordinate) {
+ return m_impl.getAttributeAsDbl(semantics, index, ordinate);
+ }
+
+ @Override
+ public int getAttributeAsInt(int semantics, int index, int ordinate) {
+ return m_impl.getAttributeAsInt(semantics, index, ordinate);
+ }
+
+ @Override
+ public Point getPoint(int index) {
+ return m_impl.getPoint(index);
+ }
+
+ @Override
+ public int getPointCount() {
+ return m_impl.getPointCount();
+ }
+
+ @Override
+ public Point2D getXY(int index) {
+ return m_impl.getXY(index);
+ }
+
+ @Override
+ public void getXY(int index, Point2D pt) {
+ m_impl.getXY(index, pt);
+ }
+
+ @Override
+ Point3D getXYZ(int index) {
+ return m_impl.getXYZ(index);
+ }
+
+ @Override
+ public void queryCoordinates(Point2D[] dst) {
+ m_impl.queryCoordinates(dst);
+ }
+
+ @Override
+ public void queryCoordinates(Point[] dst) {
+ m_impl.queryCoordinates(dst);
+ }
+
+ @Override
+ protected Object _getImpl() {
+ return m_impl;
+ }
+
+ /**
+ * Adds a point multipoint.
+ *
+ * @param point The Point to be added to this multipoint.
+ */
+ public void add(Point point) {
+ m_impl.add(point);
+ }
+
+ /**
+ * Adds a point with the specified X, Y coordinates to this multipoint.
+ *
+ * @param x The new Point's X coordinate.
+ * @param y The new Point's Y coordinate.
+ */
+ public void add(double x, double y) {
+ m_impl.add(x, y);
+ }
+
+ /**
+ * Adds a point with the specified X, Y coordinates to this multipoint.
+ *
+ * @param pt the point to add
+ */
+ public void add(Point2D pt) {
+ m_impl.add(pt.x, pt.y);
+ }
+
+ /**
+ * Adds a 3DPoint with the specified X, Y, Z coordinates to this multipoint.
+ *
+ * @param x The new Point's X coordinate.
+ * @param y The new Point's Y coordinate.
+ * @param z The new Point's Z coordinate.
+ */
+ void add(double x, double y, double z) {
+ m_impl.add(x, y, z);
+ }
+
+ /**
+ * Appends points from another multipoint at the end of this multipoint.
+ *
+ * @param src The mulitpoint to append to this multipoint.
+ * @param srcFrom The start index in the source multipoint from which to start
+ * appending points.
+ * @param srcTo The end index in the source multipoint right after the last
+ * point to be appended. Use -1 to indicate the rest of the
+ * source multipoint.
+ */
+ public void add(MultiVertexGeometry src, int srcFrom, int srcTo) {
+ m_impl.add((MultiVertexGeometryImpl) src._getImpl(), srcFrom, srcTo);
+ }
+
+ void addPoints(Point2D[] points) {
+ m_impl.addPoints(points);
+ }
+
+ void addPoints(Point[] points) {
+ m_impl.addPoints(points);
+ }
+
+ /**
+ * Inserts a point to this multipoint.
+ *
+ * @param beforePointIndex The index right before the new point to insert.
+ * @param pt The point to insert.
+ */
+ public void insertPoint(int beforePointIndex, Point pt) {
+ m_impl.insertPoint(beforePointIndex, pt);
+ } // inserts a point. The point is connected with Lines
+
+ /**
+ * Removes a point from this multipoint.
+ *
+ * @param pointIndex The index of the point to be removed.
+ */
+ public void removePoint(int pointIndex) {
+ m_impl.removePoint(pointIndex);
+ }
+
+ /**
+ * Resizes the multipoint to have the given size.
+ *
+ * @param pointCount - The number of points in this multipoint.
+ */
+ public void resize(int pointCount) {
+ m_impl.resize(pointCount);
+ }
+
+ @Override
+ void queryCoordinates(Point3D[] dst) {
+ m_impl.queryCoordinates(dst);
+ }
+
+ @Override
+ public void setAttribute(int semantics, int index, int ordinate,
+ double value) {
+ m_impl.setAttribute(semantics, index, ordinate, value);
+ }
+
+ @Override
+ public void setAttribute(int semantics, int index, int ordinate, int value) {
+ m_impl.setAttribute(semantics, index, ordinate, value);
+ }
+
+ @Override
+ public void setPoint(int index, Point pointSrc) {
+ m_impl.setPoint(index, pointSrc);
+ }
+
+ @Override
+ public void setXY(int index, Point2D pt) {
+ m_impl.setXY(index, pt);
+ }
+
+ @Override
+ void setXYZ(int index, Point3D pt) {
+ m_impl.setXYZ(index, pt);
+ }
+
+ @Override
+ public void applyTransformation(Transformation2D transform) {
+ m_impl.applyTransformation(transform);
+ }
+
+ @Override
+ void applyTransformation(Transformation3D transform) {
+ m_impl.applyTransformation(transform);
+ }
+
+ @Override
+ public void copyTo(Geometry dst) {
+ m_impl.copyTo((Geometry) dst._getImpl());
+ }
+
+ @Override
+ public Geometry createInstance() {
+ return new MultiPoint(getDescription());
+ }
+
+ @Override
+ public int getDimension() {
+ return 0;
+ }
+
+ @Override
+ public long estimateMemorySize() {
return SIZE_OF_MULTI_POINT + m_impl.estimateMemorySize();
}
@@ -258,119 +257,119 @@ public Geometry.Type getType() {
return Type.MultiPoint;
}
- @Override
- public VertexDescription getDescription() {
- return m_impl.getDescription();
- }
-
- @Override
- public void addAttribute(int semantics) {
- m_impl.addAttribute(semantics);
- }
-
- @Override
- public void assignVertexDescription(VertexDescription src) {
- m_impl.assignVertexDescription(src);
- }
-
- @Override
- public void dropAllAttributes() {
- m_impl.dropAllAttributes();
- }
-
- @Override
- public void dropAttribute(int semantics) {
- m_impl.dropAttribute(semantics);
- }
-
- @Override
- public void mergeVertexDescription(VertexDescription src) {
- m_impl.mergeVertexDescription(src);
- }
-
- @Override
- public boolean isEmpty() {
- return m_impl.isEmpty();
- }
-
- @Override
- public void queryEnvelope(Envelope env) {
- m_impl.queryEnvelope(env);
- }
-
- @Override
- public void queryEnvelope2D(Envelope2D env) {
- m_impl.queryEnvelope2D(env);
- }
-
- @Override
- void queryEnvelope3D(Envelope3D env) {
- m_impl.queryEnvelope3D(env);
- }
-
- @Override
- public Envelope1D queryInterval(int semantics, int ordinate) {
- return m_impl.queryInterval(semantics, ordinate);
- }
-
- @Override
- public void setEmpty() {
- m_impl.setEmpty();
- }
-
- /**
- * Returns TRUE when this geometry has exactly same type, properties, and
- * coordinates as the other geometry.
- */
- @Override
- public boolean equals(Object other) {
- if (other == null)
- return false;
-
- if (other == this)
- return true;
-
- if (other.getClass() != getClass())
- return false;
-
- return m_impl.equals(((MultiPoint) other)._getImpl());
- }
-
- /**
- * Returns a hash code value for this multipoint.
- */
- @Override
- public int hashCode() {
- return m_impl.hashCode();
- }
-
- int queryCoordinates(Point2D[] dst, int dstSize, int beginIndex,
- int endIndex) {
- return m_impl.queryCoordinates(dst, dstSize, beginIndex, endIndex);
- }
-
- @Override
- public void getPointByVal(int index, Point outPoint) {
- m_impl.getPointByVal(index, outPoint);
- }
-
- @Override
- public void setPointByVal(int index, Point pointSrc) {
- m_impl.setPointByVal(index, pointSrc);
- }
-
- @Override
- public int getStateFlag() {
- return m_impl.getStateFlag();
- }
-
- @Override
- public Geometry getBoundary() {
- return m_impl.getBoundary();
- }
-
- @Override
- public void replaceNaNs(int semantics, double value) {
- m_impl.replaceNaNs(semantics, value);
- }
+ @Override
+ public VertexDescription getDescription() {
+ return m_impl.getDescription();
+ }
+
+ @Override
+ public void addAttribute(int semantics) {
+ m_impl.addAttribute(semantics);
+ }
+
+ @Override
+ public void assignVertexDescription(VertexDescription src) {
+ m_impl.assignVertexDescription(src);
+ }
+
+ @Override
+ public void dropAllAttributes() {
+ m_impl.dropAllAttributes();
+ }
+
+ @Override
+ public void dropAttribute(int semantics) {
+ m_impl.dropAttribute(semantics);
+ }
+
+ @Override
+ public void mergeVertexDescription(VertexDescription src) {
+ m_impl.mergeVertexDescription(src);
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return m_impl.isEmpty();
+ }
+
+ @Override
+ public void queryEnvelope(Envelope env) {
+ m_impl.queryEnvelope(env);
+ }
+
+ @Override
+ public void queryEnvelope2D(Envelope2D env) {
+ m_impl.queryEnvelope2D(env);
+ }
+
+ @Override
+ void queryEnvelope3D(Envelope3D env) {
+ m_impl.queryEnvelope3D(env);
+ }
+
+ @Override
+ public Envelope1D queryInterval(int semantics, int ordinate) {
+ return m_impl.queryInterval(semantics, ordinate);
+ }
+
+ @Override
+ public void setEmpty() {
+ m_impl.setEmpty();
+ }
+
+ /**
+ * Returns TRUE when this geometry has exactly same type, properties, and
+ * coordinates as the other geometry.
+ */
+ @Override
+ public boolean equals(Object other) {
+ if (other == null)
+ return false;
+
+ if (other == this)
+ return true;
+
+ if (other.getClass() != getClass())
+ return false;
+
+ return m_impl.equals(((MultiPoint) other)._getImpl());
+ }
+
+ /**
+ * Returns a hash code value for this multipoint.
+ */
+ @Override
+ public int hashCode() {
+ return m_impl.hashCode();
+ }
+
+ int queryCoordinates(Point2D[] dst, int dstSize, int beginIndex,
+ int endIndex) {
+ return m_impl.queryCoordinates(dst, dstSize, beginIndex, endIndex);
+ }
+
+ @Override
+ public void getPointByVal(int index, Point outPoint) {
+ m_impl.getPointByVal(index, outPoint);
+ }
+
+ @Override
+ public void setPointByVal(int index, Point pointSrc) {
+ m_impl.setPointByVal(index, pointSrc);
+ }
+
+ @Override
+ public int getStateFlag() {
+ return m_impl.getStateFlag();
+ }
+
+ @Override
+ public Geometry getBoundary() {
+ return m_impl.getBoundary();
+ }
+
+ @Override
+ public void replaceNaNs(int semantics, double value) {
+ m_impl.replaceNaNs(semantics, value);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/MultiPointImpl.java b/src/main/java/com/esri/core/geometry/MultiPointImpl.java
index 0825b86e..4e401a8f 100644
--- a/src/main/java/com/esri/core/geometry/MultiPointImpl.java
+++ b/src/main/java/com/esri/core/geometry/MultiPointImpl.java
@@ -33,224 +33,223 @@
*/
final class MultiPointImpl extends MultiVertexGeometryImpl {
- public MultiPointImpl() {
- super();
- m_description = VertexDescriptionDesignerImpl.getDefaultDescriptor2D();
- m_pointCount = 0;
- }
-
- public MultiPointImpl(VertexDescription description) {
- super();
- if (description == null)
- throw new IllegalArgumentException();
-
- m_description = description;
- m_pointCount = 0;
- }
-
- @Override
- public Geometry createInstance() {
- return new MultiPoint(m_description);
- }
-
- /**
- * Adds a Point to this MultiPoint.
- */
- public void add(Point point) {
- resize(m_pointCount + 1);
- setPoint(m_pointCount - 1, point);
- }
-
- /**
- * Adds a Point to this MultiPoint with given x, y coordinates.
- */
- public void add(double x, double y) {
- resize(m_pointCount + 1);
- Point2D pt = new Point2D();
- pt.setCoords(x, y);
- setXY(m_pointCount - 1, pt);
- }
-
- /**
- * Adds a Point to this MultiPoint with given x, y, z coordinates.
- */
- public void add(double x, double y, double z) {
- resize(m_pointCount + 1);
- Point3D pt = new Point3D();
- pt.setCoords(x, y, z);
- setXYZ(m_pointCount - 1, pt);
- }
-
- /**
- * Appends points from another MultiVertexGeometryImpl at the end of this
- * one.
- *
- * @param src The source MultiVertexGeometryImpl
- */
- public void add(MultiVertexGeometryImpl src, int beginIndex, int endIndex) {
- int endIndexC = endIndex < 0 ? src.getPointCount() : endIndex;
- if (beginIndex < 0 || beginIndex > src.getPointCount()
- || endIndexC < beginIndex)
- throw new IllegalArgumentException();
-
- if (beginIndex == endIndexC)
- return;
-
- mergeVertexDescription(src.getDescription());
- int count = endIndexC - beginIndex;
- int oldPointCount = m_pointCount;
- resize(m_pointCount + count);
- _verifyAllStreams();
- for (int iattrib = 0, nattrib = src.getDescription()
- .getAttributeCount(); iattrib < nattrib; iattrib++) {
- int semantics = src.getDescription()._getSemanticsImpl(iattrib);
- int ncomps = VertexDescription.getComponentCount(semantics);
- AttributeStreamBase stream = getAttributeStreamRef(semantics);
- AttributeStreamBase srcStream = src
- .getAttributeStreamRef(semantics);
- stream.insertRange(oldPointCount * ncomps, srcStream, beginIndex
- * ncomps, count * ncomps, true, 1, oldPointCount * ncomps);
- }
- }
-
- public void addPoints(Point2D[] points) {
- int count = points.length;
- int oldPointCount = m_pointCount;
- resize(m_pointCount + count);
- for (int i = 0; i < count; i++)
- setXY(oldPointCount + i, points[i]);
- }
-
- public void insertPoint(int beforePointIndex, Point pt) {
- if (beforePointIndex > getPointCount())
- throw new GeometryException("index out of bounds");
-
- if (beforePointIndex < 0)
- beforePointIndex = getPointCount();
-
- mergeVertexDescription(pt.getDescription());
- int oldPointCount = m_pointCount;
- _resizeImpl(m_pointCount + 1);
- _verifyAllStreams();
-
- for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
- int semantics = m_description._getSemanticsImpl(iattr);
- int comp = VertexDescription.getComponentCount(semantics);
-
- AttributeStreamBase stream = AttributeStreamBase
- .createAttributeStreamWithSemantics(semantics, 1);
- if (pt.hasAttribute(semantics)) {
- m_vertexAttributes[iattr]
- .insertAttributes(comp * beforePointIndex, pt,
- semantics, comp * oldPointCount);
- } else {
- // Need to make room for the attribute, so we copy a default
- // value in
-
- double v = VertexDescription.getDefaultValue(semantics);
- m_vertexAttributes[iattr].insertRange(comp * beforePointIndex,
- v, comp, comp * oldPointCount);
- }
- }
-
- notifyModified(DirtyFlags.DirtyCoordinates);
- }
-
- void removePoint(int pointIndex) {
- if (pointIndex < 0 || pointIndex >= getPointCount())
- throw new GeometryException("index out of bounds");
-
- _verifyAllStreams();
-
- // Remove the attribute value for the path
- for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
- if (m_vertexAttributes[iattr] != null) {
- int semantics = m_description._getSemanticsImpl(iattr);
- int comp = VertexDescription.getComponentCount(semantics);
- m_vertexAttributes[iattr].eraseRange(comp * pointIndex, comp,
- comp * m_pointCount);
- }
- }
-
- m_pointCount--;
- m_reservedPointCount--;
- notifyModified(DirtyFlags.DirtyCoordinates);
- }
-
- /**
- * Resizes the MultiPoint to have the given size.
- */
- public void resize(int pointCount) {
- _resizeImpl(pointCount);
- }
-
- @Override
- void _copyToImpl(MultiVertexGeometryImpl mvg) {
- }
-
- @Override
- public void setEmpty() {
- super._setEmptyImpl();
- }
-
- @Override
- public void applyTransformation(Transformation2D transform) {
- if (isEmpty())
- return;
-
- _verifyAllStreams();
- AttributeStreamOfDbl points = (AttributeStreamOfDbl) m_vertexAttributes[0];
- Point2D pt2 = new Point2D();
-
- for (int ipoint = 0; ipoint < m_pointCount; ipoint++) {
- pt2.x = points.read(ipoint * 2);
- pt2.y = points.read(ipoint * 2 + 1);
-
- transform.transform(pt2, pt2);
- points.write(ipoint * 2, pt2.x);
- points.write(ipoint * 2 + 1, pt2.y);
- }
-
- // REFACTOR: reset the exact envelope only and transform the loose
- // envelope
- notifyModified(DirtyFlags.DirtyCoordinates);
- }
-
- @Override
- void applyTransformation(Transformation3D transform) {
- if (isEmpty())
- return;
-
- _verifyAllStreams();
- addAttribute(Semantics.Z);
- _verifyAllStreams();
- AttributeStreamOfDbl points = (AttributeStreamOfDbl) m_vertexAttributes[0];
- AttributeStreamOfDbl zs = (AttributeStreamOfDbl) m_vertexAttributes[1];
- Point3D pt3 = new Point3D();
- for (int ipoint = 0; ipoint < m_pointCount; ipoint++) {
- pt3.x = points.read(ipoint * 2);
- pt3.y = points.read(ipoint * 2 + 1);
- pt3.z = zs.read(ipoint);
-
- Point3D res = transform.transform(pt3);
- points.write(ipoint * 2, res.x);
- points.write(ipoint * 2 + 1, res.y);
- zs.write(ipoint, res.z);
- }
-
- // REFACTOR: reset the exact envelope only and transform the loose
- // envelope
- notifyModified(DirtyFlags.DirtyCoordinates);
- }
-
- @Override
- public int getDimension() {
- return 0;
- }
+ public MultiPointImpl() {
+ super();
+ m_description = VertexDescriptionDesignerImpl.getDefaultDescriptor2D();
+ m_pointCount = 0;
+ }
+
+ public MultiPointImpl(VertexDescription description) {
+ super();
+ if (description == null)
+ throw new IllegalArgumentException();
+
+ m_description = description;
+ m_pointCount = 0;
+ }
+
+ @Override
+ public Geometry createInstance() {
+ return new MultiPoint(m_description);
+ }
+
+ /**
+ * Adds a Point to this MultiPoint.
+ */
+ public void add(Point point) {
+ resize(m_pointCount + 1);
+ setPoint(m_pointCount - 1, point);
+ }
+
+ /**
+ * Adds a Point to this MultiPoint with given x, y coordinates.
+ */
+ public void add(double x, double y) {
+ resize(m_pointCount + 1);
+ Point2D pt = new Point2D();
+ pt.setCoords(x, y);
+ setXY(m_pointCount - 1, pt);
+ }
+
+ /**
+ * Adds a Point to this MultiPoint with given x, y, z coordinates.
+ */
+ public void add(double x, double y, double z) {
+ resize(m_pointCount + 1);
+ Point3D pt = new Point3D();
+ pt.setCoords(x, y, z);
+ setXYZ(m_pointCount - 1, pt);
+ }
+
+ /**
+ * Appends points from another MultiVertexGeometryImpl at the end of this
+ * one.
+ *
+ * @param src The source MultiVertexGeometryImpl
+ */
+ public void add(MultiVertexGeometryImpl src, int beginIndex, int endIndex) {
+ int endIndexC = endIndex < 0 ? src.getPointCount() : endIndex;
+ if (beginIndex < 0 || beginIndex > src.getPointCount()
+ || endIndexC < beginIndex)
+ throw new IllegalArgumentException();
+
+ if (beginIndex == endIndexC)
+ return;
+
+ mergeVertexDescription(src.getDescription());
+ int count = endIndexC - beginIndex;
+ int oldPointCount = m_pointCount;
+ resize(m_pointCount + count);
+ _verifyAllStreams();
+ for (int iattrib = 0, nattrib = src.getDescription()
+ .getAttributeCount(); iattrib < nattrib; iattrib++) {
+ int semantics = src.getDescription()._getSemanticsImpl(iattrib);
+ int ncomps = VertexDescription.getComponentCount(semantics);
+ AttributeStreamBase stream = getAttributeStreamRef(semantics);
+ AttributeStreamBase srcStream = src
+ .getAttributeStreamRef(semantics);
+ stream.insertRange(oldPointCount * ncomps, srcStream, beginIndex
+ * ncomps, count * ncomps, true, 1, oldPointCount * ncomps);
+ }
+ }
+
+ public void addPoints(Point2D[] points) {
+ int count = points.length;
+ int oldPointCount = m_pointCount;
+ resize(m_pointCount + count);
+ for (int i = 0; i < count; i++)
+ setXY(oldPointCount + i, points[i]);
+ }
+
+ public void insertPoint(int beforePointIndex, Point pt) {
+ if (beforePointIndex > getPointCount())
+ throw new GeometryException("index out of bounds");
+
+ if (beforePointIndex < 0)
+ beforePointIndex = getPointCount();
+
+ mergeVertexDescription(pt.getDescription());
+ int oldPointCount = m_pointCount;
+ _resizeImpl(m_pointCount + 1);
+ _verifyAllStreams();
+
+ for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
+ int semantics = m_description._getSemanticsImpl(iattr);
+ int comp = VertexDescription.getComponentCount(semantics);
+
+ AttributeStreamBase stream = AttributeStreamBase
+ .createAttributeStreamWithSemantics(semantics, 1);
+ if (pt.hasAttribute(semantics)) {
+ m_vertexAttributes[iattr]
+ .insertAttributes(comp * beforePointIndex, pt,
+ semantics, comp * oldPointCount);
+ } else {
+ // Need to make room for the attribute, so we copy a default
+ // value in
+
+ double v = VertexDescription.getDefaultValue(semantics);
+ m_vertexAttributes[iattr].insertRange(comp * beforePointIndex,
+ v, comp, comp * oldPointCount);
+ }
+ }
+
+ notifyModified(DirtyFlags.DirtyCoordinates);
+ }
+
+ void removePoint(int pointIndex) {
+ if (pointIndex < 0 || pointIndex >= getPointCount())
+ throw new GeometryException("index out of bounds");
+
+ _verifyAllStreams();
+
+ // Remove the attribute value for the path
+ for (int iattr = 0, nattr = m_description.getAttributeCount(); iattr < nattr; iattr++) {
+ if (m_vertexAttributes[iattr] != null) {
+ int semantics = m_description._getSemanticsImpl(iattr);
+ int comp = VertexDescription.getComponentCount(semantics);
+ m_vertexAttributes[iattr].eraseRange(comp * pointIndex, comp,
+ comp * m_pointCount);
+ }
+ }
+
+ m_pointCount--;
+ m_reservedPointCount--;
+ notifyModified(DirtyFlags.DirtyCoordinates);
+ }
+
+ /**
+ * Resizes the MultiPoint to have the given size.
+ */
+ public void resize(int pointCount) {
+ _resizeImpl(pointCount);
+ }
+
+ @Override
+ void _copyToImpl(MultiVertexGeometryImpl mvg) {
+ }
+
+ @Override
+ public void setEmpty() {
+ super._setEmptyImpl();
+ }
+
+ @Override
+ public void applyTransformation(Transformation2D transform) {
+ if (isEmpty())
+ return;
+
+ _verifyAllStreams();
+ AttributeStreamOfDbl points = (AttributeStreamOfDbl) m_vertexAttributes[0];
+ Point2D pt2 = new Point2D();
+
+ for (int ipoint = 0; ipoint < m_pointCount; ipoint++) {
+ pt2.x = points.read(ipoint * 2);
+ pt2.y = points.read(ipoint * 2 + 1);
+
+ transform.transform(pt2, pt2);
+ points.write(ipoint * 2, pt2.x);
+ points.write(ipoint * 2 + 1, pt2.y);
+ }
+
+ // REFACTOR: reset the exact envelope only and transform the loose
+ // envelope
+ notifyModified(DirtyFlags.DirtyCoordinates);
+ }
@Override
- public long estimateMemorySize()
- {
+ void applyTransformation(Transformation3D transform) {
+ if (isEmpty())
+ return;
+
+ _verifyAllStreams();
+ addAttribute(Semantics.Z);
+ _verifyAllStreams();
+ AttributeStreamOfDbl points = (AttributeStreamOfDbl) m_vertexAttributes[0];
+ AttributeStreamOfDbl zs = (AttributeStreamOfDbl) m_vertexAttributes[1];
+ Point3D pt3 = new Point3D();
+ for (int ipoint = 0; ipoint < m_pointCount; ipoint++) {
+ pt3.x = points.read(ipoint * 2);
+ pt3.y = points.read(ipoint * 2 + 1);
+ pt3.z = zs.read(ipoint);
+
+ Point3D res = transform.transform(pt3);
+ points.write(ipoint * 2, res.x);
+ points.write(ipoint * 2 + 1, res.y);
+ zs.write(ipoint, res.z);
+ }
+
+ // REFACTOR: reset the exact envelope only and transform the loose
+ // envelope
+ notifyModified(DirtyFlags.DirtyCoordinates);
+ }
+
+ @Override
+ public int getDimension() {
+ return 0;
+ }
+
+ @Override
+ public long estimateMemorySize() {
long size = SIZE_OF_MULTI_POINT_IMPL + (m_envelope != null ? m_envelope.estimateMemorySize() : 0);
if (m_vertexAttributes != null) {
@@ -266,100 +265,100 @@ public Geometry.Type getType() {
return Type.MultiPoint;
}
- @Override
- public double calculateArea2D() {
- return 0;
- }
-
- @Override
- public double calculateLength2D() {
- return 0;
- }
-
- @Override
- public Object _getImpl() {
- return this;
- }
-
- @Override
- public boolean equals(Object other) {
- if (other == this)
- return true;
-
- if (!(other instanceof MultiPointImpl))
- return false;
-
- return super.equals(other);
- }
-
- public void addPoints(Point[] points) {
- int count = points.length;
- // int oldPointCount = m_pointCount;
- resize(m_pointCount + count);
- for (int i = 0; i < count; i++)
- setPoint(i, points[i]);
- }
-
- public int queryCoordinates(Point2D[] dst, int dstSize, int beginIndex,
- int endIndex) {
- int endIndexC = endIndex < 0 ? m_pointCount : endIndex;
- endIndexC = Math.min(endIndexC, beginIndex + dstSize);
-
- if (beginIndex < 0 || beginIndex >= m_pointCount
- || endIndexC < beginIndex || dst.length != dstSize)
- throw new IllegalArgumentException();// GEOMTHROW(invalid_argument);
-
- AttributeStreamOfDbl xy = (AttributeStreamOfDbl) getAttributeStreamRef(VertexDescription.Semantics.POSITION);
- int pointCountToRead = endIndexC - beginIndex;
- double[] dstArray = new double[pointCountToRead * 2];
- xy.readRange(2 * beginIndex, pointCountToRead * 2, dstArray, 0, true);
-
- for (int i = 0; i < pointCountToRead; i++) {
- dst[i] = new Point2D(dstArray[i * 2], dstArray[i * 2 + 1]);
- }
-
- return endIndexC;
- }
-
- @Override
- protected void _notifyModifiedAllImpl() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- protected void _verifyStreamsImpl() {
- // TODO Auto-generated method stub
-
- }
-
- @Override
- public boolean _buildRasterizedGeometryAccelerator(double toleranceXY,
- GeometryAccelerationDegree accelDegree) {
- // TODO Auto-generated method stub
- return false;
- }
-
- @Override
- public boolean _buildQuadTreeAccelerator(GeometryAccelerationDegree accelDegree) {
- // TODO Auto-generated method stub
- return false;
- }
-
- // @Override
- // void _notifyModifiedAllImpl() {
- // // TODO Auto-generated method stub
- //
- // }
-
- // @Override
- // protected void _verifyStreamsImpl() {
- // // TODO Auto-generated method stub
- //
- // }
-
- @Override
- public Geometry getBoundary() {
- return null;
- }
+ @Override
+ public double calculateArea2D() {
+ return 0;
+ }
+
+ @Override
+ public double calculateLength2D() {
+ return 0;
+ }
+
+ @Override
+ public Object _getImpl() {
+ return this;
+ }
+
+ @Override
+ public boolean equals(Object other) {
+ if (other == this)
+ return true;
+
+ if (!(other instanceof MultiPointImpl))
+ return false;
+
+ return super.equals(other);
+ }
+
+ public void addPoints(Point[] points) {
+ int count = points.length;
+ // int oldPointCount = m_pointCount;
+ resize(m_pointCount + count);
+ for (int i = 0; i < count; i++)
+ setPoint(i, points[i]);
+ }
+
+ public int queryCoordinates(Point2D[] dst, int dstSize, int beginIndex,
+ int endIndex) {
+ int endIndexC = endIndex < 0 ? m_pointCount : endIndex;
+ endIndexC = Math.min(endIndexC, beginIndex + dstSize);
+
+ if (beginIndex < 0 || beginIndex >= m_pointCount
+ || endIndexC < beginIndex || dst.length != dstSize)
+ throw new IllegalArgumentException();// GEOMTHROW(invalid_argument);
+
+ AttributeStreamOfDbl xy = (AttributeStreamOfDbl) getAttributeStreamRef(VertexDescription.Semantics.POSITION);
+ int pointCountToRead = endIndexC - beginIndex;
+ double[] dstArray = new double[pointCountToRead * 2];
+ xy.readRange(2 * beginIndex, pointCountToRead * 2, dstArray, 0, true);
+
+ for (int i = 0; i < pointCountToRead; i++) {
+ dst[i] = new Point2D(dstArray[i * 2], dstArray[i * 2 + 1]);
+ }
+
+ return endIndexC;
+ }
+
+ @Override
+ protected void _notifyModifiedAllImpl() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ protected void _verifyStreamsImpl() {
+ // TODO Auto-generated method stub
+
+ }
+
+ @Override
+ public boolean _buildRasterizedGeometryAccelerator(double toleranceXY,
+ GeometryAccelerationDegree accelDegree) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ @Override
+ public boolean _buildQuadTreeAccelerator(GeometryAccelerationDegree accelDegree) {
+ // TODO Auto-generated method stub
+ return false;
+ }
+
+ // @Override
+ // void _notifyModifiedAllImpl() {
+ // // TODO Auto-generated method stub
+ //
+ // }
+
+ // @Override
+ // protected void _verifyStreamsImpl() {
+ // // TODO Auto-generated method stub
+ //
+ // }
+
+ @Override
+ public Geometry getBoundary() {
+ return null;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/MultiVertexGeometry.java b/src/main/java/com/esri/core/geometry/MultiVertexGeometry.java
index 56dca8ce..d3a7b921 100644
--- a/src/main/java/com/esri/core/geometry/MultiVertexGeometry.java
+++ b/src/main/java/com/esri/core/geometry/MultiVertexGeometry.java
@@ -33,173 +33,173 @@
* There are as many arrays as there are attributes in the vertex.
*/
public abstract class MultiVertexGeometry extends Geometry implements
- Serializable {
-
- @Override
- protected void _assignVertexDescriptionImpl(VertexDescription newDescription) {
- throw new GeometryException("invalid call");
- }
-
- /**
- * Returns the total vertex count in this Geometry.
- */
- public abstract int getPointCount();
-
- /**
- * Returns given vertex of the Geometry.
- */
- public abstract Point getPoint(int index);// Java only
-
- /**
- * Returns given vertex of the Geometry by value.
- */
- public void getPoint(int index, Point ptOut) {
- getPointByVal(index, ptOut);
- }
-
- /**
- * Sets the vertex at given index of the Geometry.
- *
- * @param index The index of the vertex being changed.
- * @param pointSrc The Point instance to set given vertex attributes from. The
- * pointSrc can not be empty.
- * If attribute is not present, the default value is returned.
- * See VertexDescription::GetDefaultValue() method.
- */
- abstract double getAttributeAsDbl(int semantics, int index,
- int ordinate);
-
- /**
- * Returns value of the given vertex attribute as int.
- *
- * @param semantics The atribute semantics.
- * @param index is the vertex index in the Geometry.
- * @param ordinate is the ordinate of a vertex attribute (for example, y has
- * ordinate of 1, because it is second ordinate of POSITION)
- *
- * If attribute is not present, the default value is returned.
- * See VertexDescription::GetDefaultValue() method. Avoid using
- * this method on non-integer atributes.
- */
- abstract int getAttributeAsInt(int semantics, int index, int ordinate);
-
- /**
- * Sets the value of given attribute at given posisiotnsis.
- *
- * @param semantics The atribute semantics.
- * @param index is the vertex index in the Geometry.
- * @param ordinate is the ordinate of a vertex attribute (for example, y has
- * ordinate of 1, because it is seond ordinate of POSITION)
- * @param value is the value to set. as well as the number of components of
- * the attribute.
- *
- * If the attribute is not present in this Geometry, it is added.
- */
- abstract void setAttribute(int semantics, int index, int ordinate,
- double value);
-
- /**
- * Same as above, but works with ints. Avoid using this method on
- * non-integer atributes because some double attributes may have NaN default
- * values (e.g. Ms)
- */
- abstract void setAttribute(int semantics, int index, int ordinate,
- int value);
-
- /**
- * Returns given vertex of the Geometry. The outPoint will have same
- * VertexDescription as this Geometry.
- */
- public abstract void getPointByVal(int index, Point outPoint);
-
- /**
- * Sets the vertex at given index of the Geometry.
- *
- * @param index The index of the vertex being changed.
- * @param pointSrc The Point instance to set given vertex attributes from. The
- * pointSrc can not be empty.
+ * If attribute is not present, the default value is returned.
+ * See VertexDescription::GetDefaultValue() method.
+ */
+ abstract double getAttributeAsDbl(int semantics, int index,
+ int ordinate);
+
+ /**
+ * Returns value of the given vertex attribute as int.
+ *
+ * @param semantics The atribute semantics.
+ * @param index is the vertex index in the Geometry.
+ * @param ordinate is the ordinate of a vertex attribute (for example, y has
+ * ordinate of 1, because it is second ordinate of POSITION)
+ *
+ * If attribute is not present, the default value is returned.
+ * See VertexDescription::GetDefaultValue() method. Avoid using
+ * this method on non-integer atributes.
+ */
+ abstract int getAttributeAsInt(int semantics, int index, int ordinate);
+
+ /**
+ * Sets the value of given attribute at given posisiotnsis.
+ *
+ * @param semantics The atribute semantics.
+ * @param index is the vertex index in the Geometry.
+ * @param ordinate is the ordinate of a vertex attribute (for example, y has
+ * ordinate of 1, because it is seond ordinate of POSITION)
+ * @param value is the value to set. as well as the number of components of
+ * the attribute.
+ *
+ * If the attribute is not present in this Geometry, it is added.
+ */
+ abstract void setAttribute(int semantics, int index, int ordinate,
+ double value);
+
+ /**
+ * Same as above, but works with ints. Avoid using this method on
+ * non-integer atributes because some double attributes may have NaN default
+ * values (e.g. Ms)
+ */
+ abstract void setAttribute(int semantics, int index, int ordinate,
+ int value);
+
+ /**
+ * Returns given vertex of the Geometry. The outPoint will have same
+ * VertexDescription as this Geometry.
+ */
+ public abstract void getPointByVal(int index, Point outPoint);
+
+ /**
+ * Sets the vertex at given index of the Geometry.
+ *
+ * @param index The index of the vertex being changed.
+ * @param pointSrc The Point instance to set given vertex attributes from. The
+ * pointSrc can not be empty.
+ *
* The vertex attributes are stored in separate arrays of corresponding type.
* There are as many arrays as there are attributes in the vertex. It uses lazy
* allocation for the vertex attributes. This means, the actual AttributeStream
* is allocated only when the users asks for it, or sets a non-default value.
+ *
*/
abstract class MultiVertexGeometryImpl extends MultiVertexGeometry {
- // HEADER DEFINED
- public interface GeometryXSimple {
- final int Unknown = -1; // not know if simple or not
- final int Not = 0; // not simple
- final int Weak = 1; // weak simple (no self intersections, ring
- // orientation is correct, but ring order is not)
- final int Strong = 2; // same as weak simple + OGC ring order.
- }
-
- // TODO Remove?
-
- /**
- * \internal CHildren implement this method to copy additional information
- */
- abstract void _copyToImpl(MultiVertexGeometryImpl mvg);
-
- protected abstract void _notifyModifiedAllImpl();
-
- /**
- * \internal Called inside of the VerifyAllStreams to get a child class a
- * chance to do additional verify.
- */
- protected abstract void _verifyStreamsImpl();
-
- public interface DirtyFlags {
- public static final int DirtyIsKnownSimple = 1; // !<0 when IsWeakSimple
- // flag is valid
- public static final int IsWeakSimple = 2; // !
- * For Point - returns an empty point.
- * For Multi_point - returns an empty point.
- * For Envelope - returns a polyline, that bounds the envelope.
- * For Polyline - returns a multipoint, using OGC specification (includes path endpoints, using mod 2 rule).
- * For Polygon - returns a polyline that bounds the polygon (adds all rings of the polygon to a polyline).
- */
- abstract public Geometry execute(Geometry geom,
- ProgressTracker progress_tracker);
-
- public static OperatorBoundary local() {
- return (OperatorBoundary) OperatorFactoryLocal.getInstance().getOperator(Type.Boundary);
- }
+ @Override
+ public Type getType() {
+ return Type.Boundary;
+ }
+
+ /**
+ * Calculates the boundary geometry.
+ *
+ * @param geoms The input geometry cursor.
+ * @param progress_tracker The progress tracker, that allows to cancel the lengthy operation.
+ * @return Returns a cursor over boundaries for each geometry.
+ */
+ abstract public GeometryCursor execute(GeometryCursor geoms,
+ ProgressTracker progress_tracker);
+
+ /**
+ * Calculates the boundary.
+ *
+ * @param geom The input geometry.
+ * @param progress_tracker The progress tracker, that allows to cancel the lengthy operation.
+ * @return Returns the boundary.
+ *
+ * For Point - returns an empty point.
+ * For Multi_point - returns an empty point.
+ * For Envelope - returns a polyline, that bounds the envelope.
+ * For Polyline - returns a multipoint, using OGC specification (includes path endpoints, using mod 2 rule).
+ * For Polygon - returns a polyline that bounds the polygon (adds all rings of the polygon to a polyline).
+ */
+ abstract public Geometry execute(Geometry geom,
+ ProgressTracker progress_tracker);
+
+ public static OperatorBoundary local() {
+ return (OperatorBoundary) OperatorFactoryLocal.getInstance().getOperator(Type.Boundary);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorBoundaryLocal.java b/src/main/java/com/esri/core/geometry/OperatorBoundaryLocal.java
index 56d31e11..97a62d8d 100644
--- a/src/main/java/com/esri/core/geometry/OperatorBoundaryLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorBoundaryLocal.java
@@ -25,19 +25,19 @@
class OperatorBoundaryLocal extends OperatorBoundary {
- @Override
- public GeometryCursor execute(GeometryCursor geoms,
- ProgressTracker progressTracker) {
- // TODO Auto-generated method stub
- return new OperatorBoundaryLocalCursor(geoms, progressTracker);
- }
-
- @Override
- public Geometry execute(Geometry geom, ProgressTracker progressTracker) {
- // TODO Auto-generated method stub
- GeometryCursor res = new OperatorBoundaryLocalCursor(
- new SimpleGeometryCursor(geom), progressTracker);
- return res.next();
- }
+ @Override
+ public GeometryCursor execute(GeometryCursor geoms,
+ ProgressTracker progressTracker) {
+ // TODO Auto-generated method stub
+ return new OperatorBoundaryLocalCursor(geoms, progressTracker);
+ }
+
+ @Override
+ public Geometry execute(Geometry geom, ProgressTracker progressTracker) {
+ // TODO Auto-generated method stub
+ GeometryCursor res = new OperatorBoundaryLocalCursor(
+ new SimpleGeometryCursor(geom), progressTracker);
+ return res.next();
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorBoundaryLocalCursor.java b/src/main/java/com/esri/core/geometry/OperatorBoundaryLocalCursor.java
index e2a8ff1c..7518058c 100644
--- a/src/main/java/com/esri/core/geometry/OperatorBoundaryLocalCursor.java
+++ b/src/main/java/com/esri/core/geometry/OperatorBoundaryLocalCursor.java
@@ -24,30 +24,30 @@
package com.esri.core.geometry;
final class OperatorBoundaryLocalCursor extends GeometryCursor {
- ProgressTracker m_progress_tracker;
-
- OperatorBoundaryLocalCursor(GeometryCursor inputGeoms,
- ProgressTracker tracker) {
- m_inputGeoms = inputGeoms;
- m_progress_tracker = tracker;
- }
-
- @Override
- public Geometry next() {
- if (hasNext()) {
- return calculate_boundary(m_inputGeoms.next(), m_progress_tracker);
- }
-
- return null;
- }
-
- private static Geometry calculate_boundary(Geometry geom,
- ProgressTracker progress_tracker) {
- Geometry res = Boundary.calculate(geom, progress_tracker);
- if (res == null)
- return new Point(geom.getDescription());// cannot return null
- else
- return res;
- }
+ ProgressTracker m_progress_tracker;
+
+ OperatorBoundaryLocalCursor(GeometryCursor inputGeoms,
+ ProgressTracker tracker) {
+ m_inputGeoms = inputGeoms;
+ m_progress_tracker = tracker;
+ }
+
+ @Override
+ public Geometry next() {
+ if (hasNext()) {
+ return calculate_boundary(m_inputGeoms.next(), m_progress_tracker);
+ }
+
+ return null;
+ }
+
+ private static Geometry calculate_boundary(Geometry geom,
+ ProgressTracker progress_tracker) {
+ Geometry res = Boundary.calculate(geom, progress_tracker);
+ if (res == null)
+ return new Point(geom.getDescription());// cannot return null
+ else
+ return res;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorBuffer.java b/src/main/java/com/esri/core/geometry/OperatorBuffer.java
index cac9742b..b940420d 100644
--- a/src/main/java/com/esri/core/geometry/OperatorBuffer.java
+++ b/src/main/java/com/esri/core/geometry/OperatorBuffer.java
@@ -30,69 +30,69 @@
* Creates buffer polygons around geometries.
*/
public abstract class OperatorBuffer extends Operator {
- @Override
- public Type getType() {
- return Type.Buffer;
- }
+ @Override
+ public Type getType() {
+ return Type.Buffer;
+ }
- /**
- * Creates a buffer around the input geometries
- *
- * @param inputGeometries The geometries to buffer.
- * @param sr The SpatialReference of the Geometries.
- * @param distances The buffer distances for the Geometries. If the size of the distances array is less than the number of geometries in the inputGeometries, the last distance value is used for the rest of geometries.
- * @param bUnion If True, the buffered geometries will be unioned, otherwise they wont be unioned.
- */
- public abstract GeometryCursor execute(GeometryCursor inputGeometries,
- SpatialReference sr,
- double[] distances,
- boolean bUnion,
- ProgressTracker progressTracker);
+ /**
+ * Creates a buffer around the input geometries
+ *
+ * @param inputGeometries The geometries to buffer.
+ * @param sr The SpatialReference of the Geometries.
+ * @param distances The buffer distances for the Geometries. If the size of the distances array is less than the number of geometries in the inputGeometries, the last distance value is used for the rest of geometries.
+ * @param bUnion If True, the buffered geometries will be unioned, otherwise they wont be unioned.
+ */
+ public abstract GeometryCursor execute(GeometryCursor inputGeometries,
+ SpatialReference sr,
+ double[] distances,
+ boolean bUnion,
+ ProgressTracker progressTracker);
- /**
- * Creates a buffer around the input geometry
- *
- * @param inputGeometry The geometry to buffer.
- * @param sr The SpatialReference of the Geometry.
- * @param distance The buffer distance for the Geometry.
- */
- public abstract Geometry execute(Geometry inputGeometry,
- SpatialReference sr,
- double distance,
- ProgressTracker progressTracker);
+ /**
+ * Creates a buffer around the input geometry
+ *
+ * @param inputGeometry The geometry to buffer.
+ * @param sr The SpatialReference of the Geometry.
+ * @param distance The buffer distance for the Geometry.
+ */
+ public abstract Geometry execute(Geometry inputGeometry,
+ SpatialReference sr,
+ double distance,
+ ProgressTracker progressTracker);
- /**
- * Creates a buffer around the input geometries
- *
- * @param input_geometries The geometries to buffer.
- * @param sr The Spatial_reference of the Geometries. It is used to obtain the tolerance. Can be null.
- * @param distances The buffer distances for the Geometries. If the size of the distances array is less than the number of geometries in the input_geometries, the last distance value is used for the rest of geometries.
- * @param max_deviation The max deviation of the result buffer from the true buffer in the units of the sr.
- * When max_deviation is NaN or 0, it is replaced with 1e-5 * abs(distance).
- * When max_deviation is larger than MIN = 0.5 * abs(distance), it is replaced with MIN. See below for more information.
- * @param max_vertices_in_full_circle The maximum number of vertices in polygon produced from a buffered point. A value of 96 is used in methods that do not accept max_vertices_in_full_circle.
- * If the value is less than MIN=12, it is set to MIN. See below for more information.
- * @param b_union If True, the buffered geometries will be unioned, otherwise they wont be unioned.
- * @param progress_tracker The progress tracker that allows to cancel the operation. Pass null if not needed.
- *
- * The max_deviation and max_vertices_in_full_circle control the quality of round joins in the buffer. That is, the precision of the buffer is max_deviation unless
- * the number of required vertices is too large.
- * The max_vertices_in_full_circle controls how many vertices can be in each round join in the buffer. It is approximately equal to the number of vertices in the polygon around a
- * buffered point. It has a priority over max_deviation. The max deviation is the distance from the result polygon to a true buffer.
- * The real deviation is calculated as the max(max_deviation, abs(distance) * (1 - cos(PI / max_vertex_in_complete_circle))).
- *
- * Note that max_deviation can be exceeded because geometry is generalized with 0.25 * real_deviation, also input segments closer than 0.25 * real_deviation are
- * snapped to a point.
- */
- public abstract GeometryCursor execute(GeometryCursor input_geometries,
- SpatialReference sr,
- double[] distances,
- double max_deviation,
- int max_vertices_in_full_circle,
- boolean b_union,
- ProgressTracker progress_tracker);
+ /**
+ * Creates a buffer around the input geometries
+ *
+ * @param input_geometries The geometries to buffer.
+ * @param sr The Spatial_reference of the Geometries. It is used to obtain the tolerance. Can be null.
+ * @param distances The buffer distances for the Geometries. If the size of the distances array is less than the number of geometries in the input_geometries, the last distance value is used for the rest of geometries.
+ * @param max_deviation The max deviation of the result buffer from the true buffer in the units of the sr.
+ * When max_deviation is NaN or 0, it is replaced with 1e-5 * abs(distance).
+ * When max_deviation is larger than MIN = 0.5 * abs(distance), it is replaced with MIN. See below for more information.
+ * @param max_vertices_in_full_circle The maximum number of vertices in polygon produced from a buffered point. A value of 96 is used in methods that do not accept max_vertices_in_full_circle.
+ * If the value is less than MIN=12, it is set to MIN. See below for more information.
+ * @param b_union If True, the buffered geometries will be unioned, otherwise they wont be unioned.
+ * @param progress_tracker The progress tracker that allows to cancel the operation. Pass null if not needed.
+ *
+ * The max_deviation and max_vertices_in_full_circle control the quality of round joins in the buffer. That is, the precision of the buffer is max_deviation unless
+ * the number of required vertices is too large.
+ * The max_vertices_in_full_circle controls how many vertices can be in each round join in the buffer. It is approximately equal to the number of vertices in the polygon around a
+ * buffered point. It has a priority over max_deviation. The max deviation is the distance from the result polygon to a true buffer.
+ * The real deviation is calculated as the max(max_deviation, abs(distance) * (1 - cos(PI / max_vertex_in_complete_circle))).
+ *
+ * Note that max_deviation can be exceeded because geometry is generalized with 0.25 * real_deviation, also input segments closer than 0.25 * real_deviation are
+ * snapped to a point.
+ */
+ public abstract GeometryCursor execute(GeometryCursor input_geometries,
+ SpatialReference sr,
+ double[] distances,
+ double max_deviation,
+ int max_vertices_in_full_circle,
+ boolean b_union,
+ ProgressTracker progress_tracker);
- public static OperatorBuffer local() {
- return (OperatorBuffer) OperatorFactoryLocal.getInstance().getOperator(Type.Buffer);
- }
+ public static OperatorBuffer local() {
+ return (OperatorBuffer) OperatorFactoryLocal.getInstance().getOperator(Type.Buffer);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorBufferCursor.java b/src/main/java/com/esri/core/geometry/OperatorBufferCursor.java
index bcd2d707..d77a1546 100644
--- a/src/main/java/com/esri/core/geometry/OperatorBufferCursor.java
+++ b/src/main/java/com/esri/core/geometry/OperatorBufferCursor.java
@@ -25,53 +25,53 @@
package com.esri.core.geometry;
class OperatorBufferCursor extends GeometryCursor {
- Bufferer m_bufferer = new Bufferer();
- private SpatialReferenceImpl m_Spatial_reference;
- private ProgressTracker m_progress_tracker;
- private double[] m_distances;
- private Envelope2D m_currentUnionEnvelope2D;
- private boolean m_bUnion;
- double m_max_deviation;
- int m_max_vertices_in_full_circle;
- private int m_dindex;
+ Bufferer m_bufferer = new Bufferer();
+ private SpatialReferenceImpl m_Spatial_reference;
+ private ProgressTracker m_progress_tracker;
+ private double[] m_distances;
+ private Envelope2D m_currentUnionEnvelope2D;
+ private boolean m_bUnion;
+ double m_max_deviation;
+ int m_max_vertices_in_full_circle;
+ private int m_dindex;
- OperatorBufferCursor(GeometryCursor inputGeoms,
- SpatialReference sr,
- double[] distances,
- double max_deviation,
- int max_vertices,
- boolean b_union,
- ProgressTracker progress_tracker) {
- m_inputGeoms = inputGeoms;
- m_max_deviation = max_deviation;
- m_max_vertices_in_full_circle = max_vertices;
- m_Spatial_reference = (SpatialReferenceImpl) (sr);
- m_distances = distances;
- m_bUnion = b_union;
- m_currentUnionEnvelope2D = new Envelope2D();
- m_currentUnionEnvelope2D.setEmpty();
- m_dindex = -1;
- m_progress_tracker = progress_tracker;
- }
+ OperatorBufferCursor(GeometryCursor inputGeoms,
+ SpatialReference sr,
+ double[] distances,
+ double max_deviation,
+ int max_vertices,
+ boolean b_union,
+ ProgressTracker progress_tracker) {
+ m_inputGeoms = inputGeoms;
+ m_max_deviation = max_deviation;
+ m_max_vertices_in_full_circle = max_vertices;
+ m_Spatial_reference = (SpatialReferenceImpl) (sr);
+ m_distances = distances;
+ m_bUnion = b_union;
+ m_currentUnionEnvelope2D = new Envelope2D();
+ m_currentUnionEnvelope2D.setEmpty();
+ m_dindex = -1;
+ m_progress_tracker = progress_tracker;
+ }
- @Override
- public Geometry next() {
- if (m_bUnion) {
- OperatorBufferCursor bufferCursor = new OperatorBufferCursor(m_inputGeoms,
- m_Spatial_reference, m_distances, m_max_deviation, m_max_vertices_in_full_circle, false, m_progress_tracker);
- return ((OperatorUnion) OperatorFactoryLocal.getInstance().getOperator(Operator.Type.Union)).execute(bufferCursor, m_Spatial_reference, m_progress_tracker).next();
- } else {
- if (hasNext()) {
- if (m_dindex + 1 < m_distances.length)
- m_dindex++;
+ @Override
+ public Geometry next() {
+ if (m_bUnion) {
+ OperatorBufferCursor bufferCursor = new OperatorBufferCursor(m_inputGeoms,
+ m_Spatial_reference, m_distances, m_max_deviation, m_max_vertices_in_full_circle, false, m_progress_tracker);
+ return ((OperatorUnion) OperatorFactoryLocal.getInstance().getOperator(Operator.Type.Union)).execute(bufferCursor, m_Spatial_reference, m_progress_tracker).next();
+ } else {
+ if (hasNext()) {
+ if (m_dindex + 1 < m_distances.length)
+ m_dindex++;
- return buffer(m_inputGeoms.next(), m_distances[m_dindex]);
- }
- return null;
- }
- }
+ return buffer(m_inputGeoms.next(), m_distances[m_dindex]);
+ }
+ return null;
+ }
+ }
- Geometry buffer(Geometry geom, double distance) {
- return m_bufferer.buffer(geom, distance, m_Spatial_reference, m_max_deviation, m_max_vertices_in_full_circle, m_progress_tracker);
- }
+ Geometry buffer(Geometry geom, double distance) {
+ return m_bufferer.buffer(geom, distance, m_Spatial_reference, m_max_deviation, m_max_vertices_in_full_circle, m_progress_tracker);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorBufferLocal.java b/src/main/java/com/esri/core/geometry/OperatorBufferLocal.java
index 7dddbcf1..78e281cc 100644
--- a/src/main/java/com/esri/core/geometry/OperatorBufferLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorBufferLocal.java
@@ -26,42 +26,42 @@
class OperatorBufferLocal extends OperatorBuffer {
- @Override
- public GeometryCursor execute(GeometryCursor inputGeometries,
- SpatialReference sr,
- double[] distances,
- boolean bUnion,
- ProgressTracker progressTracker) {
- return execute(inputGeometries,
- sr,
- distances,
- NumberUtils.NaN(),
- 96,
- bUnion,
- progressTracker);
- }
+ @Override
+ public GeometryCursor execute(GeometryCursor inputGeometries,
+ SpatialReference sr,
+ double[] distances,
+ boolean bUnion,
+ ProgressTracker progressTracker) {
+ return execute(inputGeometries,
+ sr,
+ distances,
+ NumberUtils.NaN(),
+ 96,
+ bUnion,
+ progressTracker);
+ }
- @Override
- public Geometry execute(Geometry inputGeometry,
- SpatialReference sr,
- double distance,
- ProgressTracker progressTracker) {
- SimpleGeometryCursor inputCursor = new SimpleGeometryCursor(inputGeometry);
- double[] distances = new double[1];
- distances[0] = distance;
- GeometryCursor outputCursor = execute(inputCursor, sr, distances, false, progressTracker);
+ @Override
+ public Geometry execute(Geometry inputGeometry,
+ SpatialReference sr,
+ double distance,
+ ProgressTracker progressTracker) {
+ SimpleGeometryCursor inputCursor = new SimpleGeometryCursor(inputGeometry);
+ double[] distances = new double[1];
+ distances[0] = distance;
+ GeometryCursor outputCursor = execute(inputCursor, sr, distances, false, progressTracker);
- return outputCursor.next();
- }
+ return outputCursor.next();
+ }
- @Override
- public GeometryCursor execute(GeometryCursor inputGeometries,
- SpatialReference sr,
- double[] distances,
- double max_deviation,
- int max_vertices_in_full_circle,
- boolean b_union,
- ProgressTracker progressTracker) {
- return new OperatorBufferCursor(inputGeometries, sr, distances, max_deviation, max_vertices_in_full_circle, b_union, progressTracker);
- }
+ @Override
+ public GeometryCursor execute(GeometryCursor inputGeometries,
+ SpatialReference sr,
+ double[] distances,
+ double max_deviation,
+ int max_vertices_in_full_circle,
+ boolean b_union,
+ ProgressTracker progressTracker) {
+ return new OperatorBufferCursor(inputGeometries, sr, distances, max_deviation, max_vertices_in_full_circle, b_union, progressTracker);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorCentroid2D.java b/src/main/java/com/esri/core/geometry/OperatorCentroid2D.java
new file mode 100644
index 00000000..9453053d
--- /dev/null
+++ b/src/main/java/com/esri/core/geometry/OperatorCentroid2D.java
@@ -0,0 +1,37 @@
+/*
+ Copyright 1995-2017 Esri
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ For additional information, contact:
+ Environmental Systems Research Institute, Inc.
+ Attn: Contracts Dept
+ 380 New York Street
+ Redlands, California, USA 92373
+
+ email: contracts@esri.com
+ */
+package com.esri.core.geometry;
+
+public abstract class OperatorCentroid2D extends Operator {
+ @Override
+ public Type getType() {
+ return Type.Centroid2D;
+ }
+
+ public abstract Point2D execute(Geometry geometry, ProgressTracker progressTracker);
+
+ public static OperatorCentroid2D local() {
+ return (OperatorCentroid2D) OperatorFactoryLocal.getInstance().getOperator(Type.Centroid2D);
+ }
+}
diff --git a/src/main/java/com/esri/core/geometry/OperatorCentroid2DLocal.java b/src/main/java/com/esri/core/geometry/OperatorCentroid2DLocal.java
new file mode 100644
index 00000000..ce7079b8
--- /dev/null
+++ b/src/main/java/com/esri/core/geometry/OperatorCentroid2DLocal.java
@@ -0,0 +1,143 @@
+/*
+ Copyright 1995-2019 Esri
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
+ For additional information, contact:
+ Environmental Systems Research Institute, Inc.
+ Attn: Contracts Dept
+ 380 New York Street
+ Redlands, California, USA 92373
+
+ email: contracts@esri.com
+ */
+package com.esri.core.geometry;
+
+public class OperatorCentroid2DLocal extends OperatorCentroid2D {
+ @Override
+ public Point2D execute(Geometry geometry, ProgressTracker progressTracker) {
+ if (geometry.isEmpty()) {
+ return null;
+ }
+
+ Geometry.Type geometryType = geometry.getType();
+ switch (geometryType) {
+ case Point:
+ return ((Point) geometry).getXY();
+ case Line:
+ return computeLineCentroid((Line) geometry);
+ case Envelope:
+ return ((Envelope) geometry).getCenterXY();
+ case MultiPoint:
+ return computePointsCentroid((MultiPoint) geometry);
+ case Polyline:
+ return computePolylineCentroid(((Polyline) geometry));
+ case Polygon:
+ return computePolygonCentroid((Polygon) geometry);
+ default:
+ throw new UnsupportedOperationException("Unexpected geometry type: " + geometryType);
+ }
+ }
+
+ private static Point2D computeLineCentroid(Line line) {
+ return new Point2D((line.getEndX() - line.getStartX()) / 2, (line.getEndY() - line.getStartY()) / 2);
+ }
+
+ // Points centroid is arithmetic mean of the input points
+ private static Point2D computePointsCentroid(MultiVertexGeometry multiPoint) {
+ double xSum = 0;
+ double ySum = 0;
+ int pointCount = multiPoint.getPointCount();
+ Point2D point2D = new Point2D();
+ for (int i = 0; i < pointCount; i++) {
+ multiPoint.getXY(i, point2D);
+ xSum += point2D.x;
+ ySum += point2D.y;
+ }
+ return new Point2D(xSum / pointCount, ySum / pointCount);
+ }
+
+ // Lines centroid is weighted mean of each line segment, weight in terms of line
+ // length
+ private static Point2D computePolylineCentroid(MultiPath polyline) {
+ double totalLength = polyline.calculateLength2D();
+ if (totalLength == 0) {
+ return computePointsCentroid(polyline);
+ }
+
+ MathUtils.KahanSummator xSum = new MathUtils.KahanSummator(0);
+ MathUtils.KahanSummator ySum = new MathUtils.KahanSummator(0);
+ Point2D point = new Point2D();
+ SegmentIterator iter = polyline.querySegmentIterator();
+ while (iter.nextPath()) {
+ while (iter.hasNextSegment()) {
+ Segment seg = iter.nextSegment();
+ seg.getCoord2D(0.5, point);
+ double length = seg.calculateLength2D();
+ point.scale(length);
+ xSum.add(point.x);
+ ySum.add(point.y);
+ }
+ }
+
+ return new Point2D(xSum.getResult() / totalLength, ySum.getResult() / totalLength);
+ }
+
+ // Polygon centroid: area weighted average of centroids
+ private static Point2D computePolygonCentroid(Polygon polygon) {
+ double totalArea = polygon.calculateArea2D();
+ if (totalArea == 0)
+ {
+ return computePolylineCentroid(polygon);
+ }
+
+ MathUtils.KahanSummator xSum = new MathUtils.KahanSummator(0);
+ MathUtils.KahanSummator ySum = new MathUtils.KahanSummator(0);
+ Point2D startPoint = new Point2D();
+ Point2D current = new Point2D();
+ Point2D next = new Point2D();
+ Point2D origin = polygon.getXY(0);
+
+ for (int ipath = 0, npaths = polygon.getPathCount(); ipath < npaths; ipath++) {
+ int startIndex = polygon.getPathStart(ipath);
+ int endIndex = polygon.getPathEnd(ipath);
+ int pointCount = endIndex - startIndex;
+ if (pointCount < 3) {
+ continue;
+ }
+
+ polygon.getXY(startIndex, startPoint);
+ polygon.getXY(startIndex + 1, current);
+ current.sub(startPoint);
+ for (int i = startIndex + 2, n = endIndex; i < n; i++) {
+ polygon.getXY(i, next);
+ next.sub(startPoint);
+ double twiceTriangleArea = next.x * current.y - current.x * next.y;
+ xSum.add((current.x + next.x) * twiceTriangleArea);
+ ySum.add((current.y + next.y) * twiceTriangleArea);
+ current.setCoords(next);
+ }
+
+ startPoint.sub(origin);
+ startPoint.scale(6.0 * polygon.calculateRingArea2D(ipath));
+ //add weighted startPoint
+ xSum.add(startPoint.x);
+ ySum.add(startPoint.y);
+ }
+
+ totalArea *= 6.0;
+ Point2D res = new Point2D(xSum.getResult() / totalArea, ySum.getResult() / totalArea);
+ res.add(origin);
+ return res;
+ }
+}
diff --git a/src/main/java/com/esri/core/geometry/OperatorClip.java b/src/main/java/com/esri/core/geometry/OperatorClip.java
index adfc4018..a32312e3 100644
--- a/src/main/java/com/esri/core/geometry/OperatorClip.java
+++ b/src/main/java/com/esri/core/geometry/OperatorClip.java
@@ -30,25 +30,25 @@
* Clips geometries with Envelope2D.
*/
public abstract class OperatorClip extends Operator {
- public Type getType() {
- return Type.Clip;
- }
-
- /**
- * Performs the Clip operation on the geometry set.
- */
- public abstract GeometryCursor execute(GeometryCursor geoms,
- Envelope2D envelope, SpatialReference spatialRef,
- ProgressTracker progressTracker);
-
- /**
- * Performs the Clip operation on a single geometry.
- */
- public abstract Geometry execute(Geometry geom, Envelope2D envelope,
- SpatialReference spatialRef, ProgressTracker progressTracker);
-
- public static OperatorClip local() {
- return (OperatorClip) OperatorFactoryLocal.getInstance().getOperator(Type.Clip);
- }
+ public Type getType() {
+ return Type.Clip;
+ }
+
+ /**
+ * Performs the Clip operation on the geometry set.
+ */
+ public abstract GeometryCursor execute(GeometryCursor geoms,
+ Envelope2D envelope, SpatialReference spatialRef,
+ ProgressTracker progressTracker);
+
+ /**
+ * Performs the Clip operation on a single geometry.
+ */
+ public abstract Geometry execute(Geometry geom, Envelope2D envelope,
+ SpatialReference spatialRef, ProgressTracker progressTracker);
+
+ public static OperatorClip local() {
+ return (OperatorClip) OperatorFactoryLocal.getInstance().getOperator(Type.Clip);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorClipCursor.java b/src/main/java/com/esri/core/geometry/OperatorClipCursor.java
index 09f024a8..7904bd57 100644
--- a/src/main/java/com/esri/core/geometry/OperatorClipCursor.java
+++ b/src/main/java/com/esri/core/geometry/OperatorClipCursor.java
@@ -25,25 +25,25 @@
package com.esri.core.geometry;
class OperatorClipCursor extends GeometryCursor {
- private Envelope2D m_envelope;
- double m_tolerance;
-
- OperatorClipCursor(GeometryCursor geoms, Envelope2D envelope,
- SpatialReference spatial_ref, ProgressTracker progress_tracker) {
- if (geoms == null)
- throw new IllegalArgumentException();
-
- m_envelope = envelope;
- m_inputGeoms = geoms;
-
- m_tolerance = InternalUtils.calculateToleranceFromGeometry(spatial_ref, envelope, false);
- }
-
- @Override
- public Geometry next() {
- if (hasNext()) {
- return Clipper.clip(m_inputGeoms.next(), m_envelope, m_tolerance, 0.0);
- }
- return null;
- }
+ private Envelope2D m_envelope;
+ double m_tolerance;
+
+ OperatorClipCursor(GeometryCursor geoms, Envelope2D envelope,
+ SpatialReference spatial_ref, ProgressTracker progress_tracker) {
+ if (geoms == null)
+ throw new IllegalArgumentException();
+
+ m_envelope = envelope;
+ m_inputGeoms = geoms;
+
+ m_tolerance = InternalUtils.calculateToleranceFromGeometry(spatial_ref, envelope, false);
+ }
+
+ @Override
+ public Geometry next() {
+ if (hasNext()) {
+ return Clipper.clip(m_inputGeoms.next(), m_envelope, m_tolerance, 0.0);
+ }
+ return null;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorClipLocal.java b/src/main/java/com/esri/core/geometry/OperatorClipLocal.java
index e641a8c9..4905eba2 100644
--- a/src/main/java/com/esri/core/geometry/OperatorClipLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorClipLocal.java
@@ -26,19 +26,19 @@
class OperatorClipLocal extends OperatorClip {
- @Override
- public GeometryCursor execute(GeometryCursor geoms, Envelope2D envelope,
- SpatialReference spatialRef, ProgressTracker progressTracker) {
- return new OperatorClipCursor(geoms, envelope, spatialRef, progressTracker);
- }
-
- @Override
- public Geometry execute(Geometry geom, Envelope2D envelope,
- SpatialReference spatialRef, ProgressTracker progressTracker) {
- SimpleGeometryCursor inputCursor = new SimpleGeometryCursor(geom);
-
- GeometryCursor outputCursor = execute(inputCursor, envelope, spatialRef, progressTracker);
- return outputCursor.next();
- }
+ @Override
+ public GeometryCursor execute(GeometryCursor geoms, Envelope2D envelope,
+ SpatialReference spatialRef, ProgressTracker progressTracker) {
+ return new OperatorClipCursor(geoms, envelope, spatialRef, progressTracker);
+ }
+
+ @Override
+ public Geometry execute(Geometry geom, Envelope2D envelope,
+ SpatialReference spatialRef, ProgressTracker progressTracker) {
+ SimpleGeometryCursor inputCursor = new SimpleGeometryCursor(geom);
+
+ GeometryCursor outputCursor = execute(inputCursor, envelope, spatialRef, progressTracker);
+ return outputCursor.next();
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorContains.java b/src/main/java/com/esri/core/geometry/OperatorContains.java
index 62745640..bbc4cf27 100644
--- a/src/main/java/com/esri/core/geometry/OperatorContains.java
+++ b/src/main/java/com/esri/core/geometry/OperatorContains.java
@@ -30,13 +30,13 @@
* Relational operation Contains.
*/
public abstract class OperatorContains extends OperatorSimpleRelation {
- @Override
- public Type getType() {
- return Type.Contains;
- }
-
- public static OperatorContains local() {
- return (OperatorContains) OperatorFactoryLocal.getInstance()
- .getOperator(Type.Contains);
- }
+ @Override
+ public Type getType() {
+ return Type.Contains;
+ }
+
+ public static OperatorContains local() {
+ return (OperatorContains) OperatorFactoryLocal.getInstance()
+ .getOperator(Type.Contains);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorContainsLocal.java b/src/main/java/com/esri/core/geometry/OperatorContainsLocal.java
index 9a61ef0f..592822e4 100644
--- a/src/main/java/com/esri/core/geometry/OperatorContainsLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorContainsLocal.java
@@ -25,11 +25,11 @@
package com.esri.core.geometry;
class OperatorContainsLocal extends OperatorContains {
- @Override
- public boolean execute(Geometry inputGeom1, Geometry inputGeom2,
- SpatialReference sr, ProgressTracker progressTracker) {
- return RelationalOperations.relate(inputGeom1, inputGeom2, sr,
- RelationalOperations.Relation.contains, progressTracker);
- }
+ @Override
+ public boolean execute(Geometry inputGeom1, Geometry inputGeom2,
+ SpatialReference sr, ProgressTracker progressTracker) {
+ return RelationalOperations.relate(inputGeom1, inputGeom2, sr,
+ RelationalOperations.Relation.contains, progressTracker);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorConvexHull.java b/src/main/java/com/esri/core/geometry/OperatorConvexHull.java
index 9c02f531..a010b62b 100644
--- a/src/main/java/com/esri/core/geometry/OperatorConvexHull.java
+++ b/src/main/java/com/esri/core/geometry/OperatorConvexHull.java
@@ -29,51 +29,51 @@
* Creates the convex hull of the input geometry.
*/
public abstract class OperatorConvexHull extends Operator {
- @Override
- public Operator.Type getType() {
- return Operator.Type.ConvexHull;
- }
+ @Override
+ public Operator.Type getType() {
+ return Operator.Type.ConvexHull;
+ }
- /**
- * Calculates the convex hull.
- *
- * @param geoms The input geometry cursor.
- * @param progress_tracker The progress tracker. Allows cancellation of a lengthy operation.
- * @param b_merge Put true if you want the convex hull of all the geometries in the cursor combined.
- * Put false if you want the convex hull of each geometry in the cursor individually.
- * @return Returns a cursor over result convex hulls.
- */
- abstract public GeometryCursor execute(GeometryCursor geoms, boolean b_merge,
- ProgressTracker progress_tracker);
+ /**
+ * Calculates the convex hull.
+ *
+ * @param geoms The input geometry cursor.
+ * @param progress_tracker The progress tracker. Allows cancellation of a lengthy operation.
+ * @param b_merge Put true if you want the convex hull of all the geometries in the cursor combined.
+ * Put false if you want the convex hull of each geometry in the cursor individually.
+ * @return Returns a cursor over result convex hulls.
+ */
+ abstract public GeometryCursor execute(GeometryCursor geoms, boolean b_merge,
+ ProgressTracker progress_tracker);
- /**
- * Calculates the convex hull geometry.
- *
- * @param geom The input geometry.
- * @param progress_tracker The progress tracker. Allows cancellation of a lengthy operation.
- * @return Returns the convex hull.
- *
- * Point - Returns the same point.
- * Envelope - returns the same envelope.
- * MultiPoint - If the point count is one, returns the same multipoint. If the point count is two, returns a polyline of the points. Otherwise, computes and returns the convex hull polygon.
- * Segment - Returns a polyline consisting of the segment.
- * Polyline - If consists of only one segment, returns the same polyline. Otherwise, computes and returns the convex hull polygon.
- * Polygon - If more than one path or if the path isn't already convex, computes and returns the convex hull polygon. Otherwise, returns the same polygon.
- */
- abstract public Geometry execute(Geometry geom,
- ProgressTracker progress_tracker);
+ /**
+ * Calculates the convex hull geometry.
+ *
+ * @param geom The input geometry.
+ * @param progress_tracker The progress tracker. Allows cancellation of a lengthy operation.
+ * @return Returns the convex hull.
+ *
+ * Point - Returns the same point.
+ * Envelope - returns the same envelope.
+ * MultiPoint - If the point count is one, returns the same multipoint. If the point count is two, returns a polyline of the points. Otherwise, computes and returns the convex hull polygon.
+ * Segment - Returns a polyline consisting of the segment.
+ * Polyline - If consists of only one segment, returns the same polyline. Otherwise, computes and returns the convex hull polygon.
+ * Polygon - If more than one path or if the path isn't already convex, computes and returns the convex hull polygon. Otherwise, returns the same polygon.
+ */
+ abstract public Geometry execute(Geometry geom,
+ ProgressTracker progress_tracker);
- /**
- * Checks whether a Geometry is convex.
- *
- * @param geom The input geometry to test for convex.
- * @param progress_tracker The progress tracker.
- * @return Returns true if the geometry is convex.
- */
- abstract public boolean isConvex(Geometry geom,
- ProgressTracker progress_tracker);
+ /**
+ * Checks whether a Geometry is convex.
+ *
+ * @param geom The input geometry to test for convex.
+ * @param progress_tracker The progress tracker.
+ * @return Returns true if the geometry is convex.
+ */
+ abstract public boolean isConvex(Geometry geom,
+ ProgressTracker progress_tracker);
- public static OperatorConvexHull local() {
- return (OperatorConvexHull) OperatorFactoryLocal.getInstance().getOperator(Type.ConvexHull);
- }
+ public static OperatorConvexHull local() {
+ return (OperatorConvexHull) OperatorFactoryLocal.getInstance().getOperator(Type.ConvexHull);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorConvexHullCursor.java b/src/main/java/com/esri/core/geometry/OperatorConvexHullCursor.java
index a91aa327..5667b4c5 100644
--- a/src/main/java/com/esri/core/geometry/OperatorConvexHullCursor.java
+++ b/src/main/java/com/esri/core/geometry/OperatorConvexHullCursor.java
@@ -24,184 +24,184 @@
package com.esri.core.geometry;
class OperatorConvexHullCursor extends GeometryCursor {
- private ProgressTracker m_progress_tracker;
- private boolean m_b_merge;
- private boolean m_b_done;
- ConvexHull m_hull = new ConvexHull();
-
- OperatorConvexHullCursor(boolean b_merge, GeometryCursor geoms, ProgressTracker progress_tracker) {
- if (geoms == null)
- throw new IllegalArgumentException();
-
- m_b_merge = b_merge;
- m_b_done = false;
- m_inputGeoms = geoms;
- m_progress_tracker = progress_tracker;
- }
-
- @Override
- public Geometry next() {
- if (m_b_merge) {
- if (!m_b_done) {
- Geometry result = calculateConvexHullMerging_(m_inputGeoms, m_progress_tracker);
- m_b_done = true;
- return result;
- }
-
- return null;
- }
-
- if (!m_b_done) {
- if (hasNext()) {
- return calculateConvexHull_(m_inputGeoms.next(), m_progress_tracker);
- }
-
- m_b_done = true;
- }
-
- return null;
- }
-
- private Geometry calculateConvexHullMerging_(GeometryCursor geoms, ProgressTracker progress_tracker) {
- while (geoms.hasNext()) {
- m_hull.addGeometry(geoms.next());
- }
-
- return m_hull.getBoundingGeometry();
- }
-
- @Override
- public boolean tock() {
- if (m_b_done)
- return true;
-
- if (!m_b_merge) {
- //Do not use tick/tock with the non-merging convex hull.
- //Call tick/next instead,
- //because tick pushes geometry into the cursor, and next performs a single convex hull on it.
- throw new GeometryException("Invalid call for non merging convex hull.");
- }
-
- Geometry geometry = m_inputGeoms.next();
- if (geometry != null) {
- m_hull.addGeometry(geometry);
- return true;
- } else {
- throw new GeometryException("Expects a non-null geometry.");
- }
- }
-
- static Geometry calculateConvexHull_(Geometry geom, ProgressTracker progress_tracker) {
- if (geom.isEmpty())
- return geom.createInstance();
-
- Geometry.Type type = geom.getType();
-
- if (Geometry.isSegment(type.value())) {// Segments are always returned either as a Point or Polyline
- Segment segment = (Segment) geom;
- if (segment.getStartXY().equals(segment.getEndXY())) {
- Point point = new Point();
- segment.queryStart(point);
- return point;
- } else {
- Point pt = new Point();
- Polyline polyline = new Polyline(geom.getDescription());
- segment.queryStart(pt);
- polyline.startPath(pt);
- segment.queryEnd(pt);
- polyline.lineTo(pt);
- return polyline;
- }
- } else if (type == Geometry.Type.Envelope) {
- Envelope envelope = (Envelope) geom;
- Envelope2D env = new Envelope2D();
- envelope.queryEnvelope2D(env);
- if (env.xmin == env.xmax && env.ymin == env.ymax) {
- Point point = new Point();
- envelope.queryCornerByVal(0, point);
- return point;
- } else if (env.xmin == env.xmax || env.ymin == env.ymax) {
- Point pt = new Point();
- Polyline polyline = new Polyline(geom.getDescription());
- envelope.queryCornerByVal(0, pt);
- polyline.startPath(pt);
- envelope.queryCornerByVal(1, pt);
- polyline.lineTo(pt);
- return polyline;
- } else {
- Polygon polygon = new Polygon(geom.getDescription());
- polygon.addEnvelope(envelope, false);
- return polygon;
- }
- }
-
- if (isConvex_(geom, progress_tracker)) {
- if (type == Geometry.Type.MultiPoint) {// Downgrade to a Point for simplistic output
- MultiPoint multi_point = (MultiPoint) geom;
- Point point = new Point();
- multi_point.getPointByVal(0, point);
- return point;
- }
-
- return geom;
- }
-
- assert (Geometry.isMultiVertex(type.value()));
-
- Geometry convex_hull = ConvexHull.construct((MultiVertexGeometry) geom);
- return convex_hull;
- }
-
- static boolean isConvex_(Geometry geom, ProgressTracker progress_tracker) {
- if (geom.isEmpty())
- return true; // vacuously true
-
- Geometry.Type type = geom.getType();
-
- if (type == Geometry.Type.Point)
- return true; // vacuously true
-
- if (type == Geometry.Type.Envelope) {
- Envelope envelope = (Envelope) geom;
- if (envelope.getXMin() == envelope.getXMax() || envelope.getYMin() == envelope.getYMax())
- return false;
-
- return true;
- }
-
- if (MultiPath.isSegment(type.value())) {
- Segment segment = (Segment) geom;
- if (segment.getStartXY().equals(segment.getEndXY()))
- return false;
-
- return true; // true, but we will upgrade to a Polyline for the ConvexHull operation
- }
-
- if (type == Geometry.Type.MultiPoint) {
- MultiPoint multi_point = (MultiPoint) geom;
-
- if (multi_point.getPointCount() == 1)
- return true; // vacuously true, but we will downgrade to a Point for the ConvexHull operation
-
- return false;
- }
-
- if (type == Geometry.Type.Polyline) {
- Polyline polyline = (Polyline) geom;
-
- if (polyline.getPathCount() == 1 && polyline.getPointCount() == 2) {
- if (!polyline.getXY(0).equals(polyline.getXY(1)))
- return true; // vacuously true
- }
-
- return false; // create convex hull
- }
-
- Polygon polygon = (Polygon) geom;
-
- if (polygon.getPathCount() != 1 || polygon.getPointCount() < 3)
- return false;
-
- return ConvexHull.isPathConvex(polygon, 0, progress_tracker);
- }
+ private ProgressTracker m_progress_tracker;
+ private boolean m_b_merge;
+ private boolean m_b_done;
+ ConvexHull m_hull = new ConvexHull();
+
+ OperatorConvexHullCursor(boolean b_merge, GeometryCursor geoms, ProgressTracker progress_tracker) {
+ if (geoms == null)
+ throw new IllegalArgumentException();
+
+ m_b_merge = b_merge;
+ m_b_done = false;
+ m_inputGeoms = geoms;
+ m_progress_tracker = progress_tracker;
+ }
+
+ @Override
+ public Geometry next() {
+ if (m_b_merge) {
+ if (!m_b_done) {
+ Geometry result = calculateConvexHullMerging_(m_inputGeoms, m_progress_tracker);
+ m_b_done = true;
+ return result;
+ }
+
+ return null;
+ }
+
+ if (!m_b_done) {
+ if (hasNext()) {
+ return calculateConvexHull_(m_inputGeoms.next(), m_progress_tracker);
+ }
+
+ m_b_done = true;
+ }
+
+ return null;
+ }
+
+ private Geometry calculateConvexHullMerging_(GeometryCursor geoms, ProgressTracker progress_tracker) {
+ while (geoms.hasNext()) {
+ m_hull.addGeometry(geoms.next());
+ }
+
+ return m_hull.getBoundingGeometry();
+ }
+
+ @Override
+ public boolean tock() {
+ if (m_b_done)
+ return true;
+
+ if (!m_b_merge) {
+ //Do not use tick/tock with the non-merging convex hull.
+ //Call tick/next instead,
+ //because tick pushes geometry into the cursor, and next performs a single convex hull on it.
+ throw new GeometryException("Invalid call for non merging convex hull.");
+ }
+
+ Geometry geometry = m_inputGeoms.next();
+ if (geometry != null) {
+ m_hull.addGeometry(geometry);
+ return true;
+ } else {
+ throw new GeometryException("Expects a non-null geometry.");
+ }
+ }
+
+ static Geometry calculateConvexHull_(Geometry geom, ProgressTracker progress_tracker) {
+ if (geom.isEmpty())
+ return geom.createInstance();
+
+ Geometry.Type type = geom.getType();
+
+ if (Geometry.isSegment(type.value())) {// Segments are always returned either as a Point or Polyline
+ Segment segment = (Segment) geom;
+ if (segment.getStartXY().equals(segment.getEndXY())) {
+ Point point = new Point();
+ segment.queryStart(point);
+ return point;
+ } else {
+ Point pt = new Point();
+ Polyline polyline = new Polyline(geom.getDescription());
+ segment.queryStart(pt);
+ polyline.startPath(pt);
+ segment.queryEnd(pt);
+ polyline.lineTo(pt);
+ return polyline;
+ }
+ } else if (type == Geometry.Type.Envelope) {
+ Envelope envelope = (Envelope) geom;
+ Envelope2D env = new Envelope2D();
+ envelope.queryEnvelope2D(env);
+ if (env.xmin == env.xmax && env.ymin == env.ymax) {
+ Point point = new Point();
+ envelope.queryCornerByVal(0, point);
+ return point;
+ } else if (env.xmin == env.xmax || env.ymin == env.ymax) {
+ Point pt = new Point();
+ Polyline polyline = new Polyline(geom.getDescription());
+ envelope.queryCornerByVal(0, pt);
+ polyline.startPath(pt);
+ envelope.queryCornerByVal(1, pt);
+ polyline.lineTo(pt);
+ return polyline;
+ } else {
+ Polygon polygon = new Polygon(geom.getDescription());
+ polygon.addEnvelope(envelope, false);
+ return polygon;
+ }
+ }
+
+ if (isConvex_(geom, progress_tracker)) {
+ if (type == Geometry.Type.MultiPoint) {// Downgrade to a Point for simplistic output
+ MultiPoint multi_point = (MultiPoint) geom;
+ Point point = new Point();
+ multi_point.getPointByVal(0, point);
+ return point;
+ }
+
+ return geom;
+ }
+
+ assert (Geometry.isMultiVertex(type.value()));
+
+ Geometry convex_hull = ConvexHull.construct((MultiVertexGeometry) geom);
+ return convex_hull;
+ }
+
+ static boolean isConvex_(Geometry geom, ProgressTracker progress_tracker) {
+ if (geom.isEmpty())
+ return true; // vacuously true
+
+ Geometry.Type type = geom.getType();
+
+ if (type == Geometry.Type.Point)
+ return true; // vacuously true
+
+ if (type == Geometry.Type.Envelope) {
+ Envelope envelope = (Envelope) geom;
+ if (envelope.getXMin() == envelope.getXMax() || envelope.getYMin() == envelope.getYMax())
+ return false;
+
+ return true;
+ }
+
+ if (MultiPath.isSegment(type.value())) {
+ Segment segment = (Segment) geom;
+ if (segment.getStartXY().equals(segment.getEndXY()))
+ return false;
+
+ return true; // true, but we will upgrade to a Polyline for the ConvexHull operation
+ }
+
+ if (type == Geometry.Type.MultiPoint) {
+ MultiPoint multi_point = (MultiPoint) geom;
+
+ if (multi_point.getPointCount() == 1)
+ return true; // vacuously true, but we will downgrade to a Point for the ConvexHull operation
+
+ return false;
+ }
+
+ if (type == Geometry.Type.Polyline) {
+ Polyline polyline = (Polyline) geom;
+
+ if (polyline.getPathCount() == 1 && polyline.getPointCount() == 2) {
+ if (!polyline.getXY(0).equals(polyline.getXY(1)))
+ return true; // vacuously true
+ }
+
+ return false; // create convex hull
+ }
+
+ Polygon polygon = (Polygon) geom;
+
+ if (polygon.getPathCount() != 1 || polygon.getPointCount() < 3)
+ return false;
+
+ return ConvexHull.isPathConvex(polygon, 0, progress_tracker);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorConvexHullLocal.java b/src/main/java/com/esri/core/geometry/OperatorConvexHullLocal.java
index 5f02bb62..d9537b79 100644
--- a/src/main/java/com/esri/core/geometry/OperatorConvexHullLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorConvexHullLocal.java
@@ -24,20 +24,20 @@
package com.esri.core.geometry;
class OperatorConvexHullLocal extends OperatorConvexHull {
- @Override
- public GeometryCursor execute(GeometryCursor geoms, boolean b_merge,
- ProgressTracker progress_tracker) {
- return new OperatorConvexHullCursor(b_merge, geoms, progress_tracker);
- }
-
- @Override
- public Geometry execute(Geometry geometry, ProgressTracker progress_tracker) {
- return OperatorConvexHullCursor.calculateConvexHull_(geometry,
- progress_tracker);
- }
-
- @Override
- public boolean isConvex(Geometry geom, ProgressTracker progress_tracker) {
- return OperatorConvexHullCursor.isConvex_(geom, progress_tracker);
- }
+ @Override
+ public GeometryCursor execute(GeometryCursor geoms, boolean b_merge,
+ ProgressTracker progress_tracker) {
+ return new OperatorConvexHullCursor(b_merge, geoms, progress_tracker);
+ }
+
+ @Override
+ public Geometry execute(Geometry geometry, ProgressTracker progress_tracker) {
+ return OperatorConvexHullCursor.calculateConvexHull_(geometry,
+ progress_tracker);
+ }
+
+ @Override
+ public boolean isConvex(Geometry geom, ProgressTracker progress_tracker) {
+ return OperatorConvexHullCursor.isConvex_(geom, progress_tracker);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorCrosses.java b/src/main/java/com/esri/core/geometry/OperatorCrosses.java
index 40bbed50..0780879a 100644
--- a/src/main/java/com/esri/core/geometry/OperatorCrosses.java
+++ b/src/main/java/com/esri/core/geometry/OperatorCrosses.java
@@ -30,14 +30,14 @@
* Relational operation Crosses.
*/
public abstract class OperatorCrosses extends OperatorSimpleRelation {
- @Override
- public Type getType() {
- return Type.Crosses;
- }
-
- public static OperatorCrosses local() {
- return (OperatorCrosses) OperatorFactoryLocal.getInstance()
- .getOperator(Type.Crosses);
- }
+ @Override
+ public Type getType() {
+ return Type.Crosses;
+ }
+
+ public static OperatorCrosses local() {
+ return (OperatorCrosses) OperatorFactoryLocal.getInstance()
+ .getOperator(Type.Crosses);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorCrossesLocal.java b/src/main/java/com/esri/core/geometry/OperatorCrossesLocal.java
index b4a7341e..752ab1be 100644
--- a/src/main/java/com/esri/core/geometry/OperatorCrossesLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorCrossesLocal.java
@@ -26,11 +26,11 @@
class OperatorCrossesLocal extends OperatorCrosses {
- @Override
- public boolean execute(Geometry inputGeom1, Geometry inputGeom2,
- SpatialReference sr, ProgressTracker progressTracker) {
- return RelationalOperations.relate(inputGeom1, inputGeom2, sr,
- RelationalOperations.Relation.crosses, progressTracker);
- }
+ @Override
+ public boolean execute(Geometry inputGeom1, Geometry inputGeom2,
+ SpatialReference sr, ProgressTracker progressTracker) {
+ return RelationalOperations.relate(inputGeom1, inputGeom2, sr,
+ RelationalOperations.Relation.crosses, progressTracker);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorCut.java b/src/main/java/com/esri/core/geometry/OperatorCut.java
index bf2d73e1..2bb553a5 100644
--- a/src/main/java/com/esri/core/geometry/OperatorCut.java
+++ b/src/main/java/com/esri/core/geometry/OperatorCut.java
@@ -28,42 +28,42 @@
* Splits the target polyline or polygon where it is crossed by the cutter polyline.
*/
public abstract class OperatorCut extends Operator {
- @Override
- public Type getType() {
- return Type.Cut;
- }
+ @Override
+ public Type getType() {
+ return Type.Cut;
+ }
- /**
- * Performs the Cut operation on a geometry.
- *
- * @param bConsiderTouch Indicates whether we consider a touch event a cut.
- * This only applies to polylines, but it's recommended to set this variable to True.
- * @param cuttee The input geometry to be cut.
- * @param cutter The polyline that will be used to divide the cuttee into
- * pieces where it crosses the cutter.
- * @return Returns a GeometryCursor of cut geometries.
- * All left cuts will be grouped together in the first geometry. Right cuts and
- * coincident cuts are grouped in the second geometry, and each undefined cut along
- * with any uncut parts are output as separate geometries. If there were no cuts
- * the cursor will return no geometry. If the left or right cut does not
- * exist, the returned geometry will be empty for this type of cut. An
- * undefined cut will only be produced if a left cut or right cut was
- * produced and there was a part left over after cutting or a cut is
- * bounded to the left and right of the cutter.
- */
- public abstract GeometryCursor execute(boolean bConsiderTouch,
- Geometry cuttee,
- Polyline cutter,
- SpatialReference spatialReference,
- ProgressTracker progressTracker);
+ /**
+ * Performs the Cut operation on a geometry.
+ *
+ * @param bConsiderTouch Indicates whether we consider a touch event a cut.
+ * This only applies to polylines, but it's recommended to set this variable to True.
+ * @param cuttee The input geometry to be cut.
+ * @param cutter The polyline that will be used to divide the cuttee into
+ * pieces where it crosses the cutter.
+ * @return Returns a GeometryCursor of cut geometries.
+ * All left cuts will be grouped together in the first geometry. Right cuts and
+ * coincident cuts are grouped in the second geometry, and each undefined cut along
+ * with any uncut parts are output as separate geometries. If there were no cuts
+ * the cursor will return no geometry. If the left or right cut does not
+ * exist, the returned geometry will be empty for this type of cut. An
+ * undefined cut will only be produced if a left cut or right cut was
+ * produced and there was a part left over after cutting or a cut is
+ * bounded to the left and right of the cutter.
+ */
+ public abstract GeometryCursor execute(boolean bConsiderTouch,
+ Geometry cuttee,
+ Polyline cutter,
+ SpatialReference spatialReference,
+ ProgressTracker progressTracker);
- public abstract GeometryCursor execute(boolean bConsiderTouch,
- GeometryCursor cuttees,
- Polyline cutter,
- SpatialReference spatialReference,
- ProgressTracker progressTracker);
+ public abstract GeometryCursor execute(boolean bConsiderTouch,
+ GeometryCursor cuttees,
+ Polyline cutter,
+ SpatialReference spatialReference,
+ ProgressTracker progressTracker);
- public static OperatorCut local() {
- return (OperatorCut) OperatorFactoryLocal.getInstance().getOperator(Type.Cut);
- }
+ public static OperatorCut local() {
+ return (OperatorCut) OperatorFactoryLocal.getInstance().getOperator(Type.Cut);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorCutCursor.java b/src/main/java/com/esri/core/geometry/OperatorCutCursor.java
index 10f97b02..c9bedffa 100644
--- a/src/main/java/com/esri/core/geometry/OperatorCutCursor.java
+++ b/src/main/java/com/esri/core/geometry/OperatorCutCursor.java
@@ -31,186 +31,186 @@
import java.util.ArrayList;
class OperatorCutCursor extends GeometryCursor {
- boolean m_bConsiderTouch;
- Geometry m_cuttee;
- Polyline m_cutter;
- double m_tolerance;
- ProgressTracker m_progressTracker;
- SpatialReference m_spatialReference;
- int m_cutIndex;
- ArrayList
- * The operator subtracts subtractor from every geometry in
- * inputGeometries.
- */
- public abstract GeometryCursor execute(GeometryCursor inputGeometries,
- GeometryCursor subtractor, SpatialReference sr,
- ProgressTracker progressTracker);
+ /**
+ * Performs the Topological Difference operation on the geometry set.
+ *
+ * @param inputGeometries is the set of Geometry instances to be subtracted by the
+ * subtractor
+ * @param subtractor is the Geometry being subtracted.
+ * @return Returns the result of the subtraction.
+ *
+ * The operator subtracts subtractor from every geometry in
+ * inputGeometries.
+ */
+ public abstract GeometryCursor execute(GeometryCursor inputGeometries,
+ GeometryCursor subtractor, SpatialReference sr,
+ ProgressTracker progressTracker);
- /**
- * Performs the Topological Difference operation on the two geometries.
- *
- * @param inputGeometry is the Geometry instance on the left hand side of the
- * subtraction.
- * @param subtractor is the Geometry on the right hand side being subtracted.
- * @return Returns the result of subtraction.
- */
- public abstract Geometry execute(Geometry inputGeometry,
- Geometry subtractor, SpatialReference sr,
- ProgressTracker progressTracker);
+ /**
+ * Performs the Topological Difference operation on the two geometries.
+ *
+ * @param inputGeometry is the Geometry instance on the left hand side of the
+ * subtraction.
+ * @param subtractor is the Geometry on the right hand side being subtracted.
+ * @return Returns the result of subtraction.
+ */
+ public abstract Geometry execute(Geometry inputGeometry,
+ Geometry subtractor, SpatialReference sr,
+ ProgressTracker progressTracker);
- public static OperatorDifference local() {
- return (OperatorDifference) OperatorFactoryLocal.getInstance()
- .getOperator(Type.Difference);
- }
+ public static OperatorDifference local() {
+ return (OperatorDifference) OperatorFactoryLocal.getInstance()
+ .getOperator(Type.Difference);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorDifferenceCursor.java b/src/main/java/com/esri/core/geometry/OperatorDifferenceCursor.java
index a71dffbc..a75bb6dd 100644
--- a/src/main/java/com/esri/core/geometry/OperatorDifferenceCursor.java
+++ b/src/main/java/com/esri/core/geometry/OperatorDifferenceCursor.java
@@ -25,33 +25,33 @@
package com.esri.core.geometry;
class OperatorDifferenceCursor extends GeometryCursor {
- ProgressTracker m_progress_tracker;
- SpatialReference m_Spatial_reference;
- Geometry m_geomSubtractor;
- boolean m_bEmpty;
-
- OperatorDifferenceCursor(GeometryCursor inputGeoms,
- GeometryCursor geomSubtractor, SpatialReference sr,
- ProgressTracker progress_tracker) {
- m_bEmpty = (geomSubtractor == null);
- m_inputGeoms = inputGeoms;
- m_Spatial_reference = sr;
- m_geomSubtractor = geomSubtractor.next();
- m_progress_tracker = progress_tracker;
- }
-
- @Override
- public Geometry next() {
- if (m_bEmpty)
- return null;
-
- if (hasNext()) {
- return OperatorDifferenceLocal.difference(
- m_inputGeoms.next(),
- m_geomSubtractor,
- m_Spatial_reference,
- m_progress_tracker);
- }
- return null;
- }
+ ProgressTracker m_progress_tracker;
+ SpatialReference m_Spatial_reference;
+ Geometry m_geomSubtractor;
+ boolean m_bEmpty;
+
+ OperatorDifferenceCursor(GeometryCursor inputGeoms,
+ GeometryCursor geomSubtractor, SpatialReference sr,
+ ProgressTracker progress_tracker) {
+ m_bEmpty = (geomSubtractor == null);
+ m_inputGeoms = inputGeoms;
+ m_Spatial_reference = sr;
+ m_geomSubtractor = geomSubtractor.next();
+ m_progress_tracker = progress_tracker;
+ }
+
+ @Override
+ public Geometry next() {
+ if (m_bEmpty)
+ return null;
+
+ if (hasNext()) {
+ return OperatorDifferenceLocal.difference(
+ m_inputGeoms.next(),
+ m_geomSubtractor,
+ m_Spatial_reference,
+ m_progress_tracker);
+ }
+ return null;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorDifferenceLocal.java b/src/main/java/com/esri/core/geometry/OperatorDifferenceLocal.java
index cd1b3b3f..31db5027 100644
--- a/src/main/java/com/esri/core/geometry/OperatorDifferenceLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorDifferenceLocal.java
@@ -26,367 +26,332 @@
class OperatorDifferenceLocal extends OperatorDifference {
- @Override
- public GeometryCursor execute(GeometryCursor inputGeometries,
- GeometryCursor subtractor, SpatialReference sr,
- ProgressTracker progressTracker) {
- return new OperatorDifferenceCursor(inputGeometries, subtractor, sr,
- progressTracker);
- }
-
- @Override
- public Geometry execute(Geometry inputGeometry, Geometry subtractor,
- SpatialReference sr, ProgressTracker progressTracker) {
- SimpleGeometryCursor inputGeomCurs = new SimpleGeometryCursor(
- inputGeometry);
- SimpleGeometryCursor subractorCurs = new SimpleGeometryCursor(
- subtractor);
- GeometryCursor geometryCursor = execute(inputGeomCurs, subractorCurs,
- sr, progressTracker);
-
- return geometryCursor.next();
- }
-
- static Geometry difference(Geometry geometry_a, Geometry geometry_b,
- SpatialReference spatial_reference, ProgressTracker progress_tracker) {
- if (geometry_a.isEmpty() || geometry_b.isEmpty())
- return geometry_a;
-
- int dimension_a = geometry_a.getDimension();
- int dimension_b = geometry_b.getDimension();
-
- if (dimension_a > dimension_b)
- return geometry_a;
-
- int type_a = geometry_a.getType().value();
- int type_b = geometry_b.getType().value();
-
- Envelope2D env_a = new Envelope2D(), env_b = new Envelope2D(), env_merged = new Envelope2D();
- geometry_a.queryEnvelope2D(env_a);
- geometry_b.queryEnvelope2D(env_b);
- env_merged.setCoords(env_a);
- env_merged.merge(env_b);
-
- double tolerance = InternalUtils.calculateToleranceFromGeometry(
- spatial_reference, env_merged, false);
- double tolerance_cluster = tolerance * Math.sqrt(2.0) * 1.00001;
-
- Envelope2D env_a_inflated = new Envelope2D();
- env_a_inflated.setCoords(env_a);
- env_a_inflated.inflate(tolerance_cluster, tolerance_cluster); // inflate
- // by
- // cluster
- // tolerance
-
- if (!env_a_inflated.isIntersecting(env_b))
- return geometry_a;
-
- if (dimension_a == 1 && dimension_b == 2)
- return polylineMinusArea_(geometry_a, geometry_b, type_b,
- spatial_reference, progress_tracker);
-
- if (type_a == Geometry.GeometryType.Point) {
- Geometry geometry_b_;
- if (MultiPath.isSegment(type_b)) {
- geometry_b_ = new Polyline(geometry_b.getDescription());
- ((Polyline) (geometry_b_)).addSegment((Segment) (geometry_b),
- true);
- } else {
- geometry_b_ = geometry_b;
- }
- switch (type_b) {
- case Geometry.GeometryType.Polygon:
- return pointMinusPolygon_((Point) (geometry_a),
- (Polygon) (geometry_b_), tolerance, progress_tracker);
- case Geometry.GeometryType.Polyline:
- return pointMinusPolyline_((Point) (geometry_a),
- (Polyline) (geometry_b_), tolerance, progress_tracker);
- case Geometry.GeometryType.MultiPoint:
- return pointMinusMultiPoint_((Point) (geometry_a),
- (MultiPoint) (geometry_b_), tolerance, progress_tracker);
- case Geometry.GeometryType.Envelope:
- return pointMinusEnvelope_((Point) (geometry_a),
- (Envelope) (geometry_b_), tolerance, progress_tracker);
- case Geometry.GeometryType.Point:
- return pointMinusPoint_((Point) (geometry_a),
- (Point) (geometry_b_), tolerance, progress_tracker);
- default:
- throw new IllegalArgumentException();
- }
- } else if (type_a == Geometry.GeometryType.MultiPoint) {
- switch (type_b) {
- case Geometry.GeometryType.Polygon:
- return multiPointMinusPolygon_((MultiPoint) (geometry_a),
- (Polygon) (geometry_b), tolerance, progress_tracker);
- case Geometry.GeometryType.Envelope:
- return multiPointMinusEnvelope_((MultiPoint) (geometry_a),
- (Envelope) (geometry_b), tolerance, progress_tracker);
- case Geometry.GeometryType.Point:
- return multiPointMinusPoint_((MultiPoint) (geometry_a),
- (Point) (geometry_b), tolerance, progress_tracker);
- default:
- break;
- }
- }
- return TopologicalOperations.difference(geometry_a, geometry_b,
- spatial_reference, progress_tracker);
- }
-
- // these are special implementations, all others delegate to the topo-graph.
- static Geometry pointMinusPolygon_(Point point, Polygon polygon,
- double tolerance, ProgressTracker progress_tracker) {
- PolygonUtils.PiPResult result = PolygonUtils.isPointInPolygon2D(
- polygon, point, tolerance);
-
- if (result == PolygonUtils.PiPResult.PiPOutside)
- return point;
-
- return point.createInstance();
- }
-
- static Geometry pointMinusPolyline_(Point point, Polyline polyline,
- double tolerance, ProgressTracker progress_tracker) {
- Point2D pt = point.getXY();
- SegmentIterator seg_iter = polyline.querySegmentIterator();
-
- double tolerance_cluster = tolerance * Math.sqrt(2.0) * 1.00001;
- double tolerance_cluster_sq = tolerance_cluster * tolerance_cluster;
- Envelope2D env = new Envelope2D();
-
- while (seg_iter.nextPath()) {
- while (seg_iter.hasNextSegment()) {
- Segment segment = seg_iter.nextSegment();
-
- segment.queryEnvelope2D(env);
- env.inflate(tolerance_cluster, tolerance_cluster);
-
- if (!env.contains(pt))
- continue;
-
- if (segment.isIntersecting(pt, tolerance))
- return point.createInstance();
-
- // check segment end points to the cluster tolerance
- Point2D end_point = segment.getStartXY();
-
- if (Point2D.sqrDistance(pt, end_point) <= tolerance_cluster_sq)
- return point.createInstance();
-
- end_point = segment.getEndXY();
-
- if (Point2D.sqrDistance(pt, end_point) <= tolerance_cluster_sq)
- return point.createInstance();
- }
- }
-
- return point;
- }
-
- static Geometry pointMinusMultiPoint_(Point point, MultiPoint multi_point,
- double tolerance, ProgressTracker progress_tracker) {
- MultiPointImpl multipointImpl = (MultiPointImpl) (multi_point
- ._getImpl());
- AttributeStreamOfDbl position = (AttributeStreamOfDbl) multipointImpl
- .getAttributeStreamRef(VertexDescription.Semantics.POSITION);
- int point_count = multi_point.getPointCount();
- Point2D point2D = point.getXY();
- Point2D pt = new Point2D();
-
- double tolerance_cluster = tolerance * Math.sqrt(2.0) * 1.00001;
- double tolerance_cluster_sq = tolerance_cluster * tolerance_cluster;
-
- for (int i = 0; i < point_count; i++) {
- position.read(2 * i, pt);
- double sqr_dist = Point2D.sqrDistance(pt, point2D);
- if (sqr_dist <= tolerance_cluster_sq)
- return point.createInstance();// return an empty point.
- }
-
- return point;// return the input point
- }
-
- static Geometry pointMinusEnvelope_(Point point, Envelope envelope,
- double tolerance, ProgressTracker progress_tracker) {
- Envelope2D env = new Envelope2D();
- envelope.queryEnvelope2D(env);
- env.inflate(tolerance, tolerance);
-
- Point2D pt = point.getXY();
+ @Override
+ public GeometryCursor execute(GeometryCursor inputGeometries,
+ GeometryCursor subtractor, SpatialReference sr,
+ ProgressTracker progressTracker) {
+ return new OperatorDifferenceCursor(inputGeometries, subtractor, sr,
+ progressTracker);
+ }
+
+ @Override
+ public Geometry execute(Geometry inputGeometry, Geometry subtractor,
+ SpatialReference sr, ProgressTracker progressTracker) {
+ SimpleGeometryCursor inputGeomCurs = new SimpleGeometryCursor(
+ inputGeometry);
+ SimpleGeometryCursor subractorCurs = new SimpleGeometryCursor(
+ subtractor);
+ GeometryCursor geometryCursor = execute(inputGeomCurs, subractorCurs,
+ sr, progressTracker);
+
+ return geometryCursor.next();
+ }
+
+ static Geometry difference(Geometry geometry_a, Geometry geometry_b,
+ SpatialReference spatial_reference, ProgressTracker progress_tracker) {
+ if (geometry_a.isEmpty() || geometry_b.isEmpty())
+ return geometry_a;
+
+ int dimension_a = geometry_a.getDimension();
+ int dimension_b = geometry_b.getDimension();
+
+ if (dimension_a > dimension_b)
+ return geometry_a;
+
+ int type_a = geometry_a.getType().value();
+ int type_b = geometry_b.getType().value();
+
+ Envelope2D env_a = new Envelope2D(), env_b = new Envelope2D(), env_merged = new Envelope2D();
+ geometry_a.queryEnvelope2D(env_a);
+ geometry_b.queryEnvelope2D(env_b);
+ env_merged.setCoords(env_a);
+ env_merged.merge(env_b);
+
+ double tolerance = InternalUtils.calculateToleranceFromGeometry(
+ spatial_reference, env_merged, false);
+ double tolerance_cluster = tolerance * Math.sqrt(2.0) * 1.00001;
+
+ Envelope2D env_a_inflated = new Envelope2D();
+ env_a_inflated.setCoords(env_a);
+ env_a_inflated.inflate(tolerance_cluster, tolerance_cluster); // inflate
+ // by
+ // cluster
+ // tolerance
+
+ if (!env_a_inflated.isIntersecting(env_b))
+ return geometry_a;
+
+ if (type_a == Geometry.GeometryType.Point) {
+ Geometry geometry_b_;
+ if (MultiPath.isSegment(type_b)) {
+ geometry_b_ = new Polyline(geometry_b.getDescription());
+ ((Polyline) (geometry_b_)).addSegment((Segment) (geometry_b),
+ true);
+ } else {
+ geometry_b_ = geometry_b;
+ }
+ switch (type_b) {
+ case Geometry.GeometryType.Polygon:
+ return pointMinusPolygon_((Point) (geometry_a),
+ (Polygon) (geometry_b_), tolerance, progress_tracker);
+ case Geometry.GeometryType.Polyline:
+ return pointMinusPolyline_((Point) (geometry_a),
+ (Polyline) (geometry_b_), tolerance, progress_tracker);
+ case Geometry.GeometryType.MultiPoint:
+ return pointMinusMultiPoint_((Point) (geometry_a),
+ (MultiPoint) (geometry_b_), tolerance, progress_tracker);
+ case Geometry.GeometryType.Envelope:
+ return pointMinusEnvelope_((Point) (geometry_a),
+ (Envelope) (geometry_b_), tolerance, progress_tracker);
+ case Geometry.GeometryType.Point:
+ return pointMinusPoint_((Point) (geometry_a),
+ (Point) (geometry_b_), tolerance, progress_tracker);
+ default:
+ throw new IllegalArgumentException();
+ }
+ } else if (type_a == Geometry.GeometryType.MultiPoint) {
+ switch (type_b) {
+ case Geometry.GeometryType.Polygon:
+ return multiPointMinusPolygon_((MultiPoint) (geometry_a),
+ (Polygon) (geometry_b), tolerance, progress_tracker);
+ case Geometry.GeometryType.Envelope:
+ return multiPointMinusEnvelope_((MultiPoint) (geometry_a),
+ (Envelope) (geometry_b), tolerance, progress_tracker);
+ case Geometry.GeometryType.Point:
+ return multiPointMinusPoint_((MultiPoint) (geometry_a),
+ (Point) (geometry_b), tolerance, progress_tracker);
+ default:
+ break;
+ }
+ }
+ return TopologicalOperations.difference(geometry_a, geometry_b,
+ spatial_reference, progress_tracker);
+ }
+
+ // these are special implementations, all others delegate to the topo-graph.
+ static Geometry pointMinusPolygon_(Point point, Polygon polygon,
+ double tolerance, ProgressTracker progress_tracker) {
+ PolygonUtils.PiPResult result = PolygonUtils.isPointInPolygon2D(
+ polygon, point, tolerance);
+
+ if (result == PolygonUtils.PiPResult.PiPOutside)
+ return point;
+
+ return point.createInstance();
+ }
+
+ static Geometry pointMinusPolyline_(Point point, Polyline polyline,
+ double tolerance, ProgressTracker progress_tracker) {
+ Point2D pt = point.getXY();
+ SegmentIterator seg_iter = polyline.querySegmentIterator();
+
+ double tolerance_cluster = tolerance * Math.sqrt(2.0) * 1.00001;
+ double tolerance_cluster_sq = tolerance_cluster * tolerance_cluster;
+ Envelope2D env = new Envelope2D();
+
+ while (seg_iter.nextPath()) {
+ while (seg_iter.hasNextSegment()) {
+ Segment segment = seg_iter.nextSegment();
+
+ segment.queryEnvelope2D(env);
+ env.inflate(tolerance_cluster, tolerance_cluster);
+
+ if (!env.contains(pt))
+ continue;
+
+ if (segment.isIntersecting(pt, tolerance))
+ return point.createInstance();
+
+ // check segment end points to the cluster tolerance
+ Point2D end_point = segment.getStartXY();
+
+ if (Point2D.sqrDistance(pt, end_point) <= tolerance_cluster_sq)
+ return point.createInstance();
+
+ end_point = segment.getEndXY();
+
+ if (Point2D.sqrDistance(pt, end_point) <= tolerance_cluster_sq)
+ return point.createInstance();
+ }
+ }
+
+ return point;
+ }
+
+ static Geometry pointMinusMultiPoint_(Point point, MultiPoint multi_point,
+ double tolerance, ProgressTracker progress_tracker) {
+ MultiPointImpl multipointImpl = (MultiPointImpl) (multi_point
+ ._getImpl());
+ AttributeStreamOfDbl position = (AttributeStreamOfDbl) multipointImpl
+ .getAttributeStreamRef(VertexDescription.Semantics.POSITION);
+ int point_count = multi_point.getPointCount();
+ Point2D point2D = point.getXY();
+ Point2D pt = new Point2D();
+
+ double tolerance_cluster = tolerance * Math.sqrt(2.0) * 1.00001;
+ double tolerance_cluster_sq = tolerance_cluster * tolerance_cluster;
+
+ for (int i = 0; i < point_count; i++) {
+ position.read(2 * i, pt);
+ double sqr_dist = Point2D.sqrDistance(pt, point2D);
+ if (sqr_dist <= tolerance_cluster_sq)
+ return point.createInstance();// return an empty point.
+ }
+
+ return point;// return the input point
+ }
+
+ static Geometry pointMinusEnvelope_(Point point, Envelope envelope,
+ double tolerance, ProgressTracker progress_tracker) {
+ Envelope2D env = new Envelope2D();
+ envelope.queryEnvelope2D(env);
+ env.inflate(tolerance, tolerance);
+
+ Point2D pt = point.getXY();
- if (!env.contains(pt))
- return point;
+ if (!env.contains(pt))
+ return point;
- return point.createInstance();
- }
+ return point.createInstance();
+ }
- static Geometry pointMinusPoint_(Point point_a, Point point_b,
- double tolerance, ProgressTracker progress_tracker) {
- double tolerance_cluster = tolerance * Math.sqrt(2.0) * 1.00001;
- double tolerance_cluster_sq = tolerance_cluster * tolerance_cluster;
+ static Geometry pointMinusPoint_(Point point_a, Point point_b,
+ double tolerance, ProgressTracker progress_tracker) {
+ double tolerance_cluster = tolerance * Math.sqrt(2.0) * 1.00001;
+ double tolerance_cluster_sq = tolerance_cluster * tolerance_cluster;
- Point2D pt_a = point_a.getXY();
- Point2D pt_b = point_b.getXY();
+ Point2D pt_a = point_a.getXY();
+ Point2D pt_b = point_b.getXY();
- if (Point2D.sqrDistance(pt_a, pt_b) <= tolerance_cluster_sq)
- return point_a.createInstance(); // return empty point
+ if (Point2D.sqrDistance(pt_a, pt_b) <= tolerance_cluster_sq)
+ return point_a.createInstance(); // return empty point
- return point_a;
- }
+ return point_a;
+ }
- static Geometry multiPointMinusPolygon_(MultiPoint multi_point,
- Polygon polygon, double tolerance, ProgressTracker progress_tracker) {
- Envelope2D env = new Envelope2D();
- polygon.queryEnvelope2D(env);
- env.inflate(tolerance, tolerance);
+ static Geometry multiPointMinusPolygon_(MultiPoint multi_point,
+ Polygon polygon, double tolerance, ProgressTracker progress_tracker) {
+ Envelope2D env = new Envelope2D();
+ polygon.queryEnvelope2D(env);
+ env.inflate(tolerance, tolerance);
- int point_count = multi_point.getPointCount();
+ int point_count = multi_point.getPointCount();
- boolean b_found_covered = false;
- boolean[] covered = new boolean[point_count];
- for (int i = 0; i < point_count; i++)
- covered[i] = false;
+ boolean b_found_covered = false;
+ boolean[] covered = new boolean[point_count];
+ for (int i = 0; i < point_count; i++)
+ covered[i] = false;
- Point2D pt = new Point2D();
+ Point2D pt = new Point2D();
- for (int i = 0; i < point_count; i++) {
- multi_point.getXY(i, pt);
+ for (int i = 0; i < point_count; i++) {
+ multi_point.getXY(i, pt);
- if (!env.contains(pt))
- continue;
+ if (!env.contains(pt))
+ continue;
- PolygonUtils.PiPResult result = PolygonUtils.isPointInPolygon2D(
- polygon, pt, tolerance);
+ PolygonUtils.PiPResult result = PolygonUtils.isPointInPolygon2D(
+ polygon, pt, tolerance);
- if (result == PolygonUtils.PiPResult.PiPOutside)
- continue;
+ if (result == PolygonUtils.PiPResult.PiPOutside)
+ continue;
- b_found_covered = true;
- covered[i] = true;
- }
+ b_found_covered = true;
+ covered[i] = true;
+ }
- if (!b_found_covered)
- return multi_point;
+ if (!b_found_covered)
+ return multi_point;
- MultiPoint new_multipoint = (MultiPoint) multi_point.createInstance();
+ MultiPoint new_multipoint = (MultiPoint) multi_point.createInstance();
- for (int i = 0; i < point_count; i++) {
- if (!covered[i])
- new_multipoint.add(multi_point, i, i + 1);
- }
+ for (int i = 0; i < point_count; i++) {
+ if (!covered[i])
+ new_multipoint.add(multi_point, i, i + 1);
+ }
- return new_multipoint;
- }
+ return new_multipoint;
+ }
- static Geometry multiPointMinusEnvelope_(MultiPoint multi_point,
- Envelope envelope, double tolerance,
- ProgressTracker progress_tracker) {
- Envelope2D env = new Envelope2D();
- envelope.queryEnvelope2D(env);
- env.inflate(tolerance, tolerance);
+ static Geometry multiPointMinusEnvelope_(MultiPoint multi_point,
+ Envelope envelope, double tolerance,
+ ProgressTracker progress_tracker) {
+ Envelope2D env = new Envelope2D();
+ envelope.queryEnvelope2D(env);
+ env.inflate(tolerance, tolerance);
- int point_count = multi_point.getPointCount();
+ int point_count = multi_point.getPointCount();
- boolean b_found_covered = false;
- boolean[] covered = new boolean[point_count];
- for (int i = 0; i < point_count; i++)
- covered[i] = false;
+ boolean b_found_covered = false;
+ boolean[] covered = new boolean[point_count];
+ for (int i = 0; i < point_count; i++)
+ covered[i] = false;
- Point2D pt = new Point2D();
+ Point2D pt = new Point2D();
- for (int i = 0; i < point_count; i++) {
- multi_point.getXY(i, pt);
+ for (int i = 0; i < point_count; i++) {
+ multi_point.getXY(i, pt);
- if (!env.contains(pt))
- continue;
+ if (!env.contains(pt))
+ continue;
- b_found_covered = true;
- covered[i] = true;
- }
+ b_found_covered = true;
+ covered[i] = true;
+ }
- if (!b_found_covered)
- return multi_point;
+ if (!b_found_covered)
+ return multi_point;
- MultiPoint new_multipoint = (MultiPoint) multi_point.createInstance();
+ MultiPoint new_multipoint = (MultiPoint) multi_point.createInstance();
- for (int i = 0; i < point_count; i++) {
- if (!covered[i])
- new_multipoint.add(multi_point, i, i + 1);
- }
+ for (int i = 0; i < point_count; i++) {
+ if (!covered[i])
+ new_multipoint.add(multi_point, i, i + 1);
+ }
- return new_multipoint;
- }
+ return new_multipoint;
+ }
- static Geometry multiPointMinusPoint_(MultiPoint multi_point, Point point,
- double tolerance, ProgressTracker progress_tracker) {
- MultiPointImpl multipointImpl = (MultiPointImpl) (multi_point
- ._getImpl());
- AttributeStreamOfDbl position = (AttributeStreamOfDbl) (multipointImpl
- .getAttributeStreamRef(VertexDescription.Semantics.POSITION));
- int point_count = multi_point.getPointCount();
- Point2D point2D = point.getXY();
- Point2D pt = new Point2D();
+ static Geometry multiPointMinusPoint_(MultiPoint multi_point, Point point,
+ double tolerance, ProgressTracker progress_tracker) {
+ MultiPointImpl multipointImpl = (MultiPointImpl) (multi_point
+ ._getImpl());
+ AttributeStreamOfDbl position = (AttributeStreamOfDbl) (multipointImpl
+ .getAttributeStreamRef(VertexDescription.Semantics.POSITION));
+ int point_count = multi_point.getPointCount();
+ Point2D point2D = point.getXY();
+ Point2D pt = new Point2D();
- boolean b_found_covered = false;
- boolean[] covered = new boolean[point_count];
- for (int i = 0; i < point_count; i++)
- covered[i] = false;
+ boolean b_found_covered = false;
+ boolean[] covered = new boolean[point_count];
+ for (int i = 0; i < point_count; i++)
+ covered[i] = false;
- double tolerance_cluster = tolerance * Math.sqrt(2.0) * 1.00001;
- double tolerance_cluster_sq = tolerance_cluster * tolerance_cluster;
+ double tolerance_cluster = tolerance * Math.sqrt(2.0) * 1.00001;
+ double tolerance_cluster_sq = tolerance_cluster * tolerance_cluster;
- for (int i = 0; i < point_count; i++) {
- position.read(2 * i, pt);
+ for (int i = 0; i < point_count; i++) {
+ position.read(2 * i, pt);
- double sqr_dist = Point2D.sqrDistance(pt, point2D);
+ double sqr_dist = Point2D.sqrDistance(pt, point2D);
- if (sqr_dist <= tolerance_cluster_sq) {
- b_found_covered = true;
- covered[i] = true;
- }
- }
+ if (sqr_dist <= tolerance_cluster_sq) {
+ b_found_covered = true;
+ covered[i] = true;
+ }
+ }
- if (!b_found_covered)
- return multi_point;
+ if (!b_found_covered)
+ return multi_point;
- MultiPoint new_multipoint = (MultiPoint) (multi_point.createInstance());
+ MultiPoint new_multipoint = (MultiPoint) (multi_point.createInstance());
- for (int i = 0; i < point_count; i++) {
- if (!covered[i])
- new_multipoint.add(multi_point, i, i + 1);
- }
-
- return new_multipoint;
- }
-
- static Geometry polylineMinusArea_(Geometry geometry, Geometry area,
- int area_type, SpatialReference sr, ProgressTracker progress_tracker) {
- // construct the complement of the Polygon (or Envelope)
- Envelope envelope = new Envelope();
- geometry.queryEnvelope(envelope);
- Envelope2D env_2D = new Envelope2D();
- area.queryEnvelope2D(env_2D);
- envelope.merge(env_2D);
- double dw = 0.1 * envelope.getWidth();
- double dh = 0.1 * envelope.getHeight();
- envelope.inflate(dw, dh);
-
- Polygon complement = new Polygon();
- complement.addEnvelope(envelope, false);
-
- MultiPathImpl complementImpl = (MultiPathImpl) (complement._getImpl());
-
- if (area_type == Geometry.GeometryType.Polygon) {
- MultiPathImpl polygonImpl = (MultiPathImpl) (area._getImpl());
- complementImpl.add(polygonImpl, true);
- } else
- complementImpl.addEnvelope((Envelope) (area), true);
-
- OperatorFactoryLocal projEnv = OperatorFactoryLocal.getInstance();
- OperatorIntersection operatorIntersection = (OperatorIntersection) projEnv
- .getOperator(Operator.Type.Intersection);
- Geometry difference = operatorIntersection.execute(geometry,
- complement, sr, progress_tracker);
- return difference;
- }
+ for (int i = 0; i < point_count; i++) {
+ if (!covered[i])
+ new_multipoint.add(multi_point, i, i + 1);
+ }
+ return new_multipoint;
+ }
}
+
diff --git a/src/main/java/com/esri/core/geometry/OperatorDisjoint.java b/src/main/java/com/esri/core/geometry/OperatorDisjoint.java
index 6c703f5f..9404759f 100644
--- a/src/main/java/com/esri/core/geometry/OperatorDisjoint.java
+++ b/src/main/java/com/esri/core/geometry/OperatorDisjoint.java
@@ -31,14 +31,14 @@
*/
public abstract class OperatorDisjoint extends OperatorSimpleRelation {
- @Override
- public Type getType() {
- return Type.Disjoint;
- }
-
- public static OperatorDisjoint local() {
- return (OperatorDisjoint) OperatorFactoryLocal.getInstance()
- .getOperator(Type.Disjoint);
- }
+ @Override
+ public Type getType() {
+ return Type.Disjoint;
+ }
+
+ public static OperatorDisjoint local() {
+ return (OperatorDisjoint) OperatorFactoryLocal.getInstance()
+ .getOperator(Type.Disjoint);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorDisjointLocal.java b/src/main/java/com/esri/core/geometry/OperatorDisjointLocal.java
index 3229d70e..6b2ab840 100644
--- a/src/main/java/com/esri/core/geometry/OperatorDisjointLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorDisjointLocal.java
@@ -25,11 +25,11 @@
package com.esri.core.geometry;
class OperatorDisjointLocal extends OperatorDisjoint {
- @Override
- public boolean execute(Geometry inputGeom1, Geometry inputGeom2,
- SpatialReference sr, ProgressTracker progressTracker) {
- return RelationalOperations.relate(inputGeom1, inputGeom2, sr,
- RelationalOperations.Relation.disjoint, progressTracker);
- }
+ @Override
+ public boolean execute(Geometry inputGeom1, Geometry inputGeom2,
+ SpatialReference sr, ProgressTracker progressTracker) {
+ return RelationalOperations.relate(inputGeom1, inputGeom2, sr,
+ RelationalOperations.Relation.disjoint, progressTracker);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorDistance.java b/src/main/java/com/esri/core/geometry/OperatorDistance.java
index 56b70976..6141f6f8 100644
--- a/src/main/java/com/esri/core/geometry/OperatorDistance.java
+++ b/src/main/java/com/esri/core/geometry/OperatorDistance.java
@@ -31,20 +31,20 @@
*/
public abstract class OperatorDistance extends Operator {
- @Override
- public Type getType() {
- return Type.Distance;
- }
-
- /**
- * Calculates distance between two geometries.
- */
- public abstract double execute(Geometry geom1, Geometry geom2,
- ProgressTracker progressTracker);
-
- public static OperatorDistance local() {
- return (OperatorDistance) OperatorFactoryLocal.getInstance()
- .getOperator(Type.Distance);
- }
+ @Override
+ public Type getType() {
+ return Type.Distance;
+ }
+
+ /**
+ * Calculates distance between two geometries.
+ */
+ public abstract double execute(Geometry geom1, Geometry geom2,
+ ProgressTracker progressTracker);
+
+ public static OperatorDistance local() {
+ return (OperatorDistance) OperatorFactoryLocal.getInstance()
+ .getOperator(Type.Distance);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorDistanceLocal.java b/src/main/java/com/esri/core/geometry/OperatorDistanceLocal.java
index 2c2d5880..ca3b305c 100644
--- a/src/main/java/com/esri/core/geometry/OperatorDistanceLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorDistanceLocal.java
@@ -26,417 +26,417 @@
class OperatorDistanceLocal extends OperatorDistance {
- /**
- * Performs the Distance operation on two geometries
- *
- * @return Returns a double.
- */
- @Override
- public double execute(Geometry geom1, Geometry geom2,
- ProgressTracker progressTracker) {
- if (null == geom1 || null == geom2) {
- throw new IllegalArgumentException();
- }
-
- Geometry geometryA = geom1;
- Geometry geometryB = geom2;
-
- if (geometryA.isEmpty() || geometryB.isEmpty())
- return NumberUtils.TheNaN;
-
- Polygon polygonA;
- Polygon polygonB;
- MultiPoint multiPointA;
- MultiPoint multiPointB;
-
- // if geometryA is an envelope use a polygon instead (if geom1 was
- // folded, then geometryA will already be a polygon)
- // if geometryA is a point use a multipoint instead
- Geometry.Type gtA = geometryA.getType();
- Geometry.Type gtB = geometryB.getType();
- if (gtA == Geometry.Type.Point) {
- if (gtB == Geometry.Type.Point) {
- return Point2D.distance(((Point) geometryA).getXY(), ((Point) geometryB).getXY());
- } else if (gtB == Geometry.Type.Envelope) {
- Envelope2D envB = new Envelope2D();
- geometryB.queryEnvelope2D(envB);
- return envB.distance(((Point) geometryA).getXY());
- }
-
- multiPointA = new MultiPoint();
- multiPointA.add((Point) geometryA);
- geometryA = multiPointA;
- } else if (gtA == Geometry.Type.Envelope) {
- if (gtB == Geometry.Type.Envelope) {
- Envelope2D envA = new Envelope2D();
- geometryA.queryEnvelope2D(envA);
- Envelope2D envB = new Envelope2D();
- geometryB.queryEnvelope2D(envB);
- return envB.distance(envA);
- }
- polygonA = new Polygon();
- polygonA.addEnvelope((Envelope) geometryA, false);
- geometryA = polygonA;
- }
-
- // if geom_2 is an envelope use a polygon instead
- // if geom_2 is a point use a multipoint instead
- if (gtB == Geometry.Type.Point) {
- multiPointB = new MultiPoint();
- multiPointB.add((Point) geometryB);
- geometryB = multiPointB;
- } else if (gtB == Geometry.Type.Envelope) {
- polygonB = new Polygon();
- polygonB.addEnvelope((Envelope) geometryB, false);
- geometryB = polygonB;
- }
-
- DistanceCalculator distanceCalculator = new DistanceCalculator(
- progressTracker);
- double distance = distanceCalculator.calculate(geometryA, geometryB);
- return distance;
- }
-
- // Implementation of distance algorithm.
- class DistanceCalculator {
- private ProgressTracker m_progressTracker;
- private Envelope2D m_env2DgeometryA;
- private Envelope2D m_env2DgeometryB;
-
- private void swapEnvelopes_() {
- double temp;
- // swap xmin
- temp = m_env2DgeometryA.xmin;
- m_env2DgeometryA.xmin = m_env2DgeometryB.xmin;
- m_env2DgeometryB.xmin = temp;
- // swap xmax
- temp = m_env2DgeometryA.xmax;
- m_env2DgeometryA.xmax = m_env2DgeometryB.xmax;
- m_env2DgeometryB.xmax = temp;
- // swap ymin
- temp = m_env2DgeometryA.ymin;
- m_env2DgeometryA.ymin = m_env2DgeometryB.ymin;
- m_env2DgeometryB.ymin = temp;
- // swap ymax
- temp = m_env2DgeometryA.ymax;
- m_env2DgeometryA.ymax = m_env2DgeometryB.ymax;
- m_env2DgeometryB.ymax = temp;
- }
-
- private double executeBruteForce_(/* const */Geometry geometryA, /* const */
- Geometry geometryB) {
- if ((m_progressTracker != null)
- && !(m_progressTracker.progress(-1, -1)))
- throw new RuntimeException("user_canceled");
-
- boolean geometriesAreDisjoint = !m_env2DgeometryA
- .isIntersecting(m_env2DgeometryB);
- if (Geometry.isMultiPath(geometryA.getType().value())
- && Geometry.isMultiPath(geometryB.getType().value())) { // MultiPath
- // vs.
- // MultiPath
- // choose
- // the
- // multipath
- // with
- // more
- // points
- // to
- // be
- // geometryA,
- // this
- // way
- // more
- // of
- // geometryA
- // segments
- // can
- // be
- // disqualified
- // more
- // quickly
- // by
- // testing
- // segmentA
- // envelope
- // vs.
- // geometryB
- // envelope
- if (((MultiPath) geometryA).getPointCount() > ((MultiPath) geometryB)
- .getPointCount())
- return bruteForceMultiPathMultiPath_((MultiPath) geometryA,
- (MultiPath) geometryB, geometriesAreDisjoint);
- swapEnvelopes_();
- double answer = bruteForceMultiPathMultiPath_(
- (MultiPath) geometryB, (MultiPath) geometryA,
- geometriesAreDisjoint);
- swapEnvelopes_();
- return answer;
- } else if (geometryA.getType() == Geometry.Type.MultiPoint
- && Geometry.isMultiPath(geometryB.getType().value())) { // MultiPoint
- // vs.
- // MultiPath
- swapEnvelopes_();
- double answer = bruteForceMultiPathMultiPoint_(
- (MultiPath) geometryB, (MultiPoint) geometryA,
- geometriesAreDisjoint);
- swapEnvelopes_();
- return answer;
- } else if (geometryB.getType() == Geometry.Type.MultiPoint
- && Geometry.isMultiPath(geometryA.getType().value())) { // MultiPath
- // vs.
- // MultiPoint
- return bruteForceMultiPathMultiPoint_((MultiPath) geometryA,
- (MultiPoint) geometryB, geometriesAreDisjoint);
- } else if (geometryA.getType() == Geometry.Type.MultiPoint
- && geometryB.getType() == Geometry.Type.MultiPoint) { // MultiPoint
- // vs.
- // MultiPoint
- // choose
- // the
- // multipoint
- // with
- // more
- // vertices
- // to
- // be
- // the
- // "geometryA",
- // this
- // way
- // more
- // points
- // can
- // be
- // potentially
- // excluded
- // by
- // envelope
- // distance
- // tests.
- if (((MultiPoint) geometryA).getPointCount() > ((MultiPoint) geometryB)
- .getPointCount())
- return bruteForceMultiPointMultiPoint_(
- (MultiPoint) geometryA, (MultiPoint) geometryB,
- geometriesAreDisjoint);
- swapEnvelopes_();
- double answer = bruteForceMultiPointMultiPoint_(
- (MultiPoint) geometryB, (MultiPoint) geometryA,
- geometriesAreDisjoint);
- swapEnvelopes_();
- return answer;
- }
- return 0.0;
- }
-
- private double bruteForceMultiPathMultiPath_(
- /* const */MultiPath geometryA, /* const */MultiPath geometryB,
- boolean geometriesAreDisjoint) {
- // It may be beneficial to have the geometry with less vertices
- // always be geometryA.
- SegmentIterator segIterA = geometryA.querySegmentIterator();
- SegmentIterator segIterB = geometryB.querySegmentIterator();
- Envelope2D env2DSegmentA = new Envelope2D();
- Envelope2D env2DSegmentB = new Envelope2D();
-
- double minSqrDistance = NumberUtils.doubleMax();
-
- if (!geometriesAreDisjoint) {
- // Geometries might be non-disjoint. Check if they intersect
- // using point-in-polygon tests
- if (weakIntersectionTest_(geometryA, geometryB, segIterA,
- segIterB))
- return 0.0;
- }
-
- // if geometries are known disjoint, don't bother to do any tests
- // for polygon containment
-
- // nested while-loop insanity
- while (segIterA.nextPath()) {
- while (segIterA.hasNextSegment()) {
+ /**
+ * Performs the Distance operation on two geometries
+ *
+ * @return Returns a double.
+ */
+ @Override
+ public double execute(Geometry geom1, Geometry geom2,
+ ProgressTracker progressTracker) {
+ if (null == geom1 || null == geom2) {
+ throw new IllegalArgumentException();
+ }
+
+ Geometry geometryA = geom1;
+ Geometry geometryB = geom2;
+
+ if (geometryA.isEmpty() || geometryB.isEmpty())
+ return NumberUtils.TheNaN;
+
+ Polygon polygonA;
+ Polygon polygonB;
+ MultiPoint multiPointA;
+ MultiPoint multiPointB;
+
+ // if geometryA is an envelope use a polygon instead (if geom1 was
+ // folded, then geometryA will already be a polygon)
+ // if geometryA is a point use a multipoint instead
+ Geometry.Type gtA = geometryA.getType();
+ Geometry.Type gtB = geometryB.getType();
+ if (gtA == Geometry.Type.Point) {
+ if (gtB == Geometry.Type.Point) {
+ return Point2D.distance(((Point) geometryA).getXY(), ((Point) geometryB).getXY());
+ } else if (gtB == Geometry.Type.Envelope) {
+ Envelope2D envB = new Envelope2D();
+ geometryB.queryEnvelope2D(envB);
+ return envB.distance(((Point) geometryA).getXY());
+ }
+
+ multiPointA = new MultiPoint();
+ multiPointA.add((Point) geometryA);
+ geometryA = multiPointA;
+ } else if (gtA == Geometry.Type.Envelope) {
+ if (gtB == Geometry.Type.Envelope) {
+ Envelope2D envA = new Envelope2D();
+ geometryA.queryEnvelope2D(envA);
+ Envelope2D envB = new Envelope2D();
+ geometryB.queryEnvelope2D(envB);
+ return envB.distance(envA);
+ }
+ polygonA = new Polygon();
+ polygonA.addEnvelope((Envelope) geometryA, false);
+ geometryA = polygonA;
+ }
+
+ // if geom_2 is an envelope use a polygon instead
+ // if geom_2 is a point use a multipoint instead
+ if (gtB == Geometry.Type.Point) {
+ multiPointB = new MultiPoint();
+ multiPointB.add((Point) geometryB);
+ geometryB = multiPointB;
+ } else if (gtB == Geometry.Type.Envelope) {
+ polygonB = new Polygon();
+ polygonB.addEnvelope((Envelope) geometryB, false);
+ geometryB = polygonB;
+ }
+
+ DistanceCalculator distanceCalculator = new DistanceCalculator(
+ progressTracker);
+ double distance = distanceCalculator.calculate(geometryA, geometryB);
+ return distance;
+ }
+
+ // Implementation of distance algorithm.
+ class DistanceCalculator {
+ private ProgressTracker m_progressTracker;
+ private Envelope2D m_env2DgeometryA;
+ private Envelope2D m_env2DgeometryB;
+
+ private void swapEnvelopes_() {
+ double temp;
+ // swap xmin
+ temp = m_env2DgeometryA.xmin;
+ m_env2DgeometryA.xmin = m_env2DgeometryB.xmin;
+ m_env2DgeometryB.xmin = temp;
+ // swap xmax
+ temp = m_env2DgeometryA.xmax;
+ m_env2DgeometryA.xmax = m_env2DgeometryB.xmax;
+ m_env2DgeometryB.xmax = temp;
+ // swap ymin
+ temp = m_env2DgeometryA.ymin;
+ m_env2DgeometryA.ymin = m_env2DgeometryB.ymin;
+ m_env2DgeometryB.ymin = temp;
+ // swap ymax
+ temp = m_env2DgeometryA.ymax;
+ m_env2DgeometryA.ymax = m_env2DgeometryB.ymax;
+ m_env2DgeometryB.ymax = temp;
+ }
+
+ private double executeBruteForce_(/* const */Geometry geometryA, /* const */
+ Geometry geometryB) {
+ if ((m_progressTracker != null)
+ && !(m_progressTracker.progress(-1, -1)))
+ throw new RuntimeException("user_canceled");
+
+ boolean geometriesAreDisjoint = !m_env2DgeometryA
+ .isIntersecting(m_env2DgeometryB);
+ if (Geometry.isMultiPath(geometryA.getType().value())
+ && Geometry.isMultiPath(geometryB.getType().value())) { // MultiPath
+ // vs.
+ // MultiPath
+ // choose
+ // the
+ // multipath
+ // with
+ // more
+ // points
+ // to
+ // be
+ // geometryA,
+ // this
+ // way
+ // more
+ // of
+ // geometryA
+ // segments
+ // can
+ // be
+ // disqualified
+ // more
+ // quickly
+ // by
+ // testing
+ // segmentA
+ // envelope
+ // vs.
+ // geometryB
+ // envelope
+ if (((MultiPath) geometryA).getPointCount() > ((MultiPath) geometryB)
+ .getPointCount())
+ return bruteForceMultiPathMultiPath_((MultiPath) geometryA,
+ (MultiPath) geometryB, geometriesAreDisjoint);
+ swapEnvelopes_();
+ double answer = bruteForceMultiPathMultiPath_(
+ (MultiPath) geometryB, (MultiPath) geometryA,
+ geometriesAreDisjoint);
+ swapEnvelopes_();
+ return answer;
+ } else if (geometryA.getType() == Geometry.Type.MultiPoint
+ && Geometry.isMultiPath(geometryB.getType().value())) { // MultiPoint
+ // vs.
+ // MultiPath
+ swapEnvelopes_();
+ double answer = bruteForceMultiPathMultiPoint_(
+ (MultiPath) geometryB, (MultiPoint) geometryA,
+ geometriesAreDisjoint);
+ swapEnvelopes_();
+ return answer;
+ } else if (geometryB.getType() == Geometry.Type.MultiPoint
+ && Geometry.isMultiPath(geometryA.getType().value())) { // MultiPath
+ // vs.
+ // MultiPoint
+ return bruteForceMultiPathMultiPoint_((MultiPath) geometryA,
+ (MultiPoint) geometryB, geometriesAreDisjoint);
+ } else if (geometryA.getType() == Geometry.Type.MultiPoint
+ && geometryB.getType() == Geometry.Type.MultiPoint) { // MultiPoint
+ // vs.
+ // MultiPoint
+ // choose
+ // the
+ // multipoint
+ // with
+ // more
+ // vertices
+ // to
+ // be
+ // the
+ // "geometryA",
+ // this
+ // way
+ // more
+ // points
+ // can
+ // be
+ // potentially
+ // excluded
+ // by
+ // envelope
+ // distance
+ // tests.
+ if (((MultiPoint) geometryA).getPointCount() > ((MultiPoint) geometryB)
+ .getPointCount())
+ return bruteForceMultiPointMultiPoint_(
+ (MultiPoint) geometryA, (MultiPoint) geometryB,
+ geometriesAreDisjoint);
+ swapEnvelopes_();
+ double answer = bruteForceMultiPointMultiPoint_(
+ (MultiPoint) geometryB, (MultiPoint) geometryA,
+ geometriesAreDisjoint);
+ swapEnvelopes_();
+ return answer;
+ }
+ return 0.0;
+ }
+
+ private double bruteForceMultiPathMultiPath_(
+ /* const */MultiPath geometryA, /* const */MultiPath geometryB,
+ boolean geometriesAreDisjoint) {
+ // It may be beneficial to have the geometry with less vertices
+ // always be geometryA.
+ SegmentIterator segIterA = geometryA.querySegmentIterator();
+ SegmentIterator segIterB = geometryB.querySegmentIterator();
+ Envelope2D env2DSegmentA = new Envelope2D();
+ Envelope2D env2DSegmentB = new Envelope2D();
+
+ double minSqrDistance = NumberUtils.doubleMax();
+
+ if (!geometriesAreDisjoint) {
+ // Geometries might be non-disjoint. Check if they intersect
+ // using point-in-polygon tests
+ if (weakIntersectionTest_(geometryA, geometryB, segIterA,
+ segIterB))
+ return 0.0;
+ }
+
+ // if geometries are known disjoint, don't bother to do any tests
+ // for polygon containment
+
+ // nested while-loop insanity
+ while (segIterA.nextPath()) {
+ while (segIterA.hasNextSegment()) {
/* const */
- Segment segmentA = segIterA.nextSegment();
- segmentA.queryEnvelope2D(env2DSegmentA);
- if (env2DSegmentA.sqrDistance(m_env2DgeometryB) > minSqrDistance)
- continue;
+ Segment segmentA = segIterA.nextSegment();
+ segmentA.queryEnvelope2D(env2DSegmentA);
+ if (env2DSegmentA.sqrDistance(m_env2DgeometryB) > minSqrDistance)
+ continue;
- while (segIterB.nextPath()) {
- while (segIterB.hasNextSegment()) {
+ while (segIterB.nextPath()) {
+ while (segIterB.hasNextSegment()) {
/* const */
- Segment segmentB = segIterB
- .nextSegment();
- segmentB.queryEnvelope2D(env2DSegmentB);
- if (env2DSegmentA.sqrDistance(env2DSegmentB) < minSqrDistance) {
- // get distance between segments
- double sqrDistance = segmentA.distance(
- segmentB, geometriesAreDisjoint);
- sqrDistance *= sqrDistance;
- if (sqrDistance < minSqrDistance) {
- if (sqrDistance == 0.0)
- return 0.0;
-
- minSqrDistance = sqrDistance;
- }
- }
- }
- }
- segIterB.resetToFirstPath();
- }
- }
-
- return Math.sqrt(minSqrDistance);
- }
-
- private double bruteForceMultiPathMultiPoint_(
- /* const */MultiPath geometryA, /* const */
- MultiPoint geometryB, boolean geometriesAreDisjoint) {
- SegmentIterator segIterA = geometryA.querySegmentIterator();
-
- Envelope2D env2DSegmentA = new Envelope2D();
-
- double minSqrDistance = NumberUtils.doubleMax();
-
- Point2D inputPoint = new Point2D();
- double t = -1;
- double sqrDistance = minSqrDistance;
+ Segment segmentB = segIterB
+ .nextSegment();
+ segmentB.queryEnvelope2D(env2DSegmentB);
+ if (env2DSegmentA.sqrDistance(env2DSegmentB) < minSqrDistance) {
+ // get distance between segments
+ double sqrDistance = segmentA.distance(
+ segmentB, geometriesAreDisjoint);
+ sqrDistance *= sqrDistance;
+ if (sqrDistance < minSqrDistance) {
+ if (sqrDistance == 0.0)
+ return 0.0;
+
+ minSqrDistance = sqrDistance;
+ }
+ }
+ }
+ }
+ segIterB.resetToFirstPath();
+ }
+ }
+
+ return Math.sqrt(minSqrDistance);
+ }
+
+ private double bruteForceMultiPathMultiPoint_(
+ /* const */MultiPath geometryA, /* const */
+ MultiPoint geometryB, boolean geometriesAreDisjoint) {
+ SegmentIterator segIterA = geometryA.querySegmentIterator();
+
+ Envelope2D env2DSegmentA = new Envelope2D();
+
+ double minSqrDistance = NumberUtils.doubleMax();
+
+ Point2D inputPoint = new Point2D();
+ double t = -1;
+ double sqrDistance = minSqrDistance;
/* const */
- MultiPointImpl multiPointImplB = (MultiPointImpl) geometryB
- ._getImpl();
- int pointCountB = multiPointImplB.getPointCount();
- boolean bDoPiPTest = !geometriesAreDisjoint
- && (geometryA.getType() == Geometry.Type.Polygon);
-
- while (segIterA.nextPath()) {
- while (segIterA.hasNextSegment()) {
+ MultiPointImpl multiPointImplB = (MultiPointImpl) geometryB
+ ._getImpl();
+ int pointCountB = multiPointImplB.getPointCount();
+ boolean bDoPiPTest = !geometriesAreDisjoint
+ && (geometryA.getType() == Geometry.Type.Polygon);
+
+ while (segIterA.nextPath()) {
+ while (segIterA.hasNextSegment()) {
/* const */
- Segment segmentA = segIterA.nextSegment();
- segmentA.queryEnvelope2D(env2DSegmentA);
- // if multipointB has only 1 vertex then it is faster to not
- // test for
- // env2DSegmentA.distance(env2DgeometryB)
- if (pointCountB > 1
- && env2DSegmentA.sqrDistance(m_env2DgeometryB) > minSqrDistance)
- continue;
-
- for (int i = 0; i < pointCountB; i++) {
- multiPointImplB.getXY(i, inputPoint);
- if (bDoPiPTest) {
- // Test for polygon containment. This takes the
- // place of a more general intersection test at the
- // beginning of the operator
- if (PolygonUtils.isPointInPolygon2D(
- (Polygon) geometryA, inputPoint, 0) != PolygonUtils.PiPResult.PiPOutside)
- return 0.0;
- }
-
- t = segmentA.getClosestCoordinate(inputPoint, false);
- inputPoint.sub(segmentA.getCoord2D(t));
- sqrDistance = inputPoint.sqrLength();
- if (sqrDistance < minSqrDistance) {
- if (sqrDistance == 0.0)
- return 0.0;
-
- minSqrDistance = sqrDistance;
- }
- }
-
- // No need to do point-in-polygon anymore (if it is a
- // polygon vs polyline)
- bDoPiPTest = false;
- }
- }
- return Math.sqrt(minSqrDistance);
- }
-
- private double bruteForceMultiPointMultiPoint_(
- /* const */MultiPoint geometryA, /* const */
- MultiPoint geometryB, boolean geometriesAreDisjoint) {
- double minSqrDistance = NumberUtils.doubleMax();
-
- Point2D pointA = new Point2D();
- Point2D pointB = new Point2D();
-
- double sqrDistance = minSqrDistance;
+ Segment segmentA = segIterA.nextSegment();
+ segmentA.queryEnvelope2D(env2DSegmentA);
+ // if multipointB has only 1 vertex then it is faster to not
+ // test for
+ // env2DSegmentA.distance(env2DgeometryB)
+ if (pointCountB > 1
+ && env2DSegmentA.sqrDistance(m_env2DgeometryB) > minSqrDistance)
+ continue;
+
+ for (int i = 0; i < pointCountB; i++) {
+ multiPointImplB.getXY(i, inputPoint);
+ if (bDoPiPTest) {
+ // Test for polygon containment. This takes the
+ // place of a more general intersection test at the
+ // beginning of the operator
+ if (PolygonUtils.isPointInPolygon2D(
+ (Polygon) geometryA, inputPoint, 0) != PolygonUtils.PiPResult.PiPOutside)
+ return 0.0;
+ }
+
+ t = segmentA.getClosestCoordinate(inputPoint, false);
+ inputPoint.sub(segmentA.getCoord2D(t));
+ sqrDistance = inputPoint.sqrLength();
+ if (sqrDistance < minSqrDistance) {
+ if (sqrDistance == 0.0)
+ return 0.0;
+
+ minSqrDistance = sqrDistance;
+ }
+ }
+
+ // No need to do point-in-polygon anymore (if it is a
+ // polygon vs polyline)
+ bDoPiPTest = false;
+ }
+ }
+ return Math.sqrt(minSqrDistance);
+ }
+
+ private double bruteForceMultiPointMultiPoint_(
+ /* const */MultiPoint geometryA, /* const */
+ MultiPoint geometryB, boolean geometriesAreDisjoint) {
+ double minSqrDistance = NumberUtils.doubleMax();
+
+ Point2D pointA = new Point2D();
+ Point2D pointB = new Point2D();
+
+ double sqrDistance = minSqrDistance;
/* const */
- MultiPointImpl multiPointImplA = (/* const */MultiPointImpl) geometryA
- ._getImpl();
+ MultiPointImpl multiPointImplA = (/* const */MultiPointImpl) geometryA
+ ._getImpl();
/* const */
- MultiPointImpl multiPointImplB = (/* const */MultiPointImpl) geometryB
- ._getImpl();
- int pointCountA = multiPointImplA.getPointCount();
- int pointCountB = multiPointImplB.getPointCount();
- for (int i = 0; i < pointCountA; i++) {
- multiPointImplA.getXY(i, pointA);
-
- if (pointCountB > 1
- && m_env2DgeometryB.sqrDistance(pointA) > minSqrDistance)
- continue;
-
- for (int j = 0; j < pointCountB; j++) {
- multiPointImplB.getXY(j, pointB);
- sqrDistance = Point2D.sqrDistance(pointA, pointB);
- if (sqrDistance < minSqrDistance) {
- if (sqrDistance == 0.0)
- return 0.0;
-
- minSqrDistance = sqrDistance;
- }
- }
- }
-
- return Math.sqrt(minSqrDistance);
- }
-
- // resets Iterators if they are used.
- private boolean weakIntersectionTest_(/* const */Geometry geometryA, /* const */
- Geometry geometryB, SegmentIterator segIterA, SegmentIterator segIterB) {
- if (geometryA.getType() == Geometry.Type.Polygon) {
- // test PolygonA vs. first segment of each of geometryB's paths
- while (segIterB.nextPath()) {
- if (segIterB.hasNextSegment()) {
+ MultiPointImpl multiPointImplB = (/* const */MultiPointImpl) geometryB
+ ._getImpl();
+ int pointCountA = multiPointImplA.getPointCount();
+ int pointCountB = multiPointImplB.getPointCount();
+ for (int i = 0; i < pointCountA; i++) {
+ multiPointImplA.getXY(i, pointA);
+
+ if (pointCountB > 1
+ && m_env2DgeometryB.sqrDistance(pointA) > minSqrDistance)
+ continue;
+
+ for (int j = 0; j < pointCountB; j++) {
+ multiPointImplB.getXY(j, pointB);
+ sqrDistance = Point2D.sqrDistance(pointA, pointB);
+ if (sqrDistance < minSqrDistance) {
+ if (sqrDistance == 0.0)
+ return 0.0;
+
+ minSqrDistance = sqrDistance;
+ }
+ }
+ }
+
+ return Math.sqrt(minSqrDistance);
+ }
+
+ // resets Iterators if they are used.
+ private boolean weakIntersectionTest_(/* const */Geometry geometryA, /* const */
+ Geometry geometryB, SegmentIterator segIterA, SegmentIterator segIterB) {
+ if (geometryA.getType() == Geometry.Type.Polygon) {
+ // test PolygonA vs. first segment of each of geometryB's paths
+ while (segIterB.nextPath()) {
+ if (segIterB.hasNextSegment()) {
/* const */
- Segment segmentB = segIterB.nextSegment();
- if (PolygonUtils.isPointInPolygon2D(
- (Polygon) geometryA, segmentB.getEndXY(), 0) != PolygonUtils.PiPResult.PiPOutside)
- return true;
- }
- }
- segIterB.resetToFirstPath();
- }
-
- if (geometryB.getType() == Geometry.Type.Polygon) {
- // test PolygonB vs. first segment of each of geometryA's paths
- while (segIterA.nextPath()) {
- if (segIterA.hasNextSegment()) {
+ Segment segmentB = segIterB.nextSegment();
+ if (PolygonUtils.isPointInPolygon2D(
+ (Polygon) geometryA, segmentB.getEndXY(), 0) != PolygonUtils.PiPResult.PiPOutside)
+ return true;
+ }
+ }
+ segIterB.resetToFirstPath();
+ }
+
+ if (geometryB.getType() == Geometry.Type.Polygon) {
+ // test PolygonB vs. first segment of each of geometryA's paths
+ while (segIterA.nextPath()) {
+ if (segIterA.hasNextSegment()) {
/* const */
- Segment segmentA = segIterA.nextSegment();
- if (PolygonUtils.isPointInPolygon2D(
- (Polygon) geometryB, segmentA.getEndXY(), 0) != PolygonUtils.PiPResult.PiPOutside)
- return true;
- }
- }
- segIterA.resetToFirstPath();
- }
- return false;
- }
-
- DistanceCalculator(ProgressTracker progressTracker) {
- m_progressTracker = progressTracker;
- m_env2DgeometryA = new Envelope2D();
- m_env2DgeometryA.setEmpty();
- m_env2DgeometryB = new Envelope2D();
- m_env2DgeometryB.setEmpty();
- }
-
- double calculate(/* const */Geometry geometryA, /* const */
- Geometry geometryB) {
- if (geometryA.isEmpty() || geometryB.isEmpty())
- return NumberUtils.TheNaN;
-
- geometryA.queryEnvelope2D(m_env2DgeometryA);
- geometryB.queryEnvelope2D(m_env2DgeometryB);
- return executeBruteForce_(geometryA, geometryB);
- }
- }
+ Segment segmentA = segIterA.nextSegment();
+ if (PolygonUtils.isPointInPolygon2D(
+ (Polygon) geometryB, segmentA.getEndXY(), 0) != PolygonUtils.PiPResult.PiPOutside)
+ return true;
+ }
+ }
+ segIterA.resetToFirstPath();
+ }
+ return false;
+ }
+
+ DistanceCalculator(ProgressTracker progressTracker) {
+ m_progressTracker = progressTracker;
+ m_env2DgeometryA = new Envelope2D();
+ m_env2DgeometryA.setEmpty();
+ m_env2DgeometryB = new Envelope2D();
+ m_env2DgeometryB.setEmpty();
+ }
+
+ double calculate(/* const */Geometry geometryA, /* const */
+ Geometry geometryB) {
+ if (geometryA.isEmpty() || geometryB.isEmpty())
+ return NumberUtils.TheNaN;
+
+ geometryA.queryEnvelope2D(m_env2DgeometryA);
+ geometryB.queryEnvelope2D(m_env2DgeometryB);
+ return executeBruteForce_(geometryA, geometryB);
+ }
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorEnclosingCircle.java b/src/main/java/com/esri/core/geometry/OperatorEnclosingCircle.java
index db4fe249..40276e8b 100644
--- a/src/main/java/com/esri/core/geometry/OperatorEnclosingCircle.java
+++ b/src/main/java/com/esri/core/geometry/OperatorEnclosingCircle.java
@@ -1,22 +1,22 @@
package com.esri.core.geometry;
public abstract class OperatorEnclosingCircle extends Operator {
- @Override
- public Type getType() {
- return Type.EnclosingCircle;
- }
+ @Override
+ public Type getType() {
+ return Type.EnclosingCircle;
+ }
- public abstract GeometryCursor execute(GeometryCursor geoms, SpatialReference spatialReference, ProgressTracker progressTracker);
+ public abstract GeometryCursor execute(GeometryCursor geoms, SpatialReference spatialReference, ProgressTracker progressTracker);
- /**
- * Performs the Generalize operation on a single geometry. Point and
- * multipoint geometries are left unchanged. An envelope is converted to a
- * polygon.
- */
- public abstract Geometry execute(Geometry geom, SpatialReference spatialReference, ProgressTracker progressTracker);
+ /**
+ * Performs the Generalize operation on a single geometry. Point and
+ * multipoint geometries are left unchanged. An envelope is converted to a
+ * polygon.
+ */
+ public abstract Geometry execute(Geometry geom, SpatialReference spatialReference, ProgressTracker progressTracker);
- public static OperatorEnclosingCircle local() {
- return (OperatorEnclosingCircle) OperatorFactoryLocal.getInstance().getOperator(Type.EnclosingCircle);
- }
+ public static OperatorEnclosingCircle local() {
+ return (OperatorEnclosingCircle) OperatorFactoryLocal.getInstance().getOperator(Type.EnclosingCircle);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorEnclosingCircleCursor.java b/src/main/java/com/esri/core/geometry/OperatorEnclosingCircleCursor.java
index 7368d38c..38611a42 100644
--- a/src/main/java/com/esri/core/geometry/OperatorEnclosingCircleCursor.java
+++ b/src/main/java/com/esri/core/geometry/OperatorEnclosingCircleCursor.java
@@ -6,30 +6,30 @@
import java.util.stream.IntStream;
public class OperatorEnclosingCircleCursor extends GeometryCursor {
- SpatialReference m_spatialReference;
- ProgressTracker m_progressTracker;
-
- public OperatorEnclosingCircleCursor(GeometryCursor geoms, SpatialReference spatialReference, ProgressTracker progressTracker) {
- m_inputGeoms = geoms;
- m_spatialReference = spatialReference;
- m_progressTracker = progressTracker;
- }
-
- @Override
- public Geometry next() {
- if (hasNext())
- return getCircle(m_inputGeoms.next());
-
- return null;
- }
-
- protected Geometry getCircle(Geometry geometry) {
- if (geometry.getType() == Geometry.Type.Point || ((MultiVertexGeometry)geometry).getPointCount() <= 1)
- return geometry;
-
- EnclosingCircler enclosingCircler = new EnclosingCircler(geometry, m_spatialReference, m_progressTracker);
- return enclosingCircler.search();
- }
+ SpatialReference m_spatialReference;
+ ProgressTracker m_progressTracker;
+
+ public OperatorEnclosingCircleCursor(GeometryCursor geoms, SpatialReference spatialReference, ProgressTracker progressTracker) {
+ m_inputGeoms = geoms;
+ m_spatialReference = spatialReference;
+ m_progressTracker = progressTracker;
+ }
+
+ @Override
+ public Geometry next() {
+ if (hasNext())
+ return getCircle(m_inputGeoms.next());
+
+ return null;
+ }
+
+ protected Geometry getCircle(Geometry geometry) {
+ if (geometry.getType() == Geometry.Type.Point || ((MultiVertexGeometry) geometry).getPointCount() <= 1)
+ return geometry;
+
+ EnclosingCircler enclosingCircler = new EnclosingCircler(geometry, m_spatialReference, m_progressTracker);
+ return enclosingCircler.search();
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorEnclosingCircleLocal.java b/src/main/java/com/esri/core/geometry/OperatorEnclosingCircleLocal.java
index b05d680b..4e63bfe0 100644
--- a/src/main/java/com/esri/core/geometry/OperatorEnclosingCircleLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorEnclosingCircleLocal.java
@@ -1,14 +1,14 @@
package com.esri.core.geometry;
public class OperatorEnclosingCircleLocal extends OperatorEnclosingCircle {
- @Override
- public GeometryCursor execute(GeometryCursor geoms, SpatialReference spatialReference, ProgressTracker progressTracker) {
- return new OperatorEnclosingCircleCursor(geoms, spatialReference, progressTracker);
- }
+ @Override
+ public GeometryCursor execute(GeometryCursor geoms, SpatialReference spatialReference, ProgressTracker progressTracker) {
+ return new OperatorEnclosingCircleCursor(geoms, spatialReference, progressTracker);
+ }
- @Override
- public Geometry execute(Geometry geom, SpatialReference spatialReference, ProgressTracker progressTracker) {
- OperatorEnclosingCircleCursor operatorEnclosingCircleCursor = new OperatorEnclosingCircleCursor(new SimpleGeometryCursor(geom), spatialReference, progressTracker);
- return operatorEnclosingCircleCursor.next();
- }
+ @Override
+ public Geometry execute(Geometry geom, SpatialReference spatialReference, ProgressTracker progressTracker) {
+ OperatorEnclosingCircleCursor operatorEnclosingCircleCursor = new OperatorEnclosingCircleCursor(new SimpleGeometryCursor(geom), spatialReference, progressTracker);
+ return operatorEnclosingCircleCursor.next();
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorEquals.java b/src/main/java/com/esri/core/geometry/OperatorEquals.java
index 1286052f..2fb6d3ba 100644
--- a/src/main/java/com/esri/core/geometry/OperatorEquals.java
+++ b/src/main/java/com/esri/core/geometry/OperatorEquals.java
@@ -30,14 +30,14 @@
* Relational operation Equals.
*/
public abstract class OperatorEquals extends OperatorSimpleRelation {
- @Override
- public Type getType() {
- return Type.Equals;
- }
-
- public static OperatorEquals local() {
- return (OperatorEquals) OperatorFactoryLocal.getInstance().getOperator(
- Type.Equals);
- }
+ @Override
+ public Type getType() {
+ return Type.Equals;
+ }
+
+ public static OperatorEquals local() {
+ return (OperatorEquals) OperatorFactoryLocal.getInstance().getOperator(
+ Type.Equals);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorEqualsLocal.java b/src/main/java/com/esri/core/geometry/OperatorEqualsLocal.java
index c0dbc7f8..945b0514 100644
--- a/src/main/java/com/esri/core/geometry/OperatorEqualsLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorEqualsLocal.java
@@ -25,11 +25,11 @@
package com.esri.core.geometry;
class OperatorEqualsLocal extends OperatorEquals {
- @Override
- public boolean execute(Geometry inputGeom1, Geometry inputGeom2,
- SpatialReference sr, ProgressTracker progressTracker) {
- return RelationalOperations.relate(inputGeom1, inputGeom2, sr,
- RelationalOperations.Relation.equals, progressTracker);
- }
+ @Override
+ public boolean execute(Geometry inputGeom1, Geometry inputGeom2,
+ SpatialReference sr, ProgressTracker progressTracker) {
+ return RelationalOperations.relate(inputGeom1, inputGeom2, sr,
+ RelationalOperations.Relation.equals, progressTracker);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorExportToESRIShape.java b/src/main/java/com/esri/core/geometry/OperatorExportToESRIShape.java
index 5842a046..9eb4051e 100644
--- a/src/main/java/com/esri/core/geometry/OperatorExportToESRIShape.java
+++ b/src/main/java/com/esri/core/geometry/OperatorExportToESRIShape.java
@@ -32,38 +32,38 @@
* Export to ESRI shape format.
*/
public abstract class OperatorExportToESRIShape extends Operator {
- @Override
- public Type getType() {
- return Type.ExportToESRIShape;
- }
+ @Override
+ public Type getType() {
+ return Type.ExportToESRIShape;
+ }
- /**
- * Performs the ExportToESRIShape operation
- *
- * @return Returns a ByteBufferCursor.
- */
- public abstract ByteBufferCursor execute(int exportFlags, GeometryCursor geometryCursor);
+ /**
+ * Performs the ExportToESRIShape operation
+ *
+ * @return Returns a ByteBufferCursor.
+ */
+ public abstract ByteBufferCursor execute(int exportFlags, GeometryCursor geometryCursor);
- /**
- * Performs the ExportToESRIShape operation.
- *
- * @param exportFlags Use the {@link ShapeExportFlags} interface.
- * @param geometry The Geometry being exported.
- * @return Returns a ByteBuffer object containing the Geometry in ESRIShape format.
- */
- public abstract ByteBuffer execute(int exportFlags, Geometry geometry);
+ /**
+ * Performs the ExportToESRIShape operation.
+ *
+ * @param exportFlags Use the {@link ShapeExportFlags} interface.
+ * @param geometry The Geometry being exported.
+ * @return Returns a ByteBuffer object containing the Geometry in ESRIShape format.
+ */
+ public abstract ByteBuffer execute(int exportFlags, Geometry geometry);
- /**
- * Performs the ExportToESRIShape operation.
- *
- * @param exportFlags Use the {@link ShapeExportFlags} interface.
- * @param geometry The Geometry being exported.
- * @param shapeBuffer The ByteBuffer to contain the exported Geometry in ESRIShape format.
- * @return If the input buffer is null, then the size needed for the buffer is returned. Otherwise the number of bytes written to the buffer is returned.
- */
- public abstract int execute(int exportFlags, Geometry geometry, ByteBuffer shapeBuffer);
+ /**
+ * Performs the ExportToESRIShape operation.
+ *
+ * @param exportFlags Use the {@link ShapeExportFlags} interface.
+ * @param geometry The Geometry being exported.
+ * @param shapeBuffer The ByteBuffer to contain the exported Geometry in ESRIShape format.
+ * @return If the input buffer is null, then the size needed for the buffer is returned. Otherwise the number of bytes written to the buffer is returned.
+ */
+ public abstract int execute(int exportFlags, Geometry geometry, ByteBuffer shapeBuffer);
- public static OperatorExportToESRIShape local() {
- return (OperatorExportToESRIShape) OperatorFactoryLocal.getInstance().getOperator(Type.ExportToESRIShape);
- }
+ public static OperatorExportToESRIShape local() {
+ return (OperatorExportToESRIShape) OperatorFactoryLocal.getInstance().getOperator(Type.ExportToESRIShape);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorExportToESRIShapeCursor.java b/src/main/java/com/esri/core/geometry/OperatorExportToESRIShapeCursor.java
index 360f3830..fa364be9 100644
--- a/src/main/java/com/esri/core/geometry/OperatorExportToESRIShapeCursor.java
+++ b/src/main/java/com/esri/core/geometry/OperatorExportToESRIShapeCursor.java
@@ -30,885 +30,887 @@
import java.nio.ByteOrder;
public class OperatorExportToESRIShapeCursor extends ByteBufferCursor {
- private GeometryCursor m_geometryCursor;
- private int m_exportFlags;
- private ByteBuffer m_shapeBuffer;
- private SimpleStateEnum simpleStateEnum = SimpleStateEnum.SIMPLE_UNKNOWN;
-
- public OperatorExportToESRIShapeCursor(int exportFlags, GeometryCursor geometryCursor) {
- if (geometryCursor == null)
- throw new GeometryException("invalid argument");
-
- m_exportFlags = exportFlags;
- m_geometryCursor = geometryCursor;
- m_shapeBuffer = null;
- }
-
- @Override
- public long getByteBufferID() {
- return m_geometryCursor.getGeometryID();
- }
-
- @Override
- public SimpleStateEnum getSimpleState() {
- return simpleStateEnum;
- }
-
- @Override
- public String getFeatureID() {
- return m_geometryCursor.getFeatureID();
- }
-
- @Override
- public boolean hasNext() { return m_geometryCursor != null && m_geometryCursor.hasNext(); }
-
- @Override
- public ByteBuffer next() {
- Geometry geometry;
- if (hasNext()) {
- geometry = m_geometryCursor.next();
- simpleStateEnum = geometry.getSimpleState();
- int size = exportToESRIShape(m_exportFlags, geometry, null);
- if (m_shapeBuffer == null || size > m_shapeBuffer.capacity())
- m_shapeBuffer = ByteBuffer.allocate(size).order(
- ByteOrder.LITTLE_ENDIAN);
- exportToESRIShape(m_exportFlags, geometry, m_shapeBuffer);
- return m_shapeBuffer;
- }
- return null;
- }
-
- static int exportToESRIShape(int exportFlags, Geometry geometry,
- ByteBuffer shapeBuffer) {
- if (geometry == null) {
- if (shapeBuffer != null)
- shapeBuffer.putInt(0, ShapeType.ShapeNull);
-
- return 4;
- }
-
- int type = geometry.getType().value();
- switch (type) {
- case Geometry.GeometryType.Polygon:
- return exportMultiPathToESRIShape(true, exportFlags,
- (MultiPath) geometry, shapeBuffer);
- case Geometry.GeometryType.Polyline:
- return exportMultiPathToESRIShape(false, exportFlags,
- (MultiPath) geometry, shapeBuffer);
- case Geometry.GeometryType.MultiPoint:
- return exportMultiPointToESRIShape(exportFlags,
- (MultiPoint) geometry, shapeBuffer);
- case Geometry.GeometryType.Point:
- return exportPointToESRIShape(exportFlags, (Point) geometry,
- shapeBuffer);
- case Geometry.GeometryType.Envelope:
- return exportEnvelopeToESRIShape(exportFlags, (Envelope) geometry,
- shapeBuffer);
- default: {
- throw GeometryException.GeometryInternalError();
- // return -1;
- }
- }
- }
-
- private static int exportEnvelopeToESRIShape(int exportFlags,
- Envelope envelope, ByteBuffer shapeBuffer) {
- boolean bExportZs = envelope.hasAttribute(Semantics.Z)
- && (exportFlags & ShapeExportFlags.ShapeExportStripZs) == 0;
- boolean bExportMs = envelope.hasAttribute(Semantics.M)
- && (exportFlags & ShapeExportFlags.ShapeExportStripMs) == 0;
- boolean bExportIDs = envelope.hasAttribute(Semantics.ID)
- && (exportFlags & ShapeExportFlags.ShapeExportStripIDs) == 0;
- boolean bArcViewNaNs = (exportFlags & ShapeExportFlags.ShapeExportTrueNaNs) == 0;
-
- boolean bEmpty = envelope.isEmpty();
- int partCount = bEmpty ? 0 : 1;
- int pointCount = bEmpty ? 0 : 5;
-
- int size = (4 /* type */) + (4 * 8 /* envelope */) + (4 /* part count */)
- + (4 /* point count */) + (partCount * 4 /* start indices */)
- + pointCount * 2 * 8 /* xy coordinates */;
-
- if (bExportZs)
- size += (2 * 8 /* min max */) + (pointCount * 8 /* zs */);
- if (bExportMs)
- size += (2 * 8 /* min max */) + (pointCount * 8 /* ms */);
- if (bExportIDs)
- size += (pointCount * 4 /* ids */);
-
- if (shapeBuffer == null)
- return size;
- else if (shapeBuffer.capacity() < size)
- throw new GeometryException("buffer is too small");
-
- int type;
-
- // Determine the shape type
- if (!bExportZs && !bExportMs) {
- if (bExportIDs)
- type = ShapeType.ShapeGeneralPolygon
- | ShapeModifiers.ShapeHasIDs;
- else
- type = ShapeType.ShapePolygon;
- } else if (bExportZs && !bExportMs) {
- if (bExportIDs)
- type = ShapeType.ShapeGeneralPolygon
- | ShapeModifiers.ShapeHasZs
- | ShapeModifiers.ShapeHasIDs;
- else
- type = ShapeType.ShapePolygonZ;
- } else if (bExportMs && !bExportZs) {
- if (bExportIDs)
- type = ShapeType.ShapeGeneralPolygon
- | ShapeModifiers.ShapeHasMs
- | ShapeModifiers.ShapeHasIDs;
- else
- type = ShapeType.ShapePolygonM;
- } else {
- if (bExportIDs)
- type = ShapeType.ShapeGeneralPolygon
- | ShapeModifiers.ShapeHasZs | ShapeModifiers.ShapeHasMs
- | ShapeModifiers.ShapeHasIDs;
- else
- type = ShapeType.ShapePolygonZM;
- }
-
- int offset = 0;
-
- // write type
- shapeBuffer.putInt(offset, type);
- offset += 4;
-
- // write Envelope
- Envelope2D env = new Envelope2D();
- envelope.queryEnvelope2D(env); // calls _VerifyAllStreams
- shapeBuffer.putDouble(offset, env.xmin);
- offset += 8;
- shapeBuffer.putDouble(offset, env.ymin);
- offset += 8;
- shapeBuffer.putDouble(offset, env.xmax);
- offset += 8;
- shapeBuffer.putDouble(offset, env.ymax);
- offset += 8;
-
- // write part count
- shapeBuffer.putInt(offset, partCount);
- offset += 4;
-
- // write pointCount
- shapeBuffer.putInt(offset, pointCount);
- offset += 4;
-
- if (!bEmpty) {
- // write start index
- shapeBuffer.putInt(offset, 0);
- offset += 4;
-
- // write xy coordinates
- shapeBuffer.putDouble(offset, env.xmin);
- offset += 8;
- shapeBuffer.putDouble(offset, env.ymin);
- offset += 8;
-
- shapeBuffer.putDouble(offset, env.xmin);
- offset += 8;
- shapeBuffer.putDouble(offset, env.ymax);
- offset += 8;
-
- shapeBuffer.putDouble(offset, env.xmax);
- offset += 8;
- shapeBuffer.putDouble(offset, env.ymax);
- offset += 8;
-
- shapeBuffer.putDouble(offset, env.xmax);
- offset += 8;
- shapeBuffer.putDouble(offset, env.ymin);
- offset += 8;
-
- shapeBuffer.putDouble(offset, env.xmin);
- offset += 8;
- shapeBuffer.putDouble(offset, env.ymin);
- offset += 8;
- }
- // write Zs
- if (bExportZs) {
- Envelope1D zInterval;
- zInterval = envelope.queryInterval(Semantics.Z, 0);
-
- double zmin = bArcViewNaNs ? Interop
- .translateToAVNaN(zInterval.vmin) : zInterval.vmin;
- double zmax = bArcViewNaNs ? Interop
- .translateToAVNaN(zInterval.vmax) : zInterval.vmax;
-
- // write min max values
- shapeBuffer.putDouble(offset, zmin);
- offset += 8;
- shapeBuffer.putDouble(offset, zmax);
- offset += 8;
-
- if (!bEmpty) {
- // write arbitrary z values
- shapeBuffer.putDouble(offset, zmin);
- offset += 8;
- shapeBuffer.putDouble(offset, zmax);
- offset += 8;
- shapeBuffer.putDouble(offset, zmin);
- offset += 8;
- shapeBuffer.putDouble(offset, zmax);
- offset += 8;
- shapeBuffer.putDouble(offset, zmin);
- offset += 8;
- }
- }
- // write Ms
- if (bExportMs) {
- Envelope1D mInterval;
- mInterval = envelope.queryInterval(Semantics.M, 0);
-
- double mmin = bArcViewNaNs ? Interop
- .translateToAVNaN(mInterval.vmin) : mInterval.vmin;
- double mmax = bArcViewNaNs ? Interop
- .translateToAVNaN(mInterval.vmax) : mInterval.vmax;
-
- // write min max values
- shapeBuffer.putDouble(offset, mmin);
- offset += 8;
- shapeBuffer.putDouble(offset, mmax);
- offset += 8;
-
- if (!bEmpty) {
- // write arbitrary m values
- shapeBuffer.putDouble(offset, mmin);
- offset += 8;
- shapeBuffer.putDouble(offset, mmax);
- offset += 8;
- shapeBuffer.putDouble(offset, mmin);
- offset += 8;
- shapeBuffer.putDouble(offset, mmax);
- offset += 8;
- shapeBuffer.putDouble(offset, mmin);
- offset += 8;
- }
- }
-
- // write IDs
- if (bExportIDs && !bEmpty) {
- Envelope1D idInterval;
- idInterval = envelope.queryInterval(Semantics.ID, 0);
-
- int idmin = (int) idInterval.vmin;
- int idmax = (int) idInterval.vmax;
-
- // write arbitrary id values
- shapeBuffer.putInt(offset, idmin);
- offset += 4;
- shapeBuffer.putInt(offset, idmax);
- offset += 4;
- shapeBuffer.putInt(offset, idmin);
- offset += 4;
- shapeBuffer.putInt(offset, idmax);
- offset += 4;
- shapeBuffer.putInt(offset, idmin);
- offset += 4;
- }
-
- return offset;
- }
-
- private static int exportPointToESRIShape(int exportFlags, Point point,
- ByteBuffer shapeBuffer) {
- boolean bExportZ = point.hasAttribute(Semantics.Z)
- && (exportFlags & ShapeExportFlags.ShapeExportStripZs) == 0;
- boolean bExportM = point.hasAttribute(Semantics.M)
- && (exportFlags & ShapeExportFlags.ShapeExportStripMs) == 0;
- boolean bExportID = point.hasAttribute(Semantics.ID)
- && (exportFlags & ShapeExportFlags.ShapeExportStripIDs) == 0;
- boolean bArcViewNaNs = (exportFlags & ShapeExportFlags.ShapeExportTrueNaNs) == 0;
-
- int size = (4 /* type */) + (2 * 8 /* xy coordinate */);
-
- if (bExportZ)
- size += 8;
- if (bExportM)
- size += 8;
- if (bExportID)
- size += 4;
-
- if (shapeBuffer == null)
- return size;
- else if (shapeBuffer.capacity() < size)
- throw new GeometryException("buffer is too small");
-
- int type;
-
- // Determine the shape type
- if (!bExportZ && !bExportM) {
- if (bExportID)
- type = ShapeType.ShapeGeneralPoint | ShapeModifiers.ShapeHasIDs;
- else
- type = ShapeType.ShapePoint;
- } else if (bExportZ && !bExportM) {
- if (bExportID)
- type = ShapeType.ShapeGeneralPoint | ShapeModifiers.ShapeHasZs
- | ShapeModifiers.ShapeHasIDs;
- else
- type = ShapeType.ShapePointZ;
- } else if (bExportM && !bExportZ) {
- if (bExportID)
- type = ShapeType.ShapeGeneralPoint | ShapeModifiers.ShapeHasMs
- | ShapeModifiers.ShapeHasIDs;
- else
- type = ShapeType.ShapePointM;
- } else {
- if (bExportID)
- type = ShapeType.ShapeGeneralPoint | ShapeModifiers.ShapeHasZs
- | ShapeModifiers.ShapeHasMs
- | ShapeModifiers.ShapeHasIDs;
- else
- type = ShapeType.ShapePointZM;
- }
-
- int offset = 0;
-
- // write type
-
- shapeBuffer.putInt(offset, type);
- offset += 4;
-
- boolean bEmpty = point.isEmpty();
-
- // write xy
- double x = !bEmpty ? point.getX() : NumberUtils.NaN();
- double y = !bEmpty ? point.getY() : NumberUtils.NaN();
- shapeBuffer.putDouble(offset,
- bArcViewNaNs ? Interop.translateToAVNaN(x) : x);
- offset += 8;
- shapeBuffer.putDouble(offset,
- bArcViewNaNs ? Interop.translateToAVNaN(y) : y);
- offset += 8;
-
- // write Z
- if (bExportZ) {
- double z = !bEmpty ? point.getZ() : NumberUtils.NaN();
- shapeBuffer.putDouble(offset,
- bArcViewNaNs ? Interop.translateToAVNaN(z) : z);
- offset += 8;
- }
-
- // WriteM
- if (bExportM) {
- double m = !bEmpty ? point.getM() : NumberUtils.NaN();
- shapeBuffer.putDouble(offset,
- bArcViewNaNs ? Interop.translateToAVNaN(m) : m);
- offset += 8;
- }
-
- // write ID
- if (bExportID) {
- int id = !bEmpty ? point.getID() : 0;
- shapeBuffer.putInt(offset, id);
- offset += 4;
- }
-
- return offset;
- }
-
- private static int exportMultiPointToESRIShape(int exportFlags,
- MultiPoint multipoint, ByteBuffer shapeBuffer) {
- MultiPointImpl multipointImpl = (MultiPointImpl) multipoint._getImpl();
- boolean bExportZs = multipointImpl.hasAttribute(Semantics.Z)
- && (exportFlags & ShapeExportFlags.ShapeExportStripZs) == 0;
- boolean bExportMs = multipointImpl.hasAttribute(Semantics.M)
- && (exportFlags & ShapeExportFlags.ShapeExportStripMs) == 0;
- boolean bExportIDs = multipointImpl.hasAttribute(Semantics.ID)
- && (exportFlags & ShapeExportFlags.ShapeExportStripIDs) == 0;
- boolean bArcViewNaNs = (exportFlags & ShapeExportFlags.ShapeExportTrueNaNs) == 0;
-
- int pointCount = multipointImpl.getPointCount();
-
- int size = (4 /* type */) + (4 * 8 /* envelope */) + (4 /* point count */)
- + (pointCount * 2 * 8 /* xy coordinates */);
-
- if (bExportZs)
- size += (2 * 8 /* min max */) + (pointCount * 8 /* zs */);
- if (bExportMs)
- size += (2 * 8 /* min max */) + (pointCount * 8 /* ms */);
- if (bExportIDs)
- size += pointCount * 4 /* ids */;
-
- if (size >= NumberUtils.intMax())
- throw new GeometryException("invalid call");
-
- if (shapeBuffer == null)
- return size;
- else if (shapeBuffer.capacity() < size)
- throw new GeometryException("buffer is too small");
-
- int type;
-
- // Determine the shape type
- if (!bExportZs && !bExportMs) {
- if (bExportIDs)
- type = ShapeType.ShapeGeneralMultiPoint
- | ShapeModifiers.ShapeHasIDs;
- else
- type = ShapeType.ShapeMultiPoint;
- } else if (bExportZs && !bExportMs) {
- if (bExportIDs)
- type = ShapeType.ShapeGeneralMultiPoint
- | ShapeModifiers.ShapeHasZs
- | ShapeModifiers.ShapeHasIDs;
- else
- type = ShapeType.ShapeMultiPointZ;
- } else if (bExportMs && !bExportZs) {
- if (bExportIDs)
- type = ShapeType.ShapeGeneralMultiPoint
- | ShapeModifiers.ShapeHasMs
- | ShapeModifiers.ShapeHasIDs;
- else
- type = ShapeType.ShapeMultiPointM;
- } else {
- if (bExportIDs)
- type = ShapeType.ShapeGeneralMultiPoint
- | ShapeModifiers.ShapeHasZs | ShapeModifiers.ShapeHasMs
- | ShapeModifiers.ShapeHasIDs;
- else
- type = ShapeType.ShapeMultiPointZM;
- }
-
- // write type
- int offset = 0;
-
- shapeBuffer.putInt(offset, type);
- offset += 4;
-
- // write Envelope
- Envelope2D env = new Envelope2D();
- multipointImpl.queryEnvelope2D(env); // calls _VerifyAllStreams
- shapeBuffer.putDouble(offset, env.xmin);
- offset += 8;
- shapeBuffer.putDouble(offset, env.ymin);
- offset += 8;
- shapeBuffer.putDouble(offset, env.xmax);
- offset += 8;
- shapeBuffer.putDouble(offset, env.ymax);
- offset += 8;
-
- // write point count
- shapeBuffer.putInt(offset, pointCount);
- offset += 4;
-
- if (pointCount > 0) {
- // write xy coordinates
- AttributeStreamBase positionStream = multipointImpl
- .getAttributeStreamRef(Semantics.POSITION);
- AttributeStreamOfDbl position = (AttributeStreamOfDbl) positionStream;
- for (int i = 0; i < pointCount; i++) {
- double x = position.read(2 * i);
- double y = position.read(2 * i + 1);
- shapeBuffer.putDouble(offset, x);
- offset += 8;
- shapeBuffer.putDouble(offset, y);
- offset += 8;
- }
- }
-
- // write Zs
- if (bExportZs) {
- Envelope1D zInterval = multipointImpl.queryInterval(Semantics.Z, 0);
- shapeBuffer.putDouble(offset,
- bArcViewNaNs ? Interop.translateToAVNaN(zInterval.vmin)
- : zInterval.vmin);
- offset += 8;
- shapeBuffer.putDouble(offset,
- bArcViewNaNs ? Interop.translateToAVNaN(zInterval.vmax)
- : zInterval.vmax);
- offset += 8;
-
- if (pointCount > 0) {
- if (multipointImpl._attributeStreamIsAllocated(Semantics.Z)) {
- AttributeStreamOfDbl zs = (AttributeStreamOfDbl) multipointImpl
- .getAttributeStreamRef(Semantics.Z);
- for (int i = 0; i < pointCount; i++) {
- double z = zs.read(i);
- shapeBuffer.putDouble(offset,
- bArcViewNaNs ? Interop.translateToAVNaN(z) : z);
- offset += 8;
- }
- } else {
- double z = VertexDescription.getDefaultValue(Semantics.Z);
-
- if (bArcViewNaNs)
- z = Interop.translateToAVNaN(z);
-
- // Can we write a function that writes all these values at
- // once instead of doing a for loop?
- for (int i = 0; i < pointCount; i++)
- shapeBuffer.putDouble(offset, z);
- offset += 8;
- }
- }
- }
-
- // write Ms
- if (bExportMs) {
- Envelope1D mInterval = multipointImpl.queryInterval(Semantics.M, 0);
- shapeBuffer.putDouble(offset,
- bArcViewNaNs ? Interop.translateToAVNaN(mInterval.vmin)
- : mInterval.vmin);
- offset += 8;
- shapeBuffer.putDouble(offset,
- bArcViewNaNs ? Interop.translateToAVNaN(mInterval.vmax)
- : mInterval.vmax);
- offset += 8;
-
- if (pointCount > 0) {
- if (multipointImpl._attributeStreamIsAllocated(Semantics.M)) {
- AttributeStreamOfDbl ms = (AttributeStreamOfDbl) multipointImpl
- .getAttributeStreamRef(Semantics.M);
- for (int i = 0; i < pointCount; i++) {
- double m = ms.read(i);
- shapeBuffer.putDouble(offset,
- bArcViewNaNs ? Interop.translateToAVNaN(m) : m);
- offset += 8;
- }
- } else {
- double m = VertexDescription.getDefaultValue(Semantics.M);
-
- if (bArcViewNaNs)
- m = Interop.translateToAVNaN(m);
-
- for (int i = 0; i < pointCount; i++)
- shapeBuffer.putDouble(offset, m);
- offset += 8;
- }
- }
- }
-
- // write IDs
- if (bExportIDs) {
- if (pointCount > 0) {
- if (multipointImpl._attributeStreamIsAllocated(Semantics.ID)) {
- AttributeStreamOfInt32 ids = (AttributeStreamOfInt32) multipointImpl
- .getAttributeStreamRef(Semantics.ID);
- for (int i = 0; i < pointCount; i++) {
- int id = ids.read(i);
- shapeBuffer.putInt(offset, id);
- offset += 4;
- }
- } else {
- int id = (int) VertexDescription
- .getDefaultValue(Semantics.ID);
- for (int i = 0; i < pointCount; i++)
- shapeBuffer.putInt(offset, id);
- offset += 4;
- }
- }
- }
-
- return offset;
- }
-
- private static int exportMultiPathToESRIShape(boolean bPolygon,
- int exportFlags, MultiPath multipath, ByteBuffer shapeBuffer) {
- MultiPathImpl multipathImpl = (MultiPathImpl) multipath._getImpl();
-
- boolean bExportZs = multipathImpl.hasAttribute(Semantics.Z)
- && (exportFlags & ShapeExportFlags.ShapeExportStripZs) == 0;
- boolean bExportMs = multipathImpl.hasAttribute(Semantics.M)
- && (exportFlags & ShapeExportFlags.ShapeExportStripMs) == 0;
- boolean bExportIDs = multipathImpl.hasAttribute(Semantics.ID)
- && (exportFlags & ShapeExportFlags.ShapeExportStripIDs) == 0;
- boolean bHasCurves = multipathImpl.hasNonLinearSegments();
- boolean bArcViewNaNs = (exportFlags & ShapeExportFlags.ShapeExportTrueNaNs) == 0;
-
- int partCount = multipathImpl.getPathCount();
- int pointCount = multipathImpl.getPointCount();
-
- if (!bPolygon) {
- for (int ipart = 0; ipart < partCount; ipart++)
- if (multipath.isClosedPath(ipart))
- pointCount++;
- } else
- pointCount += partCount;
-
- int size = (4 /* type */) + (4 * 8 /* envelope */) + (4 /* part count */)
- + (4 /* point count */) + (partCount * 4 /* start indices */)
- + pointCount * 2 * 8 /* xy coordinates */;
-
- if (bExportZs)
- size += (2 * 8 /* min max */) + (pointCount * 8 /* zs */);
- if (bExportMs)
- size += (2 * 8 /* min max */) + (pointCount * 8 /* ms */);
- if (bExportIDs)
- size += pointCount * 4 /* ids */;
- if (bHasCurves) {
- // to-do: curves
- }
-
- if (size >= NumberUtils.intMax())
- throw new GeometryException("invalid call");
-
- if (shapeBuffer == null)
- return size;
- else if (shapeBuffer.capacity() < size)
- throw new GeometryException("buffer is too small");
-
- int offset = 0;
-
- // Determine the shape type
- int type;
- if (!bExportZs && !bExportMs) {
- if (bExportIDs || bHasCurves) {
- type = bPolygon ? ShapeType.ShapeGeneralPolygon
- : ShapeType.ShapeGeneralPolyline;
- if (bExportIDs)
- type |= ShapeModifiers.ShapeHasIDs;
- if (bHasCurves)
- type |= ShapeModifiers.ShapeHasCurves;
- } else
- type = bPolygon ? ShapeType.ShapePolygon
- : ShapeType.ShapePolyline;
- } else if (bExportZs && !bExportMs) {
- if (bExportIDs || bHasCurves) {
- type = bPolygon ? ShapeType.ShapeGeneralPolygon
- : ShapeType.ShapeGeneralPolyline;
- type |= ShapeModifiers.ShapeHasZs;
- if (bExportIDs)
- type |= ShapeModifiers.ShapeHasIDs;
- if (bHasCurves)
- type |= ShapeModifiers.ShapeHasCurves;
- } else
- type = bPolygon ? ShapeType.ShapePolygonZ
- : ShapeType.ShapePolylineZ;
- } else if (bExportMs && !bExportZs) {
- if (bExportIDs || bHasCurves) {
- type = bPolygon ? ShapeType.ShapeGeneralPolygon
- : ShapeType.ShapeGeneralPolyline;
- type |= ShapeModifiers.ShapeHasMs;
- if (bExportIDs)
- type |= ShapeModifiers.ShapeHasIDs;
- if (bHasCurves)
- type |= ShapeModifiers.ShapeHasCurves;
- } else
- type = bPolygon ? ShapeType.ShapePolygonM
- : ShapeType.ShapePolylineM;
- } else {
- if (bExportIDs || bHasCurves) {
- type = bPolygon ? ShapeType.ShapeGeneralPolygon
- : ShapeType.ShapeGeneralPolyline;
- type |= ShapeModifiers.ShapeHasZs | ShapeModifiers.ShapeHasMs;
- if (bExportIDs)
- type |= ShapeModifiers.ShapeHasIDs;
- if (bHasCurves)
- type |= ShapeModifiers.ShapeHasCurves;
- } else
- type = bPolygon ? ShapeType.ShapePolygonZM
- : ShapeType.ShapePolylineZM;
- }
-
- // write type
- shapeBuffer.putInt(offset, type);
- offset += 4;
-
- // write Envelope
- Envelope2D env = new Envelope2D();
- multipathImpl.queryEnvelope2D(env); // calls _VerifyAllStreams
- shapeBuffer.putDouble(offset, env.xmin);
- offset += 8;
- shapeBuffer.putDouble(offset, env.ymin);
- offset += 8;
- shapeBuffer.putDouble(offset, env.xmax);
- offset += 8;
- shapeBuffer.putDouble(offset, env.ymax);
- offset += 8;
-
- // write part count
- shapeBuffer.putInt(offset, partCount);
- offset += 4; // to-do: return error if larger than 2^32 - 1
-
- // write pointCount
- shapeBuffer.putInt(offset, pointCount);
- offset += 4;
-
- // write start indices for each part
- int pointIndexDelta = 0;
- for (int ipart = 0; ipart < partCount; ipart++) {
- int istart = multipathImpl.getPathStart(ipart) + pointIndexDelta;
- shapeBuffer.putInt(offset, istart);
- offset += 4;
- if (bPolygon || multipathImpl.isClosedPath(ipart))
- pointIndexDelta++;
- }
-
- if (pointCount > 0) {
- // write xy coordinates
- AttributeStreamBase positionStream = multipathImpl
- .getAttributeStreamRef(Semantics.POSITION);
- AttributeStreamOfDbl position = (AttributeStreamOfDbl) positionStream;
-
- for (int ipart = 0; ipart < partCount; ipart++) {
- int partStart = multipathImpl.getPathStart(ipart);
- int partEnd = multipathImpl.getPathEnd(ipart);
- for (int i = partStart; i < partEnd; i++) {
- double x = position.read(2 * i);
- double y = position.read(2 * i + 1);
-
- shapeBuffer.putDouble(offset, x);
- offset += 8;
- shapeBuffer.putDouble(offset, y);
- offset += 8;
- }
-
- // If the part is closed, then we need to duplicate the start
- // point
- if (bPolygon || multipathImpl.isClosedPath(ipart)) {
- double x = position.read(2 * partStart);
- double y = position.read(2 * partStart + 1);
-
- shapeBuffer.putDouble(offset, x);
- offset += 8;
- shapeBuffer.putDouble(offset, y);
- offset += 8;
- }
- }
- }
-
- // write Zs
- if (bExportZs) {
- Envelope1D zInterval = multipathImpl.queryInterval(Semantics.Z, 0);
- shapeBuffer.putDouble(offset,
- bArcViewNaNs ? Interop.translateToAVNaN(zInterval.vmin)
- : zInterval.vmin);
- offset += 8;
- shapeBuffer.putDouble(offset,
- bArcViewNaNs ? Interop.translateToAVNaN(zInterval.vmax)
- : zInterval.vmax);
- offset += 8;
-
- if (pointCount > 0) {
- if (multipathImpl._attributeStreamIsAllocated(Semantics.Z)) {
- AttributeStreamOfDbl zs = (AttributeStreamOfDbl) multipathImpl
- .getAttributeStreamRef(Semantics.Z);
- for (int ipart = 0; ipart < partCount; ipart++) {
- int partStart = multipathImpl.getPathStart(ipart);
- int partEnd = multipathImpl.getPathEnd(ipart);
- for (int i = partStart; i < partEnd; i++) {
- double z = zs.read(i);
- shapeBuffer.putDouble(offset,
- bArcViewNaNs ? Interop.translateToAVNaN(z)
- : z);
- offset += 8;
- }
-
- // If the part is closed, then we need to duplicate the
- // start z
- if (bPolygon || multipathImpl.isClosedPath(ipart)) {
- double z = zs.read(partStart);
- shapeBuffer.putDouble(offset, z);
- offset += 8;
- }
- }
- } else {
- double z = VertexDescription.getDefaultValue(Semantics.Z);
-
- if (bArcViewNaNs)
- z = Interop.translateToAVNaN(z);
-
- for (int i = 0; i < pointCount; i++)
- shapeBuffer.putDouble(offset, z);
- offset += 8;
- }
- }
- }
-
- // write Ms
- if (bExportMs) {
- Envelope1D mInterval = multipathImpl.queryInterval(Semantics.M, 0);
- shapeBuffer.putDouble(offset,
- bArcViewNaNs ? Interop.translateToAVNaN(mInterval.vmin)
- : mInterval.vmin);
- offset += 8;
- shapeBuffer.putDouble(offset,
- bArcViewNaNs ? Interop.translateToAVNaN(mInterval.vmax)
- : mInterval.vmax);
- offset += 8;
-
- if (pointCount > 0) {
- if (multipathImpl._attributeStreamIsAllocated(Semantics.M)) {
- AttributeStreamOfDbl ms = (AttributeStreamOfDbl) multipathImpl
- .getAttributeStreamRef(Semantics.M);
- for (int ipart = 0; ipart < partCount; ipart++) {
- int partStart = multipathImpl.getPathStart(ipart);
- int partEnd = multipathImpl.getPathEnd(ipart);
- for (int i = partStart; i < partEnd; i++) {
- double m = ms.read(i);
- shapeBuffer.putDouble(offset,
- bArcViewNaNs ? Interop.translateToAVNaN(m)
- : m);
- offset += 8;
- }
-
- // If the part is closed, then we need to duplicate the
- // start m
- if (bPolygon || multipathImpl.isClosedPath(ipart)) {
- double m = ms.read(partStart);
- shapeBuffer.putDouble(offset, m);
- offset += 8;
- }
- }
- } else {
- double m = VertexDescription.getDefaultValue(Semantics.M);
-
- if (bArcViewNaNs)
- m = Interop.translateToAVNaN(m);
-
- for (int i = 0; i < pointCount; i++)
- shapeBuffer.putDouble(offset, m);
- offset += 8;
- }
- }
- }
-
- // write Curves
- if (bHasCurves) {
- // to-do: We'll finish this later
- }
-
- // write IDs
- if (bExportIDs) {
- if (pointCount > 0) {
- if (multipathImpl._attributeStreamIsAllocated(Semantics.ID)) {
- AttributeStreamOfInt32 ids = (AttributeStreamOfInt32) multipathImpl
- .getAttributeStreamRef(Semantics.ID);
- for (int ipart = 0; ipart < partCount; ipart++) {
- int partStart = multipathImpl.getPathStart(ipart);
- int partEnd = multipathImpl.getPathEnd(ipart);
- for (int i = partStart; i < partEnd; i++) {
- int id = ids.read(i);
- shapeBuffer.putInt(offset, id);
- offset += 4;
- }
-
- // If the part is closed, then we need to duplicate the
- // start id
- if (bPolygon || multipathImpl.isClosedPath(ipart)) {
- int id = ids.read(partStart);
- shapeBuffer.putInt(offset, id);
- offset += 4;
- }
- }
- } else {
- int id = (int) VertexDescription
- .getDefaultValue(Semantics.ID);
- for (int i = 0; i < pointCount; i++)
- shapeBuffer.putInt(offset, id);
- offset += 4;
- }
- }
- }
-
- return offset;
- }
+ private GeometryCursor m_geometryCursor;
+ private int m_exportFlags;
+ private ByteBuffer m_shapeBuffer;
+ private SimpleStateEnum simpleStateEnum = SimpleStateEnum.SIMPLE_UNKNOWN;
+
+ public OperatorExportToESRIShapeCursor(int exportFlags, GeometryCursor geometryCursor) {
+ if (geometryCursor == null)
+ throw new GeometryException("invalid argument");
+
+ m_exportFlags = exportFlags;
+ m_geometryCursor = geometryCursor;
+ m_shapeBuffer = null;
+ }
+
+ @Override
+ public long getByteBufferID() {
+ return m_geometryCursor.getGeometryID();
+ }
+
+ @Override
+ public SimpleStateEnum getSimpleState() {
+ return simpleStateEnum;
+ }
+
+ @Override
+ public String getFeatureID() {
+ return m_geometryCursor.getFeatureID();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return m_geometryCursor != null && m_geometryCursor.hasNext();
+ }
+
+ @Override
+ public ByteBuffer next() {
+ Geometry geometry;
+ if (hasNext()) {
+ geometry = m_geometryCursor.next();
+ simpleStateEnum = geometry.getSimpleState();
+ int size = exportToESRIShape(m_exportFlags, geometry, null);
+ if (m_shapeBuffer == null || size > m_shapeBuffer.capacity())
+ m_shapeBuffer = ByteBuffer.allocate(size).order(
+ ByteOrder.LITTLE_ENDIAN);
+ exportToESRIShape(m_exportFlags, geometry, m_shapeBuffer);
+ return m_shapeBuffer;
+ }
+ return null;
+ }
+
+ static int exportToESRIShape(int exportFlags, Geometry geometry,
+ ByteBuffer shapeBuffer) {
+ if (geometry == null) {
+ if (shapeBuffer != null)
+ shapeBuffer.putInt(0, ShapeType.ShapeNull);
+
+ return 4;
+ }
+
+ int type = geometry.getType().value();
+ switch (type) {
+ case Geometry.GeometryType.Polygon:
+ return exportMultiPathToESRIShape(true, exportFlags,
+ (MultiPath) geometry, shapeBuffer);
+ case Geometry.GeometryType.Polyline:
+ return exportMultiPathToESRIShape(false, exportFlags,
+ (MultiPath) geometry, shapeBuffer);
+ case Geometry.GeometryType.MultiPoint:
+ return exportMultiPointToESRIShape(exportFlags,
+ (MultiPoint) geometry, shapeBuffer);
+ case Geometry.GeometryType.Point:
+ return exportPointToESRIShape(exportFlags, (Point) geometry,
+ shapeBuffer);
+ case Geometry.GeometryType.Envelope:
+ return exportEnvelopeToESRIShape(exportFlags, (Envelope) geometry,
+ shapeBuffer);
+ default: {
+ throw GeometryException.GeometryInternalError();
+ // return -1;
+ }
+ }
+ }
+
+ private static int exportEnvelopeToESRIShape(int exportFlags,
+ Envelope envelope, ByteBuffer shapeBuffer) {
+ boolean bExportZs = envelope.hasAttribute(Semantics.Z)
+ && (exportFlags & ShapeExportFlags.ShapeExportStripZs) == 0;
+ boolean bExportMs = envelope.hasAttribute(Semantics.M)
+ && (exportFlags & ShapeExportFlags.ShapeExportStripMs) == 0;
+ boolean bExportIDs = envelope.hasAttribute(Semantics.ID)
+ && (exportFlags & ShapeExportFlags.ShapeExportStripIDs) == 0;
+ boolean bArcViewNaNs = (exportFlags & ShapeExportFlags.ShapeExportTrueNaNs) == 0;
+
+ boolean bEmpty = envelope.isEmpty();
+ int partCount = bEmpty ? 0 : 1;
+ int pointCount = bEmpty ? 0 : 5;
+
+ int size = (4 /* type */) + (4 * 8 /* envelope */) + (4 /* part count */)
+ + (4 /* point count */) + (partCount * 4 /* start indices */)
+ + pointCount * 2 * 8 /* xy coordinates */;
+
+ if (bExportZs)
+ size += (2 * 8 /* min max */) + (pointCount * 8 /* zs */);
+ if (bExportMs)
+ size += (2 * 8 /* min max */) + (pointCount * 8 /* ms */);
+ if (bExportIDs)
+ size += (pointCount * 4 /* ids */);
+
+ if (shapeBuffer == null)
+ return size;
+ else if (shapeBuffer.capacity() < size)
+ throw new GeometryException("buffer is too small");
+
+ int type;
+
+ // Determine the shape type
+ if (!bExportZs && !bExportMs) {
+ if (bExportIDs)
+ type = ShapeType.ShapeGeneralPolygon
+ | ShapeModifiers.ShapeHasIDs;
+ else
+ type = ShapeType.ShapePolygon;
+ } else if (bExportZs && !bExportMs) {
+ if (bExportIDs)
+ type = ShapeType.ShapeGeneralPolygon
+ | ShapeModifiers.ShapeHasZs
+ | ShapeModifiers.ShapeHasIDs;
+ else
+ type = ShapeType.ShapePolygonZ;
+ } else if (bExportMs && !bExportZs) {
+ if (bExportIDs)
+ type = ShapeType.ShapeGeneralPolygon
+ | ShapeModifiers.ShapeHasMs
+ | ShapeModifiers.ShapeHasIDs;
+ else
+ type = ShapeType.ShapePolygonM;
+ } else {
+ if (bExportIDs)
+ type = ShapeType.ShapeGeneralPolygon
+ | ShapeModifiers.ShapeHasZs | ShapeModifiers.ShapeHasMs
+ | ShapeModifiers.ShapeHasIDs;
+ else
+ type = ShapeType.ShapePolygonZM;
+ }
+
+ int offset = 0;
+
+ // write type
+ shapeBuffer.putInt(offset, type);
+ offset += 4;
+
+ // write Envelope
+ Envelope2D env = new Envelope2D();
+ envelope.queryEnvelope2D(env); // calls _VerifyAllStreams
+ shapeBuffer.putDouble(offset, env.xmin);
+ offset += 8;
+ shapeBuffer.putDouble(offset, env.ymin);
+ offset += 8;
+ shapeBuffer.putDouble(offset, env.xmax);
+ offset += 8;
+ shapeBuffer.putDouble(offset, env.ymax);
+ offset += 8;
+
+ // write part count
+ shapeBuffer.putInt(offset, partCount);
+ offset += 4;
+
+ // write pointCount
+ shapeBuffer.putInt(offset, pointCount);
+ offset += 4;
+
+ if (!bEmpty) {
+ // write start index
+ shapeBuffer.putInt(offset, 0);
+ offset += 4;
+
+ // write xy coordinates
+ shapeBuffer.putDouble(offset, env.xmin);
+ offset += 8;
+ shapeBuffer.putDouble(offset, env.ymin);
+ offset += 8;
+
+ shapeBuffer.putDouble(offset, env.xmin);
+ offset += 8;
+ shapeBuffer.putDouble(offset, env.ymax);
+ offset += 8;
+
+ shapeBuffer.putDouble(offset, env.xmax);
+ offset += 8;
+ shapeBuffer.putDouble(offset, env.ymax);
+ offset += 8;
+
+ shapeBuffer.putDouble(offset, env.xmax);
+ offset += 8;
+ shapeBuffer.putDouble(offset, env.ymin);
+ offset += 8;
+
+ shapeBuffer.putDouble(offset, env.xmin);
+ offset += 8;
+ shapeBuffer.putDouble(offset, env.ymin);
+ offset += 8;
+ }
+ // write Zs
+ if (bExportZs) {
+ Envelope1D zInterval;
+ zInterval = envelope.queryInterval(Semantics.Z, 0);
+
+ double zmin = bArcViewNaNs ? Interop
+ .translateToAVNaN(zInterval.vmin) : zInterval.vmin;
+ double zmax = bArcViewNaNs ? Interop
+ .translateToAVNaN(zInterval.vmax) : zInterval.vmax;
+
+ // write min max values
+ shapeBuffer.putDouble(offset, zmin);
+ offset += 8;
+ shapeBuffer.putDouble(offset, zmax);
+ offset += 8;
+
+ if (!bEmpty) {
+ // write arbitrary z values
+ shapeBuffer.putDouble(offset, zmin);
+ offset += 8;
+ shapeBuffer.putDouble(offset, zmax);
+ offset += 8;
+ shapeBuffer.putDouble(offset, zmin);
+ offset += 8;
+ shapeBuffer.putDouble(offset, zmax);
+ offset += 8;
+ shapeBuffer.putDouble(offset, zmin);
+ offset += 8;
+ }
+ }
+ // write Ms
+ if (bExportMs) {
+ Envelope1D mInterval;
+ mInterval = envelope.queryInterval(Semantics.M, 0);
+
+ double mmin = bArcViewNaNs ? Interop
+ .translateToAVNaN(mInterval.vmin) : mInterval.vmin;
+ double mmax = bArcViewNaNs ? Interop
+ .translateToAVNaN(mInterval.vmax) : mInterval.vmax;
+
+ // write min max values
+ shapeBuffer.putDouble(offset, mmin);
+ offset += 8;
+ shapeBuffer.putDouble(offset, mmax);
+ offset += 8;
+
+ if (!bEmpty) {
+ // write arbitrary m values
+ shapeBuffer.putDouble(offset, mmin);
+ offset += 8;
+ shapeBuffer.putDouble(offset, mmax);
+ offset += 8;
+ shapeBuffer.putDouble(offset, mmin);
+ offset += 8;
+ shapeBuffer.putDouble(offset, mmax);
+ offset += 8;
+ shapeBuffer.putDouble(offset, mmin);
+ offset += 8;
+ }
+ }
+
+ // write IDs
+ if (bExportIDs && !bEmpty) {
+ Envelope1D idInterval;
+ idInterval = envelope.queryInterval(Semantics.ID, 0);
+
+ int idmin = (int) idInterval.vmin;
+ int idmax = (int) idInterval.vmax;
+
+ // write arbitrary id values
+ shapeBuffer.putInt(offset, idmin);
+ offset += 4;
+ shapeBuffer.putInt(offset, idmax);
+ offset += 4;
+ shapeBuffer.putInt(offset, idmin);
+ offset += 4;
+ shapeBuffer.putInt(offset, idmax);
+ offset += 4;
+ shapeBuffer.putInt(offset, idmin);
+ offset += 4;
+ }
+
+ return offset;
+ }
+
+ private static int exportPointToESRIShape(int exportFlags, Point point,
+ ByteBuffer shapeBuffer) {
+ boolean bExportZ = point.hasAttribute(Semantics.Z)
+ && (exportFlags & ShapeExportFlags.ShapeExportStripZs) == 0;
+ boolean bExportM = point.hasAttribute(Semantics.M)
+ && (exportFlags & ShapeExportFlags.ShapeExportStripMs) == 0;
+ boolean bExportID = point.hasAttribute(Semantics.ID)
+ && (exportFlags & ShapeExportFlags.ShapeExportStripIDs) == 0;
+ boolean bArcViewNaNs = (exportFlags & ShapeExportFlags.ShapeExportTrueNaNs) == 0;
+
+ int size = (4 /* type */) + (2 * 8 /* xy coordinate */);
+
+ if (bExportZ)
+ size += 8;
+ if (bExportM)
+ size += 8;
+ if (bExportID)
+ size += 4;
+
+ if (shapeBuffer == null)
+ return size;
+ else if (shapeBuffer.capacity() < size)
+ throw new GeometryException("buffer is too small");
+
+ int type;
+
+ // Determine the shape type
+ if (!bExportZ && !bExportM) {
+ if (bExportID)
+ type = ShapeType.ShapeGeneralPoint | ShapeModifiers.ShapeHasIDs;
+ else
+ type = ShapeType.ShapePoint;
+ } else if (bExportZ && !bExportM) {
+ if (bExportID)
+ type = ShapeType.ShapeGeneralPoint | ShapeModifiers.ShapeHasZs
+ | ShapeModifiers.ShapeHasIDs;
+ else
+ type = ShapeType.ShapePointZ;
+ } else if (bExportM && !bExportZ) {
+ if (bExportID)
+ type = ShapeType.ShapeGeneralPoint | ShapeModifiers.ShapeHasMs
+ | ShapeModifiers.ShapeHasIDs;
+ else
+ type = ShapeType.ShapePointM;
+ } else {
+ if (bExportID)
+ type = ShapeType.ShapeGeneralPoint | ShapeModifiers.ShapeHasZs
+ | ShapeModifiers.ShapeHasMs
+ | ShapeModifiers.ShapeHasIDs;
+ else
+ type = ShapeType.ShapePointZM;
+ }
+
+ int offset = 0;
+
+ // write type
+
+ shapeBuffer.putInt(offset, type);
+ offset += 4;
+
+ boolean bEmpty = point.isEmpty();
+
+ // write xy
+ double x = !bEmpty ? point.getX() : NumberUtils.NaN();
+ double y = !bEmpty ? point.getY() : NumberUtils.NaN();
+ shapeBuffer.putDouble(offset,
+ bArcViewNaNs ? Interop.translateToAVNaN(x) : x);
+ offset += 8;
+ shapeBuffer.putDouble(offset,
+ bArcViewNaNs ? Interop.translateToAVNaN(y) : y);
+ offset += 8;
+
+ // write Z
+ if (bExportZ) {
+ double z = !bEmpty ? point.getZ() : NumberUtils.NaN();
+ shapeBuffer.putDouble(offset,
+ bArcViewNaNs ? Interop.translateToAVNaN(z) : z);
+ offset += 8;
+ }
+
+ // WriteM
+ if (bExportM) {
+ double m = !bEmpty ? point.getM() : NumberUtils.NaN();
+ shapeBuffer.putDouble(offset,
+ bArcViewNaNs ? Interop.translateToAVNaN(m) : m);
+ offset += 8;
+ }
+
+ // write ID
+ if (bExportID) {
+ int id = !bEmpty ? point.getID() : 0;
+ shapeBuffer.putInt(offset, id);
+ offset += 4;
+ }
+
+ return offset;
+ }
+
+ private static int exportMultiPointToESRIShape(int exportFlags,
+ MultiPoint multipoint, ByteBuffer shapeBuffer) {
+ MultiPointImpl multipointImpl = (MultiPointImpl) multipoint._getImpl();
+ boolean bExportZs = multipointImpl.hasAttribute(Semantics.Z)
+ && (exportFlags & ShapeExportFlags.ShapeExportStripZs) == 0;
+ boolean bExportMs = multipointImpl.hasAttribute(Semantics.M)
+ && (exportFlags & ShapeExportFlags.ShapeExportStripMs) == 0;
+ boolean bExportIDs = multipointImpl.hasAttribute(Semantics.ID)
+ && (exportFlags & ShapeExportFlags.ShapeExportStripIDs) == 0;
+ boolean bArcViewNaNs = (exportFlags & ShapeExportFlags.ShapeExportTrueNaNs) == 0;
+
+ int pointCount = multipointImpl.getPointCount();
+
+ int size = (4 /* type */) + (4 * 8 /* envelope */) + (4 /* point count */)
+ + (pointCount * 2 * 8 /* xy coordinates */);
+
+ if (bExportZs)
+ size += (2 * 8 /* min max */) + (pointCount * 8 /* zs */);
+ if (bExportMs)
+ size += (2 * 8 /* min max */) + (pointCount * 8 /* ms */);
+ if (bExportIDs)
+ size += pointCount * 4 /* ids */;
+
+ if (size >= NumberUtils.intMax())
+ throw new GeometryException("invalid call");
+
+ if (shapeBuffer == null)
+ return size;
+ else if (shapeBuffer.capacity() < size)
+ throw new GeometryException("buffer is too small");
+
+ int type;
+
+ // Determine the shape type
+ if (!bExportZs && !bExportMs) {
+ if (bExportIDs)
+ type = ShapeType.ShapeGeneralMultiPoint
+ | ShapeModifiers.ShapeHasIDs;
+ else
+ type = ShapeType.ShapeMultiPoint;
+ } else if (bExportZs && !bExportMs) {
+ if (bExportIDs)
+ type = ShapeType.ShapeGeneralMultiPoint
+ | ShapeModifiers.ShapeHasZs
+ | ShapeModifiers.ShapeHasIDs;
+ else
+ type = ShapeType.ShapeMultiPointZ;
+ } else if (bExportMs && !bExportZs) {
+ if (bExportIDs)
+ type = ShapeType.ShapeGeneralMultiPoint
+ | ShapeModifiers.ShapeHasMs
+ | ShapeModifiers.ShapeHasIDs;
+ else
+ type = ShapeType.ShapeMultiPointM;
+ } else {
+ if (bExportIDs)
+ type = ShapeType.ShapeGeneralMultiPoint
+ | ShapeModifiers.ShapeHasZs | ShapeModifiers.ShapeHasMs
+ | ShapeModifiers.ShapeHasIDs;
+ else
+ type = ShapeType.ShapeMultiPointZM;
+ }
+
+ // write type
+ int offset = 0;
+
+ shapeBuffer.putInt(offset, type);
+ offset += 4;
+
+ // write Envelope
+ Envelope2D env = new Envelope2D();
+ multipointImpl.queryEnvelope2D(env); // calls _VerifyAllStreams
+ shapeBuffer.putDouble(offset, env.xmin);
+ offset += 8;
+ shapeBuffer.putDouble(offset, env.ymin);
+ offset += 8;
+ shapeBuffer.putDouble(offset, env.xmax);
+ offset += 8;
+ shapeBuffer.putDouble(offset, env.ymax);
+ offset += 8;
+
+ // write point count
+ shapeBuffer.putInt(offset, pointCount);
+ offset += 4;
+
+ if (pointCount > 0) {
+ // write xy coordinates
+ AttributeStreamBase positionStream = multipointImpl
+ .getAttributeStreamRef(Semantics.POSITION);
+ AttributeStreamOfDbl position = (AttributeStreamOfDbl) positionStream;
+ for (int i = 0; i < pointCount; i++) {
+ double x = position.read(2 * i);
+ double y = position.read(2 * i + 1);
+ shapeBuffer.putDouble(offset, x);
+ offset += 8;
+ shapeBuffer.putDouble(offset, y);
+ offset += 8;
+ }
+ }
+
+ // write Zs
+ if (bExportZs) {
+ Envelope1D zInterval = multipointImpl.queryInterval(Semantics.Z, 0);
+ shapeBuffer.putDouble(offset,
+ bArcViewNaNs ? Interop.translateToAVNaN(zInterval.vmin)
+ : zInterval.vmin);
+ offset += 8;
+ shapeBuffer.putDouble(offset,
+ bArcViewNaNs ? Interop.translateToAVNaN(zInterval.vmax)
+ : zInterval.vmax);
+ offset += 8;
+
+ if (pointCount > 0) {
+ if (multipointImpl._attributeStreamIsAllocated(Semantics.Z)) {
+ AttributeStreamOfDbl zs = (AttributeStreamOfDbl) multipointImpl
+ .getAttributeStreamRef(Semantics.Z);
+ for (int i = 0; i < pointCount; i++) {
+ double z = zs.read(i);
+ shapeBuffer.putDouble(offset,
+ bArcViewNaNs ? Interop.translateToAVNaN(z) : z);
+ offset += 8;
+ }
+ } else {
+ double z = VertexDescription.getDefaultValue(Semantics.Z);
+
+ if (bArcViewNaNs)
+ z = Interop.translateToAVNaN(z);
+
+ // Can we write a function that writes all these values at
+ // once instead of doing a for loop?
+ for (int i = 0; i < pointCount; i++)
+ shapeBuffer.putDouble(offset, z);
+ offset += 8;
+ }
+ }
+ }
+
+ // write Ms
+ if (bExportMs) {
+ Envelope1D mInterval = multipointImpl.queryInterval(Semantics.M, 0);
+ shapeBuffer.putDouble(offset,
+ bArcViewNaNs ? Interop.translateToAVNaN(mInterval.vmin)
+ : mInterval.vmin);
+ offset += 8;
+ shapeBuffer.putDouble(offset,
+ bArcViewNaNs ? Interop.translateToAVNaN(mInterval.vmax)
+ : mInterval.vmax);
+ offset += 8;
+
+ if (pointCount > 0) {
+ if (multipointImpl._attributeStreamIsAllocated(Semantics.M)) {
+ AttributeStreamOfDbl ms = (AttributeStreamOfDbl) multipointImpl
+ .getAttributeStreamRef(Semantics.M);
+ for (int i = 0; i < pointCount; i++) {
+ double m = ms.read(i);
+ shapeBuffer.putDouble(offset,
+ bArcViewNaNs ? Interop.translateToAVNaN(m) : m);
+ offset += 8;
+ }
+ } else {
+ double m = VertexDescription.getDefaultValue(Semantics.M);
+
+ if (bArcViewNaNs)
+ m = Interop.translateToAVNaN(m);
+
+ for (int i = 0; i < pointCount; i++)
+ shapeBuffer.putDouble(offset, m);
+ offset += 8;
+ }
+ }
+ }
+
+ // write IDs
+ if (bExportIDs) {
+ if (pointCount > 0) {
+ if (multipointImpl._attributeStreamIsAllocated(Semantics.ID)) {
+ AttributeStreamOfInt32 ids = (AttributeStreamOfInt32) multipointImpl
+ .getAttributeStreamRef(Semantics.ID);
+ for (int i = 0; i < pointCount; i++) {
+ int id = ids.read(i);
+ shapeBuffer.putInt(offset, id);
+ offset += 4;
+ }
+ } else {
+ int id = (int) VertexDescription
+ .getDefaultValue(Semantics.ID);
+ for (int i = 0; i < pointCount; i++)
+ shapeBuffer.putInt(offset, id);
+ offset += 4;
+ }
+ }
+ }
+
+ return offset;
+ }
+
+ private static int exportMultiPathToESRIShape(boolean bPolygon,
+ int exportFlags, MultiPath multipath, ByteBuffer shapeBuffer) {
+ MultiPathImpl multipathImpl = (MultiPathImpl) multipath._getImpl();
+
+ boolean bExportZs = multipathImpl.hasAttribute(Semantics.Z)
+ && (exportFlags & ShapeExportFlags.ShapeExportStripZs) == 0;
+ boolean bExportMs = multipathImpl.hasAttribute(Semantics.M)
+ && (exportFlags & ShapeExportFlags.ShapeExportStripMs) == 0;
+ boolean bExportIDs = multipathImpl.hasAttribute(Semantics.ID)
+ && (exportFlags & ShapeExportFlags.ShapeExportStripIDs) == 0;
+ boolean bHasCurves = multipathImpl.hasNonLinearSegments();
+ boolean bArcViewNaNs = (exportFlags & ShapeExportFlags.ShapeExportTrueNaNs) == 0;
+
+ int partCount = multipathImpl.getPathCount();
+ int pointCount = multipathImpl.getPointCount();
+
+ if (!bPolygon) {
+ for (int ipart = 0; ipart < partCount; ipart++)
+ if (multipath.isClosedPath(ipart))
+ pointCount++;
+ } else
+ pointCount += partCount;
+
+ int size = (4 /* type */) + (4 * 8 /* envelope */) + (4 /* part count */)
+ + (4 /* point count */) + (partCount * 4 /* start indices */)
+ + pointCount * 2 * 8 /* xy coordinates */;
+
+ if (bExportZs)
+ size += (2 * 8 /* min max */) + (pointCount * 8 /* zs */);
+ if (bExportMs)
+ size += (2 * 8 /* min max */) + (pointCount * 8 /* ms */);
+ if (bExportIDs)
+ size += pointCount * 4 /* ids */;
+ if (bHasCurves) {
+ // to-do: curves
+ }
+
+ if (size >= NumberUtils.intMax())
+ throw new GeometryException("invalid call");
+
+ if (shapeBuffer == null)
+ return size;
+ else if (shapeBuffer.capacity() < size)
+ throw new GeometryException("buffer is too small");
+
+ int offset = 0;
+
+ // Determine the shape type
+ int type;
+ if (!bExportZs && !bExportMs) {
+ if (bExportIDs || bHasCurves) {
+ type = bPolygon ? ShapeType.ShapeGeneralPolygon
+ : ShapeType.ShapeGeneralPolyline;
+ if (bExportIDs)
+ type |= ShapeModifiers.ShapeHasIDs;
+ if (bHasCurves)
+ type |= ShapeModifiers.ShapeHasCurves;
+ } else
+ type = bPolygon ? ShapeType.ShapePolygon
+ : ShapeType.ShapePolyline;
+ } else if (bExportZs && !bExportMs) {
+ if (bExportIDs || bHasCurves) {
+ type = bPolygon ? ShapeType.ShapeGeneralPolygon
+ : ShapeType.ShapeGeneralPolyline;
+ type |= ShapeModifiers.ShapeHasZs;
+ if (bExportIDs)
+ type |= ShapeModifiers.ShapeHasIDs;
+ if (bHasCurves)
+ type |= ShapeModifiers.ShapeHasCurves;
+ } else
+ type = bPolygon ? ShapeType.ShapePolygonZ
+ : ShapeType.ShapePolylineZ;
+ } else if (bExportMs && !bExportZs) {
+ if (bExportIDs || bHasCurves) {
+ type = bPolygon ? ShapeType.ShapeGeneralPolygon
+ : ShapeType.ShapeGeneralPolyline;
+ type |= ShapeModifiers.ShapeHasMs;
+ if (bExportIDs)
+ type |= ShapeModifiers.ShapeHasIDs;
+ if (bHasCurves)
+ type |= ShapeModifiers.ShapeHasCurves;
+ } else
+ type = bPolygon ? ShapeType.ShapePolygonM
+ : ShapeType.ShapePolylineM;
+ } else {
+ if (bExportIDs || bHasCurves) {
+ type = bPolygon ? ShapeType.ShapeGeneralPolygon
+ : ShapeType.ShapeGeneralPolyline;
+ type |= ShapeModifiers.ShapeHasZs | ShapeModifiers.ShapeHasMs;
+ if (bExportIDs)
+ type |= ShapeModifiers.ShapeHasIDs;
+ if (bHasCurves)
+ type |= ShapeModifiers.ShapeHasCurves;
+ } else
+ type = bPolygon ? ShapeType.ShapePolygonZM
+ : ShapeType.ShapePolylineZM;
+ }
+
+ // write type
+ shapeBuffer.putInt(offset, type);
+ offset += 4;
+
+ // write Envelope
+ Envelope2D env = new Envelope2D();
+ multipathImpl.queryEnvelope2D(env); // calls _VerifyAllStreams
+ shapeBuffer.putDouble(offset, env.xmin);
+ offset += 8;
+ shapeBuffer.putDouble(offset, env.ymin);
+ offset += 8;
+ shapeBuffer.putDouble(offset, env.xmax);
+ offset += 8;
+ shapeBuffer.putDouble(offset, env.ymax);
+ offset += 8;
+
+ // write part count
+ shapeBuffer.putInt(offset, partCount);
+ offset += 4; // to-do: return error if larger than 2^32 - 1
+
+ // write pointCount
+ shapeBuffer.putInt(offset, pointCount);
+ offset += 4;
+
+ // write start indices for each part
+ int pointIndexDelta = 0;
+ for (int ipart = 0; ipart < partCount; ipart++) {
+ int istart = multipathImpl.getPathStart(ipart) + pointIndexDelta;
+ shapeBuffer.putInt(offset, istart);
+ offset += 4;
+ if (bPolygon || multipathImpl.isClosedPath(ipart))
+ pointIndexDelta++;
+ }
+
+ if (pointCount > 0) {
+ // write xy coordinates
+ AttributeStreamBase positionStream = multipathImpl
+ .getAttributeStreamRef(Semantics.POSITION);
+ AttributeStreamOfDbl position = (AttributeStreamOfDbl) positionStream;
+
+ for (int ipart = 0; ipart < partCount; ipart++) {
+ int partStart = multipathImpl.getPathStart(ipart);
+ int partEnd = multipathImpl.getPathEnd(ipart);
+ for (int i = partStart; i < partEnd; i++) {
+ double x = position.read(2 * i);
+ double y = position.read(2 * i + 1);
+
+ shapeBuffer.putDouble(offset, x);
+ offset += 8;
+ shapeBuffer.putDouble(offset, y);
+ offset += 8;
+ }
+
+ // If the part is closed, then we need to duplicate the start
+ // point
+ if (bPolygon || multipathImpl.isClosedPath(ipart)) {
+ double x = position.read(2 * partStart);
+ double y = position.read(2 * partStart + 1);
+
+ shapeBuffer.putDouble(offset, x);
+ offset += 8;
+ shapeBuffer.putDouble(offset, y);
+ offset += 8;
+ }
+ }
+ }
+
+ // write Zs
+ if (bExportZs) {
+ Envelope1D zInterval = multipathImpl.queryInterval(Semantics.Z, 0);
+ shapeBuffer.putDouble(offset,
+ bArcViewNaNs ? Interop.translateToAVNaN(zInterval.vmin)
+ : zInterval.vmin);
+ offset += 8;
+ shapeBuffer.putDouble(offset,
+ bArcViewNaNs ? Interop.translateToAVNaN(zInterval.vmax)
+ : zInterval.vmax);
+ offset += 8;
+
+ if (pointCount > 0) {
+ if (multipathImpl._attributeStreamIsAllocated(Semantics.Z)) {
+ AttributeStreamOfDbl zs = (AttributeStreamOfDbl) multipathImpl
+ .getAttributeStreamRef(Semantics.Z);
+ for (int ipart = 0; ipart < partCount; ipart++) {
+ int partStart = multipathImpl.getPathStart(ipart);
+ int partEnd = multipathImpl.getPathEnd(ipart);
+ for (int i = partStart; i < partEnd; i++) {
+ double z = zs.read(i);
+ shapeBuffer.putDouble(offset,
+ bArcViewNaNs ? Interop.translateToAVNaN(z)
+ : z);
+ offset += 8;
+ }
+
+ // If the part is closed, then we need to duplicate the
+ // start z
+ if (bPolygon || multipathImpl.isClosedPath(ipart)) {
+ double z = zs.read(partStart);
+ shapeBuffer.putDouble(offset, z);
+ offset += 8;
+ }
+ }
+ } else {
+ double z = VertexDescription.getDefaultValue(Semantics.Z);
+
+ if (bArcViewNaNs)
+ z = Interop.translateToAVNaN(z);
+
+ for (int i = 0; i < pointCount; i++)
+ shapeBuffer.putDouble(offset, z);
+ offset += 8;
+ }
+ }
+ }
+
+ // write Ms
+ if (bExportMs) {
+ Envelope1D mInterval = multipathImpl.queryInterval(Semantics.M, 0);
+ shapeBuffer.putDouble(offset,
+ bArcViewNaNs ? Interop.translateToAVNaN(mInterval.vmin)
+ : mInterval.vmin);
+ offset += 8;
+ shapeBuffer.putDouble(offset,
+ bArcViewNaNs ? Interop.translateToAVNaN(mInterval.vmax)
+ : mInterval.vmax);
+ offset += 8;
+
+ if (pointCount > 0) {
+ if (multipathImpl._attributeStreamIsAllocated(Semantics.M)) {
+ AttributeStreamOfDbl ms = (AttributeStreamOfDbl) multipathImpl
+ .getAttributeStreamRef(Semantics.M);
+ for (int ipart = 0; ipart < partCount; ipart++) {
+ int partStart = multipathImpl.getPathStart(ipart);
+ int partEnd = multipathImpl.getPathEnd(ipart);
+ for (int i = partStart; i < partEnd; i++) {
+ double m = ms.read(i);
+ shapeBuffer.putDouble(offset,
+ bArcViewNaNs ? Interop.translateToAVNaN(m)
+ : m);
+ offset += 8;
+ }
+
+ // If the part is closed, then we need to duplicate the
+ // start m
+ if (bPolygon || multipathImpl.isClosedPath(ipart)) {
+ double m = ms.read(partStart);
+ shapeBuffer.putDouble(offset, m);
+ offset += 8;
+ }
+ }
+ } else {
+ double m = VertexDescription.getDefaultValue(Semantics.M);
+
+ if (bArcViewNaNs)
+ m = Interop.translateToAVNaN(m);
+
+ for (int i = 0; i < pointCount; i++)
+ shapeBuffer.putDouble(offset, m);
+ offset += 8;
+ }
+ }
+ }
+
+ // write Curves
+ if (bHasCurves) {
+ // to-do: We'll finish this later
+ }
+
+ // write IDs
+ if (bExportIDs) {
+ if (pointCount > 0) {
+ if (multipathImpl._attributeStreamIsAllocated(Semantics.ID)) {
+ AttributeStreamOfInt32 ids = (AttributeStreamOfInt32) multipathImpl
+ .getAttributeStreamRef(Semantics.ID);
+ for (int ipart = 0; ipart < partCount; ipart++) {
+ int partStart = multipathImpl.getPathStart(ipart);
+ int partEnd = multipathImpl.getPathEnd(ipart);
+ for (int i = partStart; i < partEnd; i++) {
+ int id = ids.read(i);
+ shapeBuffer.putInt(offset, id);
+ offset += 4;
+ }
+
+ // If the part is closed, then we need to duplicate the
+ // start id
+ if (bPolygon || multipathImpl.isClosedPath(ipart)) {
+ int id = ids.read(partStart);
+ shapeBuffer.putInt(offset, id);
+ offset += 4;
+ }
+ }
+ } else {
+ int id = (int) VertexDescription
+ .getDefaultValue(Semantics.ID);
+ for (int i = 0; i < pointCount; i++)
+ shapeBuffer.putInt(offset, id);
+ offset += 4;
+ }
+ }
+ }
+
+ return offset;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorExportToESRIShapeLocal.java b/src/main/java/com/esri/core/geometry/OperatorExportToESRIShapeLocal.java
index ce3c7b4c..071a9428 100644
--- a/src/main/java/com/esri/core/geometry/OperatorExportToESRIShapeLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorExportToESRIShapeLocal.java
@@ -32,23 +32,23 @@
*/
class OperatorExportToESRIShapeLocal extends OperatorExportToESRIShape {
- @Override
- public ByteBufferCursor execute(int exportFlags, GeometryCursor geometryCursor) {
- return new OperatorExportToESRIShapeCursor(exportFlags, geometryCursor);
- }
-
- @Override
- public ByteBuffer execute(int exportFlags, Geometry geometry) {
- ByteBuffer shapeBuffer = null;
- int size = OperatorExportToESRIShapeCursor.exportToESRIShape(exportFlags, geometry, shapeBuffer);
- shapeBuffer = ByteBuffer.allocate(size).order(ByteOrder.LITTLE_ENDIAN);
- OperatorExportToESRIShapeCursor.exportToESRIShape(exportFlags, geometry, shapeBuffer);
- return shapeBuffer;
- }
-
- @Override
- public int execute(int exportFlags, Geometry geometry, ByteBuffer shapeBuffer) {
- shapeBuffer.order(ByteOrder.LITTLE_ENDIAN);
- return OperatorExportToESRIShapeCursor.exportToESRIShape(exportFlags, geometry, shapeBuffer);
- }
+ @Override
+ public ByteBufferCursor execute(int exportFlags, GeometryCursor geometryCursor) {
+ return new OperatorExportToESRIShapeCursor(exportFlags, geometryCursor);
+ }
+
+ @Override
+ public ByteBuffer execute(int exportFlags, Geometry geometry) {
+ ByteBuffer shapeBuffer = null;
+ int size = OperatorExportToESRIShapeCursor.exportToESRIShape(exportFlags, geometry, shapeBuffer);
+ shapeBuffer = ByteBuffer.allocate(size).order(ByteOrder.LITTLE_ENDIAN);
+ OperatorExportToESRIShapeCursor.exportToESRIShape(exportFlags, geometry, shapeBuffer);
+ return shapeBuffer;
+ }
+
+ @Override
+ public int execute(int exportFlags, Geometry geometry, ByteBuffer shapeBuffer) {
+ shapeBuffer.order(ByteOrder.LITTLE_ENDIAN);
+ return OperatorExportToESRIShapeCursor.exportToESRIShape(exportFlags, geometry, shapeBuffer);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorExportToGeoJson.java b/src/main/java/com/esri/core/geometry/OperatorExportToGeoJson.java
index 656070de..52af8dfe 100644
--- a/src/main/java/com/esri/core/geometry/OperatorExportToGeoJson.java
+++ b/src/main/java/com/esri/core/geometry/OperatorExportToGeoJson.java
@@ -28,57 +28,57 @@
* Export to GeoJson format.
*/
public abstract class OperatorExportToGeoJson extends Operator {
- @Override
- public Type getType() {
- return Type.ExportToGeoJson;
- }
+ @Override
+ public Type getType() {
+ return Type.ExportToGeoJson;
+ }
- /**
- * Performs the ExportToGeoJson operation
- *
- * @param spatialReference The SpatialReference of the Geometry. Will be written as "crs":null if the spatialReference is null.
- * @param geometryCursor The cursor of geometries to write as GeoJson.
- * @return Returns a JsonCursor.
- */
- public abstract StringCursor execute(SpatialReference spatialReference, GeometryCursor geometryCursor);
+ /**
+ * Performs the ExportToGeoJson operation
+ *
+ * @param spatialReference The SpatialReference of the Geometry. Will be written as "crs":null if the spatialReference is null.
+ * @param geometryCursor The cursor of geometries to write as GeoJson.
+ * @return Returns a JsonCursor.
+ */
+ public abstract StringCursor execute(SpatialReference spatialReference, GeometryCursor geometryCursor);
- /**
- * Performs the ExportToGeoJson operation
- *
- * @param spatialReference The SpatialReference of the Geometry. Will be written as "crs":null if the spatialReference is null.
- * @param geometry The Geometry to write as GeoJson.
- * @return Returns a string in GeoJson format.
- */
- public abstract String execute(SpatialReference spatialReference, Geometry geometry);
+ /**
+ * Performs the ExportToGeoJson operation
+ *
+ * @param spatialReference The SpatialReference of the Geometry. Will be written as "crs":null if the spatialReference is null.
+ * @param geometry The Geometry to write as GeoJson.
+ * @return Returns a string in GeoJson format.
+ */
+ public abstract String execute(SpatialReference spatialReference, Geometry geometry);
- /**
- * Performs the ExportToGeoJson operation
- *
- * @param exportFlags Use the {@link GeoJsonExportFlags} interface.
- * @param spatialReference The SpatialReference of the Geometry. Will be written as "crs":null if the spatialReference is null.
- * @param geometry The Geometry to write as GeoJson.
- * @return Returns a string in GeoJson format.
- */
- public abstract String execute(int exportFlags, SpatialReference spatialReference, Geometry geometry);
+ /**
+ * Performs the ExportToGeoJson operation
+ *
+ * @param exportFlags Use the {@link GeoJsonExportFlags} interface.
+ * @param spatialReference The SpatialReference of the Geometry. Will be written as "crs":null if the spatialReference is null.
+ * @param geometry The Geometry to write as GeoJson.
+ * @return Returns a string in GeoJson format.
+ */
+ public abstract String execute(int exportFlags, SpatialReference spatialReference, Geometry geometry);
- /**
- * Performs the ExportToGeoJson operation. Will not write out a spatial reference or crs tag. Assumes the geometry is in wgs84.
- *
- * @param geometry The Geometry to write as GeoJson.
- * @return Returns a string in GeoJson format.
- */
- public abstract String execute(Geometry geometry);
+ /**
+ * Performs the ExportToGeoJson operation. Will not write out a spatial reference or crs tag. Assumes the geometry is in wgs84.
+ *
+ * @param geometry The Geometry to write as GeoJson.
+ * @return Returns a string in GeoJson format.
+ */
+ public abstract String execute(Geometry geometry);
- /**
- * Performs the ExportToGeoJson operation on a spatial reference.
- *
- * @param export_flags The flags used for the export.
- * @param spatial_reference The spatial reference being exported. Cannot be null.
- * @return Returns the crs value object.
- */
- public abstract String exportSpatialReference(int export_flags, SpatialReference spatial_reference);
+ /**
+ * Performs the ExportToGeoJson operation on a spatial reference.
+ *
+ * @param export_flags The flags used for the export.
+ * @param spatial_reference The spatial reference being exported. Cannot be null.
+ * @return Returns the crs value object.
+ */
+ public abstract String exportSpatialReference(int export_flags, SpatialReference spatial_reference);
- public static OperatorExportToGeoJson local() {
- return (OperatorExportToGeoJson) OperatorFactoryLocal.getInstance().getOperator(Type.ExportToGeoJson);
- }
+ public static OperatorExportToGeoJson local() {
+ return (OperatorExportToGeoJson) OperatorFactoryLocal.getInstance().getOperator(Type.ExportToGeoJson);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorExportToGeoJsonCursor.java b/src/main/java/com/esri/core/geometry/OperatorExportToGeoJsonCursor.java
index b5713159..33c1e926 100644
--- a/src/main/java/com/esri/core/geometry/OperatorExportToGeoJsonCursor.java
+++ b/src/main/java/com/esri/core/geometry/OperatorExportToGeoJsonCursor.java
@@ -48,768 +48,770 @@
import com.esri.core.geometry.VertexDescription.Semantics;
public class OperatorExportToGeoJsonCursor extends StringCursor {
- private GeometryCursor m_geometryCursor;
- private SpatialReference m_spatialReference;
- private int m_export_flags;
- private SimpleStateEnum simpleStateEnum = SimpleStateEnum.SIMPLE_UNKNOWN;
-
- public OperatorExportToGeoJsonCursor(int export_flags, SpatialReference spatialReference,
- GeometryCursor geometryCursor) {
- if (geometryCursor == null)
- throw new IllegalArgumentException();
-
- m_export_flags = export_flags;
- m_spatialReference = spatialReference;
- m_geometryCursor = geometryCursor;
- }
+ private GeometryCursor m_geometryCursor;
+ private SpatialReference m_spatialReference;
+ private int m_export_flags;
+ private SimpleStateEnum simpleStateEnum = SimpleStateEnum.SIMPLE_UNKNOWN;
+
+ public OperatorExportToGeoJsonCursor(int export_flags, SpatialReference spatialReference,
+ GeometryCursor geometryCursor) {
+ if (geometryCursor == null)
+ throw new IllegalArgumentException();
+
+ m_export_flags = export_flags;
+ m_spatialReference = spatialReference;
+ m_geometryCursor = geometryCursor;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return m_geometryCursor != null && m_geometryCursor.hasNext();
+ }
+
+ @Override
+ public long getID() {
+ return m_geometryCursor.getGeometryID();
+ }
- @Override
- public boolean hasNext() { return m_geometryCursor != null && m_geometryCursor.hasNext(); }
+ @Override
+ public SimpleStateEnum getSimpleState() {
+ return simpleStateEnum;
+ }
- @Override
- public long getID() {
- return m_geometryCursor.getGeometryID();
- }
+ @Override
+ public String getFeatureID() {
+ return m_geometryCursor.getFeatureID();
+ }
- @Override
- public SimpleStateEnum getSimpleState() {
- return simpleStateEnum;
- }
+ @Override
+ public String next() {
+ Geometry geometry;
+ if (hasNext()) {
+ geometry = m_geometryCursor.next();
+ simpleStateEnum = geometry.getSimpleState();
+ return exportToGeoJson(m_export_flags, geometry, m_spatialReference);
+ }
+ return null;
+ }
- @Override
- public String getFeatureID() {
- return m_geometryCursor.getFeatureID();
- }
+ // Mirrors wkt
+ static String exportToGeoJson(int export_flags, Geometry geometry, SpatialReference spatial_reference) {
- @Override
- public String next() {
- Geometry geometry;
- if (hasNext()) {
- geometry = m_geometryCursor.next();
- simpleStateEnum = geometry.getSimpleState();
- return exportToGeoJson(m_export_flags, geometry, m_spatialReference);
- }
- return null;
- }
+ if (geometry == null)
+ throw new IllegalArgumentException("");
- // Mirrors wkt
- static String exportToGeoJson(int export_flags, Geometry geometry, SpatialReference spatial_reference) {
+ JsonWriter json_writer = new JsonStringWriter();
- if (geometry == null)
- throw new IllegalArgumentException("");
+ json_writer.startObject();
- JsonWriter json_writer = new JsonStringWriter();
+ exportGeometryToGeoJson_(export_flags, geometry, json_writer);
- json_writer.startObject();
+ if ((export_flags & GeoJsonExportFlags.geoJsonExportSkipCRS) == 0) {
+ json_writer.addFieldName("crs");
+ exportSpatialReference(export_flags, spatial_reference, json_writer);
+ }
- exportGeometryToGeoJson_(export_flags, geometry, json_writer);
+ json_writer.endObject();
- if ((export_flags & GeoJsonExportFlags.geoJsonExportSkipCRS) == 0) {
- json_writer.addFieldName("crs");
- exportSpatialReference(export_flags, spatial_reference, json_writer);
- }
+ return (String) json_writer.getJson();
+ }
- json_writer.endObject();
+ static String exportSpatialReference(int export_flags, SpatialReference spatial_reference) {
+ if (spatial_reference == null || (export_flags & GeoJsonExportFlags.geoJsonExportSkipCRS) != 0)
+ throw new IllegalArgumentException("");
+
+ JsonWriter json_writer = new JsonStringWriter();
+ exportSpatialReference(export_flags, spatial_reference, json_writer);
- return (String) json_writer.getJson();
- }
+ return (String) json_writer.getJson();
+ }
+
+ private static void exportGeometryToGeoJson_(int export_flags, Geometry geometry, JsonWriter json_writer) {
+ int type = geometry.getType().value();
+ switch (type) {
+ case Geometry.GeometryType.Polygon:
+ exportPolygonToGeoJson_(export_flags, (Polygon) geometry, json_writer);
+ return;
+
+ case Geometry.GeometryType.Polyline:
+ exportPolylineToGeoJson_(export_flags, (Polyline) geometry, json_writer);
+ return;
+
+ case Geometry.GeometryType.MultiPoint:
+ exportMultiPointToGeoJson_(export_flags, (MultiPoint) geometry, json_writer);
+ return;
+
+ case Geometry.GeometryType.Point:
+ exportPointToGeoJson_(export_flags, (Point) geometry, json_writer);
+ return;
+
+ case Geometry.GeometryType.Envelope:
+ exportEnvelopeToGeoJson_(export_flags, (Envelope) geometry,
+ json_writer);
+ return;
+
+ default:
+ throw new RuntimeException("not implemented for this geometry type");
+ }
+ }
+
+ private static void exportSpatialReference(int export_flags, SpatialReference spatial_reference,
+ JsonWriter json_writer) {
+ if (spatial_reference != null) {
+ int wkid = spatial_reference.getLatestID();
+
+ if (wkid <= 0)
+ throw new GeometryException("invalid call");
+
+ json_writer.startObject();
+
+ json_writer.addFieldName("type");
+
+ json_writer.addValueString("name");
+
+ json_writer.addFieldName("properties");
+ json_writer.startObject();
+
+ json_writer.addFieldName("name");
+
+ String authority = ((SpatialReferenceImpl) spatial_reference).getAuthority();
+ authority = authority.toUpperCase();
+ StringBuilder crs_identifier = new StringBuilder(authority);
+ crs_identifier.append(':');
+ crs_identifier.append(wkid);
+ json_writer.addValueString(crs_identifier.toString());
+
+ json_writer.endObject();
+
+ json_writer.endObject();
+ } else {
+ json_writer.addValueNull();
+ }
+ }
+
+ // Mirrors wkt
+ private static void exportPolygonToGeoJson_(int export_flags, Polygon polygon, JsonWriter json_writer) {
+ MultiPathImpl polygon_impl = (MultiPathImpl) (polygon._getImpl());
+
+ if ((export_flags & GeoJsonExportFlags.geoJsonExportFailIfNotSimple) != 0) {
+ int simple = polygon_impl.getIsSimple(0.0);
+
+ if (simple != MultiPathImpl.GeometryXSimple.Strong)
+ throw new GeometryException("corrupted geometry");
+ }
+
+ int point_count = polygon.getPointCount();
+ int polygon_count = polygon_impl.getOGCPolygonCount();
+
+ if (point_count > 0 && polygon_count == 0)
+ throw new GeometryException("corrupted geometry");
+
+ int precision = 17 - (31 & (export_flags >> 13));
+ boolean bFixedPoint = (GeoJsonExportFlags.geoJsonExportPrecisionFixedPoint & export_flags) != 0;
+ boolean b_export_zs = polygon_impl.hasAttribute(VertexDescription.Semantics.Z)
+ && (export_flags & GeoJsonExportFlags.geoJsonExportStripZs) == 0;
+ boolean b_export_ms = polygon_impl.hasAttribute(VertexDescription.Semantics.M)
+ && (export_flags & GeoJsonExportFlags.geoJsonExportStripMs) == 0;
+
+ if (!b_export_zs && b_export_ms)
+ throw new IllegalArgumentException("invalid argument");
+
+ int path_count = 0;
+ AttributeStreamOfDbl position = null;
+ AttributeStreamOfDbl zs = null;
+ AttributeStreamOfDbl ms = null;
+ AttributeStreamOfInt8 path_flags = null;
+ AttributeStreamOfInt32 paths = null;
+
+ if (point_count > 0) {
+ position = (AttributeStreamOfDbl) polygon_impl.getAttributeStreamRef(Semantics.POSITION);
+ path_flags = polygon_impl.getPathFlagsStreamRef();
+ paths = polygon_impl.getPathStreamRef();
+ path_count = polygon_impl.getPathCount();
+
+ if (b_export_zs) {
+ if (polygon_impl._attributeStreamIsAllocated(Semantics.Z))
+ zs = (AttributeStreamOfDbl) polygon_impl.getAttributeStreamRef(Semantics.Z);
+ }
+
+ if (b_export_ms) {
+ if (polygon_impl._attributeStreamIsAllocated(Semantics.M))
+ ms = (AttributeStreamOfDbl) polygon_impl.getAttributeStreamRef(Semantics.M);
+ }
+ }
+
+ if ((export_flags & GeoJsonExportFlags.geoJsonExportPreferMultiGeometry) == 0 && polygon_count <= 1)
+ polygonTaggedText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, paths, path_count,
+ json_writer);
+ else
+ multiPolygonTaggedText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, path_flags,
+ paths, polygon_count, path_count, json_writer);
+ }
+
+ // Mirrors wkt
+ private static void exportPolylineToGeoJson_(int export_flags, Polyline polyline, JsonWriter json_writer) {
+ MultiPathImpl polyline_impl = (MultiPathImpl) polyline._getImpl();
+
+ int point_count = polyline_impl.getPointCount();
+ int path_count = polyline_impl.getPathCount();
+
+ if (point_count > 0 && path_count == 0)
+ throw new GeometryException("corrupted geometry");
+
+ int precision = 17 - (31 & (export_flags >> 13));
+ boolean bFixedPoint = (GeoJsonExportFlags.geoJsonExportPrecisionFixedPoint & export_flags) != 0;
+ boolean b_export_zs = polyline_impl.hasAttribute(VertexDescription.Semantics.Z)
+ && (export_flags & GeoJsonExportFlags.geoJsonExportStripZs) == 0;
+ boolean b_export_ms = polyline_impl.hasAttribute(VertexDescription.Semantics.M)
+ && (export_flags & GeoJsonExportFlags.geoJsonExportStripMs) == 0;
+
+ if (!b_export_zs && b_export_ms)
+ throw new IllegalArgumentException("invalid argument");
+
+ AttributeStreamOfDbl position = null;
+ AttributeStreamOfDbl zs = null;
+ AttributeStreamOfDbl ms = null;
+ AttributeStreamOfInt8 path_flags = null;
+ AttributeStreamOfInt32 paths = null;
+
+ if (point_count > 0) {
+ position = (AttributeStreamOfDbl) polyline_impl.getAttributeStreamRef(Semantics.POSITION);
+ path_flags = polyline_impl.getPathFlagsStreamRef();
+ paths = polyline_impl.getPathStreamRef();
+
+ if (b_export_zs) {
+ if (polyline_impl._attributeStreamIsAllocated(Semantics.Z))
+ zs = (AttributeStreamOfDbl) polyline_impl.getAttributeStreamRef(Semantics.Z);
+ }
+
+ if (b_export_ms) {
+ if (polyline_impl._attributeStreamIsAllocated(Semantics.M))
+ ms = (AttributeStreamOfDbl) polyline_impl.getAttributeStreamRef(Semantics.M);
+ }
+ }
+
+ if ((export_flags & GeoJsonExportFlags.geoJsonExportPreferMultiGeometry) == 0 && path_count <= 1)
+ lineStringTaggedText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, path_flags, paths,
+ json_writer);
+ else
+ multiLineStringTaggedText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, path_flags,
+ paths, path_count, json_writer);
+ }
+
+ // Mirrors wkt
+ private static void exportMultiPointToGeoJson_(int export_flags, MultiPoint multipoint, JsonWriter json_writer) {
+ MultiPointImpl multipoint_impl = (MultiPointImpl) multipoint._getImpl();
+
+ int point_count = multipoint_impl.getPointCount();
+
+ int precision = 17 - (31 & (export_flags >> 13));
+ boolean bFixedPoint = (GeoJsonExportFlags.geoJsonExportPrecisionFixedPoint & export_flags) != 0;
+ boolean b_export_zs = multipoint_impl.hasAttribute(VertexDescription.Semantics.Z)
+ && (export_flags & GeoJsonExportFlags.geoJsonExportStripZs) == 0;
+ boolean b_export_ms = multipoint_impl.hasAttribute(VertexDescription.Semantics.M)
+ && (export_flags & GeoJsonExportFlags.geoJsonExportStripMs) == 0;
+
+ if (!b_export_zs && b_export_ms)
+ throw new IllegalArgumentException("invalid argument");
+
+ AttributeStreamOfDbl position = null;
+ AttributeStreamOfDbl zs = null;
+ AttributeStreamOfDbl ms = null;
+
+ if (point_count > 0) {
+ position = (AttributeStreamOfDbl) multipoint_impl.getAttributeStreamRef(Semantics.POSITION);
+
+ if (b_export_zs) {
+ if (multipoint_impl._attributeStreamIsAllocated(Semantics.Z))
+ zs = (AttributeStreamOfDbl) multipoint_impl.getAttributeStreamRef(Semantics.Z);
+ }
+
+ if (b_export_ms) {
+ if (multipoint_impl._attributeStreamIsAllocated(Semantics.M))
+ ms = (AttributeStreamOfDbl) multipoint_impl.getAttributeStreamRef(Semantics.M);
+ }
+ }
+
+ multiPointTaggedText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, point_count,
+ json_writer);
+ }
+
+ // Mirrors wkt
+ private static void exportPointToGeoJson_(int export_flags, Point point, JsonWriter json_writer) {
+ int precision = 17 - (31 & (export_flags >> 13));
+ boolean bFixedPoint = (GeoJsonExportFlags.geoJsonExportPrecisionFixedPoint & export_flags) != 0;
+ boolean b_export_zs = point.hasAttribute(VertexDescription.Semantics.Z)
+ && (export_flags & GeoJsonExportFlags.geoJsonExportStripZs) == 0;
+ boolean b_export_ms = point.hasAttribute(VertexDescription.Semantics.M)
+ && (export_flags & GeoJsonExportFlags.geoJsonExportStripMs) == 0;
+
+ if (!b_export_zs && b_export_ms)
+ throw new IllegalArgumentException("invalid argument");
+
+ double x = NumberUtils.NaN();
+ double y = NumberUtils.NaN();
+ double z = NumberUtils.NaN();
+ double m = NumberUtils.NaN();
+
+ if (!point.isEmpty()) {
+ x = point.getX();
+ y = point.getY();
+
+ if (b_export_zs)
+ z = point.getZ();
+
+ if (b_export_ms)
+ m = point.getM();
+ }
+
+ if ((export_flags & GeoJsonExportFlags.geoJsonExportPreferMultiGeometry) == 0)
+ pointTaggedText_(precision, bFixedPoint, b_export_zs, b_export_ms, x, y, z, m, json_writer);
+ else
+ multiPointTaggedTextFromPoint_(precision, bFixedPoint, b_export_zs, b_export_ms, x, y, z, m, json_writer);
+ }
+
+ // Mirrors wkt
+ private static void exportEnvelopeToGeoJson_(int export_flags, Envelope envelope, JsonWriter json_writer) {
+ int precision = 17 - (31 & (export_flags >> 13));
+ boolean bFixedPoint = (GeoJsonExportFlags.geoJsonExportPrecisionFixedPoint & export_flags) != 0;
+ boolean b_export_zs = envelope.hasAttribute(VertexDescription.Semantics.Z)
+ && (export_flags & GeoJsonExportFlags.geoJsonExportStripZs) == 0;
+ boolean b_export_ms = envelope.hasAttribute(VertexDescription.Semantics.M)
+ && (export_flags & GeoJsonExportFlags.geoJsonExportStripMs) == 0;
+
+ if (!b_export_zs && b_export_ms)
+ throw new IllegalArgumentException("invalid argument");
+
+ double xmin = NumberUtils.NaN();
+ double ymin = NumberUtils.NaN();
+ double xmax = NumberUtils.NaN();
+ double ymax = NumberUtils.NaN();
+ double zmin = NumberUtils.NaN();
+ double zmax = NumberUtils.NaN();
+ double mmin = NumberUtils.NaN();
+ double mmax = NumberUtils.NaN();
+
+ if (!envelope.isEmpty()) {
+ xmin = envelope.getXMin();
+ ymin = envelope.getYMin();
+ xmax = envelope.getXMax();
+ ymax = envelope.getYMax();
+
+ Envelope1D interval;
+
+ if (b_export_zs) {
+ interval = envelope.queryInterval(Semantics.Z, 0);
+ zmin = interval.vmin;
+ zmax = interval.vmax;
+ }
+
+ if (b_export_ms) {
+ interval = envelope.queryInterval(Semantics.M, 0);
+ mmin = interval.vmin;
+ mmax = interval.vmax;
+ }
+ }
+
+ if ((export_flags & GeoJsonExportFlags.geoJsonExportPreferMultiGeometry) == 0)
+ polygonTaggedTextFromEnvelope_(precision, bFixedPoint, b_export_zs, b_export_ms, xmin, ymin, xmax, ymax,
+ zmin, zmax, mmin, mmax, json_writer);
+ else
+ multiPolygonTaggedTextFromEnvelope_(precision, bFixedPoint, b_export_zs, b_export_ms, xmin, ymin, xmax,
+ ymax, zmin, zmax, mmin, mmax, json_writer);
+ }
+
+ // Mirrors wkt
+ private static void multiPolygonTaggedText_(int precision, boolean bFixedPoint, boolean b_export_zs,
+ boolean b_export_ms, AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position,
+ AttributeStreamOfInt8 path_flags, AttributeStreamOfInt32 paths, int polygon_count, int path_count,
+ JsonWriter json_writer) {
+ json_writer.addFieldName("type");
+ json_writer.addValueString("MultiPolygon");
+
+ json_writer.addFieldName("coordinates");
+
+ if (position == null) {
+ json_writer.startArray();
+ json_writer.endArray();
+ return;
+ }
+
+ json_writer.startArray();
+
+ multiPolygonText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, path_flags, paths,
+ polygon_count, path_count, json_writer);
+
+ json_writer.endArray();
+ }
+
+ // Mirrors wkt
+ private static void multiPolygonTaggedTextFromEnvelope_(int precision, boolean bFixedPoint, boolean b_export_zs,
+ boolean b_export_ms, double xmin, double ymin, double xmax, double ymax, double zmin, double zmax,
+ double mmin, double mmax, JsonWriter json_writer) {
+ json_writer.addFieldName("type");
+ json_writer.addValueString("MultiPolygon");
+
+ json_writer.addFieldName("coordinates");
+
+ if (NumberUtils.isNaN(xmin)) {
+ json_writer.startArray();
+ json_writer.endArray();
+ return;
+ }
+
+ json_writer.startArray();
+
+ writeEnvelopeAsGeoJsonPolygon_(precision, bFixedPoint, b_export_zs, b_export_ms, xmin, ymin, xmax, ymax, zmin,
+ zmax, mmin, mmax, json_writer);
+
+ json_writer.endArray();
+ }
+
+ // Mirrors wkt
+ private static void multiLineStringTaggedText_(int precision, boolean bFixedPoint, boolean b_export_zs,
+ boolean b_export_ms, AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position,
+ AttributeStreamOfInt8 path_flags, AttributeStreamOfInt32 paths, int path_count, JsonWriter json_writer) {
+ json_writer.addFieldName("type");
+ json_writer.addValueString("MultiLineString");
+
+ json_writer.addFieldName("coordinates");
+
+ if (position == null) {
+ json_writer.startArray();
+ json_writer.endArray();
+ return;
+ }
+
+ json_writer.startArray();
+
+ multiLineStringText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, path_flags, paths,
+ path_count, json_writer);
+
+ json_writer.endArray();
+ }
+
+ // Mirrors wkt
+ private static void multiPointTaggedText_(int precision, boolean bFixedPoint, boolean b_export_zs,
+ boolean b_export_ms, AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position,
+ int point_count, JsonWriter json_writer) {
+ json_writer.addFieldName("type");
+ json_writer.addValueString("MultiPoint");
+
+ json_writer.addFieldName("coordinates");
+
+ if (position == null) {
+ json_writer.startArray();
+ json_writer.endArray();
+ return;
+ }
+
+ lineStringText_(false, false, precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, 0,
+ point_count, json_writer);
+ }
+
+ // Mirrors wkt
+ private static void multiPointTaggedTextFromPoint_(int precision, boolean bFixedPoint, boolean b_export_zs,
+ boolean b_export_ms, double x, double y, double z, double m, JsonWriter json_writer) {
+ json_writer.addFieldName("type");
+ json_writer.addValueString("MultiPoint");
+
+ json_writer.addFieldName("coordinates");
+
+ if (NumberUtils.isNaN(x)) {
+ json_writer.startArray();
+ json_writer.endArray();
+ return;
+ }
+
+ json_writer.startArray();
- static String exportSpatialReference(int export_flags, SpatialReference spatial_reference) {
- if (spatial_reference == null || (export_flags & GeoJsonExportFlags.geoJsonExportSkipCRS) != 0)
- throw new IllegalArgumentException("");
+ pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, x, y, z, m, json_writer);
- JsonWriter json_writer = new JsonStringWriter();
- exportSpatialReference(export_flags, spatial_reference, json_writer);
+ json_writer.endArray();
+ }
- return (String) json_writer.getJson();
- }
-
- private static void exportGeometryToGeoJson_(int export_flags, Geometry geometry, JsonWriter json_writer) {
- int type = geometry.getType().value();
- switch (type) {
- case Geometry.GeometryType.Polygon:
- exportPolygonToGeoJson_(export_flags, (Polygon) geometry, json_writer);
- return;
-
- case Geometry.GeometryType.Polyline:
- exportPolylineToGeoJson_(export_flags, (Polyline) geometry, json_writer);
- return;
-
- case Geometry.GeometryType.MultiPoint:
- exportMultiPointToGeoJson_(export_flags, (MultiPoint) geometry, json_writer);
- return;
-
- case Geometry.GeometryType.Point:
- exportPointToGeoJson_(export_flags, (Point) geometry, json_writer);
- return;
-
- case Geometry.GeometryType.Envelope:
- exportEnvelopeToGeoJson_(export_flags, (Envelope) geometry,
- json_writer);
- return;
-
- default:
- throw new RuntimeException("not implemented for this geometry type");
- }
- }
-
- private static void exportSpatialReference(int export_flags, SpatialReference spatial_reference,
- JsonWriter json_writer) {
- if (spatial_reference != null) {
- int wkid = spatial_reference.getLatestID();
-
- if (wkid <= 0)
- throw new GeometryException("invalid call");
-
- json_writer.startObject();
-
- json_writer.addFieldName("type");
-
- json_writer.addValueString("name");
-
- json_writer.addFieldName("properties");
- json_writer.startObject();
-
- json_writer.addFieldName("name");
-
- String authority = ((SpatialReferenceImpl) spatial_reference).getAuthority();
- authority = authority.toUpperCase();
- StringBuilder crs_identifier = new StringBuilder(authority);
- crs_identifier.append(':');
- crs_identifier.append(wkid);
- json_writer.addValueString(crs_identifier.toString());
-
- json_writer.endObject();
-
- json_writer.endObject();
- } else {
- json_writer.addValueNull();
- }
- }
-
- // Mirrors wkt
- private static void exportPolygonToGeoJson_(int export_flags, Polygon polygon, JsonWriter json_writer) {
- MultiPathImpl polygon_impl = (MultiPathImpl) (polygon._getImpl());
-
- if ((export_flags & GeoJsonExportFlags.geoJsonExportFailIfNotSimple) != 0) {
- int simple = polygon_impl.getIsSimple(0.0);
-
- if (simple != MultiPathImpl.GeometryXSimple.Strong)
- throw new GeometryException("corrupted geometry");
- }
-
- int point_count = polygon.getPointCount();
- int polygon_count = polygon_impl.getOGCPolygonCount();
-
- if (point_count > 0 && polygon_count == 0)
- throw new GeometryException("corrupted geometry");
-
- int precision = 17 - (31 & (export_flags >> 13));
- boolean bFixedPoint = (GeoJsonExportFlags.geoJsonExportPrecisionFixedPoint & export_flags) != 0;
- boolean b_export_zs = polygon_impl.hasAttribute(VertexDescription.Semantics.Z)
- && (export_flags & GeoJsonExportFlags.geoJsonExportStripZs) == 0;
- boolean b_export_ms = polygon_impl.hasAttribute(VertexDescription.Semantics.M)
- && (export_flags & GeoJsonExportFlags.geoJsonExportStripMs) == 0;
-
- if (!b_export_zs && b_export_ms)
- throw new IllegalArgumentException("invalid argument");
-
- int path_count = 0;
- AttributeStreamOfDbl position = null;
- AttributeStreamOfDbl zs = null;
- AttributeStreamOfDbl ms = null;
- AttributeStreamOfInt8 path_flags = null;
- AttributeStreamOfInt32 paths = null;
-
- if (point_count > 0) {
- position = (AttributeStreamOfDbl) polygon_impl.getAttributeStreamRef(Semantics.POSITION);
- path_flags = polygon_impl.getPathFlagsStreamRef();
- paths = polygon_impl.getPathStreamRef();
- path_count = polygon_impl.getPathCount();
-
- if (b_export_zs) {
- if (polygon_impl._attributeStreamIsAllocated(Semantics.Z))
- zs = (AttributeStreamOfDbl) polygon_impl.getAttributeStreamRef(Semantics.Z);
- }
-
- if (b_export_ms) {
- if (polygon_impl._attributeStreamIsAllocated(Semantics.M))
- ms = (AttributeStreamOfDbl) polygon_impl.getAttributeStreamRef(Semantics.M);
- }
- }
-
- if ((export_flags & GeoJsonExportFlags.geoJsonExportPreferMultiGeometry) == 0 && polygon_count <= 1)
- polygonTaggedText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, paths, path_count,
- json_writer);
- else
- multiPolygonTaggedText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, path_flags,
- paths, polygon_count, path_count, json_writer);
- }
-
- // Mirrors wkt
- private static void exportPolylineToGeoJson_(int export_flags, Polyline polyline, JsonWriter json_writer) {
- MultiPathImpl polyline_impl = (MultiPathImpl) polyline._getImpl();
-
- int point_count = polyline_impl.getPointCount();
- int path_count = polyline_impl.getPathCount();
-
- if (point_count > 0 && path_count == 0)
- throw new GeometryException("corrupted geometry");
-
- int precision = 17 - (31 & (export_flags >> 13));
- boolean bFixedPoint = (GeoJsonExportFlags.geoJsonExportPrecisionFixedPoint & export_flags) != 0;
- boolean b_export_zs = polyline_impl.hasAttribute(VertexDescription.Semantics.Z)
- && (export_flags & GeoJsonExportFlags.geoJsonExportStripZs) == 0;
- boolean b_export_ms = polyline_impl.hasAttribute(VertexDescription.Semantics.M)
- && (export_flags & GeoJsonExportFlags.geoJsonExportStripMs) == 0;
-
- if (!b_export_zs && b_export_ms)
- throw new IllegalArgumentException("invalid argument");
-
- AttributeStreamOfDbl position = null;
- AttributeStreamOfDbl zs = null;
- AttributeStreamOfDbl ms = null;
- AttributeStreamOfInt8 path_flags = null;
- AttributeStreamOfInt32 paths = null;
-
- if (point_count > 0) {
- position = (AttributeStreamOfDbl) polyline_impl.getAttributeStreamRef(Semantics.POSITION);
- path_flags = polyline_impl.getPathFlagsStreamRef();
- paths = polyline_impl.getPathStreamRef();
-
- if (b_export_zs) {
- if (polyline_impl._attributeStreamIsAllocated(Semantics.Z))
- zs = (AttributeStreamOfDbl) polyline_impl.getAttributeStreamRef(Semantics.Z);
- }
-
- if (b_export_ms) {
- if (polyline_impl._attributeStreamIsAllocated(Semantics.M))
- ms = (AttributeStreamOfDbl) polyline_impl.getAttributeStreamRef(Semantics.M);
- }
- }
-
- if ((export_flags & GeoJsonExportFlags.geoJsonExportPreferMultiGeometry) == 0 && path_count <= 1)
- lineStringTaggedText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, path_flags, paths,
- json_writer);
- else
- multiLineStringTaggedText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, path_flags,
- paths, path_count, json_writer);
- }
-
- // Mirrors wkt
- private static void exportMultiPointToGeoJson_(int export_flags, MultiPoint multipoint, JsonWriter json_writer) {
- MultiPointImpl multipoint_impl = (MultiPointImpl) multipoint._getImpl();
-
- int point_count = multipoint_impl.getPointCount();
-
- int precision = 17 - (31 & (export_flags >> 13));
- boolean bFixedPoint = (GeoJsonExportFlags.geoJsonExportPrecisionFixedPoint & export_flags) != 0;
- boolean b_export_zs = multipoint_impl.hasAttribute(VertexDescription.Semantics.Z)
- && (export_flags & GeoJsonExportFlags.geoJsonExportStripZs) == 0;
- boolean b_export_ms = multipoint_impl.hasAttribute(VertexDescription.Semantics.M)
- && (export_flags & GeoJsonExportFlags.geoJsonExportStripMs) == 0;
-
- if (!b_export_zs && b_export_ms)
- throw new IllegalArgumentException("invalid argument");
-
- AttributeStreamOfDbl position = null;
- AttributeStreamOfDbl zs = null;
- AttributeStreamOfDbl ms = null;
-
- if (point_count > 0) {
- position = (AttributeStreamOfDbl) multipoint_impl.getAttributeStreamRef(Semantics.POSITION);
-
- if (b_export_zs) {
- if (multipoint_impl._attributeStreamIsAllocated(Semantics.Z))
- zs = (AttributeStreamOfDbl) multipoint_impl.getAttributeStreamRef(Semantics.Z);
- }
-
- if (b_export_ms) {
- if (multipoint_impl._attributeStreamIsAllocated(Semantics.M))
- ms = (AttributeStreamOfDbl) multipoint_impl.getAttributeStreamRef(Semantics.M);
- }
- }
-
- multiPointTaggedText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, point_count,
- json_writer);
- }
-
- // Mirrors wkt
- private static void exportPointToGeoJson_(int export_flags, Point point, JsonWriter json_writer) {
- int precision = 17 - (31 & (export_flags >> 13));
- boolean bFixedPoint = (GeoJsonExportFlags.geoJsonExportPrecisionFixedPoint & export_flags) != 0;
- boolean b_export_zs = point.hasAttribute(VertexDescription.Semantics.Z)
- && (export_flags & GeoJsonExportFlags.geoJsonExportStripZs) == 0;
- boolean b_export_ms = point.hasAttribute(VertexDescription.Semantics.M)
- && (export_flags & GeoJsonExportFlags.geoJsonExportStripMs) == 0;
-
- if (!b_export_zs && b_export_ms)
- throw new IllegalArgumentException("invalid argument");
-
- double x = NumberUtils.NaN();
- double y = NumberUtils.NaN();
- double z = NumberUtils.NaN();
- double m = NumberUtils.NaN();
-
- if (!point.isEmpty()) {
- x = point.getX();
- y = point.getY();
-
- if (b_export_zs)
- z = point.getZ();
-
- if (b_export_ms)
- m = point.getM();
- }
-
- if ((export_flags & GeoJsonExportFlags.geoJsonExportPreferMultiGeometry) == 0)
- pointTaggedText_(precision, bFixedPoint, b_export_zs, b_export_ms, x, y, z, m, json_writer);
- else
- multiPointTaggedTextFromPoint_(precision, bFixedPoint, b_export_zs, b_export_ms, x, y, z, m, json_writer);
- }
-
- // Mirrors wkt
- private static void exportEnvelopeToGeoJson_(int export_flags, Envelope envelope, JsonWriter json_writer) {
- int precision = 17 - (31 & (export_flags >> 13));
- boolean bFixedPoint = (GeoJsonExportFlags.geoJsonExportPrecisionFixedPoint & export_flags) != 0;
- boolean b_export_zs = envelope.hasAttribute(VertexDescription.Semantics.Z)
- && (export_flags & GeoJsonExportFlags.geoJsonExportStripZs) == 0;
- boolean b_export_ms = envelope.hasAttribute(VertexDescription.Semantics.M)
- && (export_flags & GeoJsonExportFlags.geoJsonExportStripMs) == 0;
-
- if (!b_export_zs && b_export_ms)
- throw new IllegalArgumentException("invalid argument");
-
- double xmin = NumberUtils.NaN();
- double ymin = NumberUtils.NaN();
- double xmax = NumberUtils.NaN();
- double ymax = NumberUtils.NaN();
- double zmin = NumberUtils.NaN();
- double zmax = NumberUtils.NaN();
- double mmin = NumberUtils.NaN();
- double mmax = NumberUtils.NaN();
-
- if (!envelope.isEmpty()) {
- xmin = envelope.getXMin();
- ymin = envelope.getYMin();
- xmax = envelope.getXMax();
- ymax = envelope.getYMax();
-
- Envelope1D interval;
-
- if (b_export_zs) {
- interval = envelope.queryInterval(Semantics.Z, 0);
- zmin = interval.vmin;
- zmax = interval.vmax;
- }
-
- if (b_export_ms) {
- interval = envelope.queryInterval(Semantics.M, 0);
- mmin = interval.vmin;
- mmax = interval.vmax;
- }
- }
-
- if ((export_flags & GeoJsonExportFlags.geoJsonExportPreferMultiGeometry) == 0)
- polygonTaggedTextFromEnvelope_(precision, bFixedPoint, b_export_zs, b_export_ms, xmin, ymin, xmax, ymax,
- zmin, zmax, mmin, mmax, json_writer);
- else
- multiPolygonTaggedTextFromEnvelope_(precision, bFixedPoint, b_export_zs, b_export_ms, xmin, ymin, xmax,
- ymax, zmin, zmax, mmin, mmax, json_writer);
- }
-
- // Mirrors wkt
- private static void multiPolygonTaggedText_(int precision, boolean bFixedPoint, boolean b_export_zs,
- boolean b_export_ms, AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position,
- AttributeStreamOfInt8 path_flags, AttributeStreamOfInt32 paths, int polygon_count, int path_count,
- JsonWriter json_writer) {
- json_writer.addFieldName("type");
- json_writer.addValueString("MultiPolygon");
-
- json_writer.addFieldName("coordinates");
-
- if (position == null) {
- json_writer.startArray();
- json_writer.endArray();
- return;
- }
-
- json_writer.startArray();
-
- multiPolygonText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, path_flags, paths,
- polygon_count, path_count, json_writer);
-
- json_writer.endArray();
- }
-
- // Mirrors wkt
- private static void multiPolygonTaggedTextFromEnvelope_(int precision, boolean bFixedPoint, boolean b_export_zs,
- boolean b_export_ms, double xmin, double ymin, double xmax, double ymax, double zmin, double zmax,
- double mmin, double mmax, JsonWriter json_writer) {
- json_writer.addFieldName("type");
- json_writer.addValueString("MultiPolygon");
-
- json_writer.addFieldName("coordinates");
-
- if (NumberUtils.isNaN(xmin)) {
- json_writer.startArray();
- json_writer.endArray();
- return;
- }
-
- json_writer.startArray();
-
- writeEnvelopeAsGeoJsonPolygon_(precision, bFixedPoint, b_export_zs, b_export_ms, xmin, ymin, xmax, ymax, zmin,
- zmax, mmin, mmax, json_writer);
-
- json_writer.endArray();
- }
-
- // Mirrors wkt
- private static void multiLineStringTaggedText_(int precision, boolean bFixedPoint, boolean b_export_zs,
- boolean b_export_ms, AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position,
- AttributeStreamOfInt8 path_flags, AttributeStreamOfInt32 paths, int path_count, JsonWriter json_writer) {
- json_writer.addFieldName("type");
- json_writer.addValueString("MultiLineString");
-
- json_writer.addFieldName("coordinates");
-
- if (position == null) {
- json_writer.startArray();
- json_writer.endArray();
- return;
- }
-
- json_writer.startArray();
-
- multiLineStringText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, path_flags, paths,
- path_count, json_writer);
-
- json_writer.endArray();
- }
-
- // Mirrors wkt
- private static void multiPointTaggedText_(int precision, boolean bFixedPoint, boolean b_export_zs,
- boolean b_export_ms, AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position,
- int point_count, JsonWriter json_writer) {
- json_writer.addFieldName("type");
- json_writer.addValueString("MultiPoint");
-
- json_writer.addFieldName("coordinates");
-
- if (position == null) {
- json_writer.startArray();
- json_writer.endArray();
- return;
- }
-
- lineStringText_(false, false, precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, 0,
- point_count, json_writer);
- }
-
- // Mirrors wkt
- private static void multiPointTaggedTextFromPoint_(int precision, boolean bFixedPoint, boolean b_export_zs,
- boolean b_export_ms, double x, double y, double z, double m, JsonWriter json_writer) {
- json_writer.addFieldName("type");
- json_writer.addValueString("MultiPoint");
-
- json_writer.addFieldName("coordinates");
-
- if (NumberUtils.isNaN(x)) {
- json_writer.startArray();
- json_writer.endArray();
- return;
- }
-
- json_writer.startArray();
+ // Mirrors wkt
+ private static void polygonTaggedText_(int precision, boolean bFixedPoint, boolean b_export_zs, boolean b_export_ms,
+ AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position,
+ AttributeStreamOfInt32 paths, int path_count, JsonWriter json_writer) {
+ json_writer.addFieldName("type");
+ json_writer.addValueString("Polygon");
+
+ json_writer.addFieldName("coordinates");
+
+ if (position == null) {
+ json_writer.startArray();
+ json_writer.endArray();
+ return;
+ }
+
+ polygonText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, paths, 0, path_count,
+ json_writer);
+ }
+
+ // Mirrors wkt
+ private static void polygonTaggedTextFromEnvelope_(int precision, boolean bFixedPoint, boolean b_export_zs,
+ boolean b_export_ms, double xmin, double ymin, double xmax, double ymax, double zmin, double zmax,
+ double mmin, double mmax, JsonWriter json_writer) {
+ json_writer.addFieldName("type");
+ json_writer.addValueString("Polygon");
+
+ json_writer.addFieldName("coordinates");
+
+ if (NumberUtils.isNaN(xmin)) {
+ json_writer.startArray();
+ json_writer.endArray();
+ return;
+ }
+
+ writeEnvelopeAsGeoJsonPolygon_(precision, bFixedPoint, b_export_zs, b_export_ms, xmin, ymin, xmax, ymax, zmin,
+ zmax, mmin, mmax, json_writer);
+ }
+
+ // Mirrors wkt
+ private static void lineStringTaggedText_(int precision, boolean bFixedPoint, boolean b_export_zs,
+ boolean b_export_ms, AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position,
+ AttributeStreamOfInt8 path_flags, AttributeStreamOfInt32 paths, JsonWriter json_writer) {
+ json_writer.addFieldName("type");
+ json_writer.addValueString("LineString");
+
+ json_writer.addFieldName("coordinates");
+
+ if (position == null) {
+ json_writer.startArray();
+ json_writer.endArray();
+ return;
+ }
+
+ boolean b_closed = ((path_flags.read(0) & PathFlags.enumClosed) != 0);
+
+ lineStringText_(false, b_closed, precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, 0,
+ paths.read(1), json_writer);
+ }
+
+ // Mirrors wkt
+ private static void pointTaggedText_(int precision, boolean bFixedPoint, boolean b_export_zs, boolean b_export_ms,
+ double x, double y, double z, double m, JsonWriter json_writer) {
+ json_writer.addFieldName("type");
+ json_writer.addValueString("Point");
+
+ json_writer.addFieldName("coordinates");
+
+ if (NumberUtils.isNaN(x)) {
+ json_writer.startArray();
+ json_writer.endArray();
+
+ return;
+ }
+
+ pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, x, y, z, m, json_writer);
+ }
+
+ // Mirrors wkt
+ private static void multiPolygonText_(int precision, boolean bFixedPoint, boolean b_export_zs, boolean b_export_ms,
+ AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position,
+ AttributeStreamOfInt8 path_flags, AttributeStreamOfInt32 paths, int polygon_count, int path_count,
+ JsonWriter json_writer) {
+ int polygon_start = 0;
+ int polygon_end = 1;
+
+ while (polygon_end < path_count && ((int) path_flags.read(polygon_end) & PathFlags.enumOGCStartPolygon) == 0)
+ polygon_end++;
+
+ polygonText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, paths, polygon_start,
+ polygon_end, json_writer);
+
+ for (int ipolygon = 1; ipolygon < polygon_count; ipolygon++) {
+ polygon_start = polygon_end;
+ polygon_end++;
+
+ while (polygon_end < path_count
+ && ((int) path_flags.read(polygon_end) & PathFlags.enumOGCStartPolygon) == 0)
+ polygon_end++;
+
+ polygonText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, paths, polygon_start,
+ polygon_end, json_writer);
+ }
+ }
+
+ // Mirrors wkt
+ private static void multiLineStringText_(int precision, boolean bFixedPoint, boolean b_export_zs,
+ boolean b_export_ms, AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position,
+ AttributeStreamOfInt8 path_flags, AttributeStreamOfInt32 paths, int path_count, JsonWriter json_writer) {
+ boolean b_closed = ((path_flags.read(0) & PathFlags.enumClosed) != 0);
+
+ lineStringText_(false, b_closed, precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, 0,
+ paths.read(1), json_writer);
+
+ for (int path = 1; path < path_count; path++) {
+ b_closed = ((path_flags.read(path) & PathFlags.enumClosed) != 0);
+
+ int istart = paths.read(path);
+ int iend = paths.read(path + 1);
+ lineStringText_(false, b_closed, precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, istart,
+ iend, json_writer);
+ }
+ }
+
+ // Mirrors wkt
+ private static void polygonText_(int precision, boolean bFixedPoint, boolean b_export_zs, boolean b_export_ms,
+ AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position,
+ AttributeStreamOfInt32 paths, int polygon_start, int polygon_end, JsonWriter json_writer) {
+ json_writer.startArray();
+
+ int istart = paths.read(polygon_start);
+ int iend = paths.read(polygon_start + 1);
+ lineStringText_(true, true, precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, istart, iend,
+ json_writer);
- pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, x, y, z, m, json_writer);
+ for (int path = polygon_start + 1; path < polygon_end; path++) {
+ istart = paths.read(path);
+ iend = paths.read(path + 1);
+ lineStringText_(true, true, precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, istart,
+ iend, json_writer);
+ }
- json_writer.endArray();
- }
+ json_writer.endArray();
+ }
- // Mirrors wkt
- private static void polygonTaggedText_(int precision, boolean bFixedPoint, boolean b_export_zs, boolean b_export_ms,
- AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position,
- AttributeStreamOfInt32 paths, int path_count, JsonWriter json_writer) {
- json_writer.addFieldName("type");
- json_writer.addValueString("Polygon");
-
- json_writer.addFieldName("coordinates");
-
- if (position == null) {
- json_writer.startArray();
- json_writer.endArray();
- return;
- }
-
- polygonText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, paths, 0, path_count,
- json_writer);
- }
-
- // Mirrors wkt
- private static void polygonTaggedTextFromEnvelope_(int precision, boolean bFixedPoint, boolean b_export_zs,
- boolean b_export_ms, double xmin, double ymin, double xmax, double ymax, double zmin, double zmax,
- double mmin, double mmax, JsonWriter json_writer) {
- json_writer.addFieldName("type");
- json_writer.addValueString("Polygon");
-
- json_writer.addFieldName("coordinates");
-
- if (NumberUtils.isNaN(xmin)) {
- json_writer.startArray();
- json_writer.endArray();
- return;
- }
-
- writeEnvelopeAsGeoJsonPolygon_(precision, bFixedPoint, b_export_zs, b_export_ms, xmin, ymin, xmax, ymax, zmin,
- zmax, mmin, mmax, json_writer);
- }
-
- // Mirrors wkt
- private static void lineStringTaggedText_(int precision, boolean bFixedPoint, boolean b_export_zs,
- boolean b_export_ms, AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position,
- AttributeStreamOfInt8 path_flags, AttributeStreamOfInt32 paths, JsonWriter json_writer) {
- json_writer.addFieldName("type");
- json_writer.addValueString("LineString");
-
- json_writer.addFieldName("coordinates");
-
- if (position == null) {
- json_writer.startArray();
- json_writer.endArray();
- return;
- }
-
- boolean b_closed = ((path_flags.read(0) & PathFlags.enumClosed) != 0);
-
- lineStringText_(false, b_closed, precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, 0,
- paths.read(1), json_writer);
- }
-
- // Mirrors wkt
- private static void pointTaggedText_(int precision, boolean bFixedPoint, boolean b_export_zs, boolean b_export_ms,
- double x, double y, double z, double m, JsonWriter json_writer) {
- json_writer.addFieldName("type");
- json_writer.addValueString("Point");
-
- json_writer.addFieldName("coordinates");
-
- if (NumberUtils.isNaN(x)) {
- json_writer.startArray();
- json_writer.endArray();
-
- return;
- }
-
- pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, x, y, z, m, json_writer);
- }
-
- // Mirrors wkt
- private static void multiPolygonText_(int precision, boolean bFixedPoint, boolean b_export_zs, boolean b_export_ms,
- AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position,
- AttributeStreamOfInt8 path_flags, AttributeStreamOfInt32 paths, int polygon_count, int path_count,
- JsonWriter json_writer) {
- int polygon_start = 0;
- int polygon_end = 1;
-
- while (polygon_end < path_count && ((int) path_flags.read(polygon_end) & PathFlags.enumOGCStartPolygon) == 0)
- polygon_end++;
-
- polygonText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, paths, polygon_start,
- polygon_end, json_writer);
-
- for (int ipolygon = 1; ipolygon < polygon_count; ipolygon++) {
- polygon_start = polygon_end;
- polygon_end++;
-
- while (polygon_end < path_count
- && ((int) path_flags.read(polygon_end) & PathFlags.enumOGCStartPolygon) == 0)
- polygon_end++;
-
- polygonText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, paths, polygon_start,
- polygon_end, json_writer);
- }
- }
-
- // Mirrors wkt
- private static void multiLineStringText_(int precision, boolean bFixedPoint, boolean b_export_zs,
- boolean b_export_ms, AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position,
- AttributeStreamOfInt8 path_flags, AttributeStreamOfInt32 paths, int path_count, JsonWriter json_writer) {
- boolean b_closed = ((path_flags.read(0) & PathFlags.enumClosed) != 0);
-
- lineStringText_(false, b_closed, precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, 0,
- paths.read(1), json_writer);
-
- for (int path = 1; path < path_count; path++) {
- b_closed = ((path_flags.read(path) & PathFlags.enumClosed) != 0);
-
- int istart = paths.read(path);
- int iend = paths.read(path + 1);
- lineStringText_(false, b_closed, precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, istart,
- iend, json_writer);
- }
- }
-
- // Mirrors wkt
- private static void polygonText_(int precision, boolean bFixedPoint, boolean b_export_zs, boolean b_export_ms,
- AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position,
- AttributeStreamOfInt32 paths, int polygon_start, int polygon_end, JsonWriter json_writer) {
- json_writer.startArray();
-
- int istart = paths.read(polygon_start);
- int iend = paths.read(polygon_start + 1);
- lineStringText_(true, true, precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, istart, iend,
- json_writer);
+ // Mirrors wkt
+ private static void lineStringText_(boolean bRing, boolean b_closed, int precision, boolean bFixedPoint,
+ boolean b_export_zs, boolean b_export_ms, AttributeStreamOfDbl zs, AttributeStreamOfDbl ms,
+ AttributeStreamOfDbl position, int istart, int iend, JsonWriter json_writer) {
+ if (istart == iend) {
+ json_writer.startArray();
+ json_writer.endArray();
+ return;
+ }
- for (int path = polygon_start + 1; path < polygon_end; path++) {
- istart = paths.read(path);
- iend = paths.read(path + 1);
- lineStringText_(true, true, precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, istart,
- iend, json_writer);
- }
+ json_writer.startArray();
- json_writer.endArray();
- }
+ if (bRing) {
+ pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, istart, json_writer);
- // Mirrors wkt
- private static void lineStringText_(boolean bRing, boolean b_closed, int precision, boolean bFixedPoint,
- boolean b_export_zs, boolean b_export_ms, AttributeStreamOfDbl zs, AttributeStreamOfDbl ms,
- AttributeStreamOfDbl position, int istart, int iend, JsonWriter json_writer) {
- if (istart == iend) {
- json_writer.startArray();
- json_writer.endArray();
- return;
- }
+ for (int point = iend - 1; point >= istart + 1; point--)
+ pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, point, json_writer);
- json_writer.startArray();
+ pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, istart, json_writer);
+ } else {
+ for (int point = istart; point < iend - 1; point++)
+ pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, point, json_writer);
- if (bRing) {
- pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, istart, json_writer);
+ pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, iend - 1, json_writer);
- for (int point = iend - 1; point >= istart + 1; point--)
- pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, point, json_writer);
+ if (b_closed)
+ pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, istart, json_writer);
+ }
- pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, istart, json_writer);
- } else {
- for (int point = istart; point < iend - 1; point++)
- pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, point, json_writer);
+ json_writer.endArray();
+ }
- pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, iend - 1, json_writer);
+ // Mirrors wkt
+ private static int pointText_(int precision, boolean bFixedPoint, boolean b_export_zs, boolean b_export_ms,
+ double x, double y, double z, double m, JsonWriter json_writer) {
- if (b_closed)
- pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, zs, ms, position, istart, json_writer);
- }
+ json_writer.startArray();
- json_writer.endArray();
- }
+ json_writer.addValueDouble(x, precision, bFixedPoint);
+ json_writer.addValueDouble(y, precision, bFixedPoint);
- // Mirrors wkt
- private static int pointText_(int precision, boolean bFixedPoint, boolean b_export_zs, boolean b_export_ms,
- double x, double y, double z, double m, JsonWriter json_writer) {
+ if (b_export_zs)
+ json_writer.addValueDouble(z, precision, bFixedPoint);
- json_writer.startArray();
+ if (b_export_ms)
+ json_writer.addValueDouble(m, precision, bFixedPoint);
- json_writer.addValueDouble(x, precision, bFixedPoint);
- json_writer.addValueDouble(y, precision, bFixedPoint);
+ json_writer.endArray();
- if (b_export_zs)
- json_writer.addValueDouble(z, precision, bFixedPoint);
+ return 1;
+ }
- if (b_export_ms)
- json_writer.addValueDouble(m, precision, bFixedPoint);
+ // Mirrors wkt
+ private static void pointText_(int precision, boolean bFixedPoint, boolean b_export_zs, boolean b_export_ms,
+ AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position, int point,
+ JsonWriter json_writer) {
+ double x = position.readAsDbl(2 * point);
+ double y = position.readAsDbl(2 * point + 1);
+ double z = NumberUtils.NaN();
+ double m = NumberUtils.NaN();
- json_writer.endArray();
+ if (b_export_zs)
+ z = (zs != null ? zs.readAsDbl(point) : VertexDescription.getDefaultValue(Semantics.Z));
- return 1;
- }
+ if (b_export_ms)
+ m = (ms != null ? ms.readAsDbl(point) : VertexDescription.getDefaultValue(Semantics.M));
- // Mirrors wkt
- private static void pointText_(int precision, boolean bFixedPoint, boolean b_export_zs, boolean b_export_ms,
- AttributeStreamOfDbl zs, AttributeStreamOfDbl ms, AttributeStreamOfDbl position, int point,
- JsonWriter json_writer) {
- double x = position.readAsDbl(2 * point);
- double y = position.readAsDbl(2 * point + 1);
- double z = NumberUtils.NaN();
- double m = NumberUtils.NaN();
+ pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, x, y, z, m, json_writer);
+ }
- if (b_export_zs)
- z = (zs != null ? zs.readAsDbl(point) : VertexDescription.getDefaultValue(Semantics.Z));
+ // Mirrors wkt
+ private static void writeEnvelopeAsGeoJsonPolygon_(int precision, boolean bFixedPoint, boolean b_export_zs,
+ boolean b_export_ms, double xmin, double ymin, double xmax, double ymax, double zmin, double zmax,
+ double mmin, double mmax, JsonWriter json_writer) {
+ json_writer.startArray();
+ json_writer.startArray();
- if (b_export_ms)
- m = (ms != null ? ms.readAsDbl(point) : VertexDescription.getDefaultValue(Semantics.M));
+ json_writer.startArray();
+ json_writer.addValueDouble(xmin, precision, bFixedPoint);
+ json_writer.addValueDouble(ymin, precision, bFixedPoint);
- pointText_(precision, bFixedPoint, b_export_zs, b_export_ms, x, y, z, m, json_writer);
- }
+ if (b_export_zs)
+ json_writer.addValueDouble(zmin, precision, bFixedPoint);
- // Mirrors wkt
- private static void writeEnvelopeAsGeoJsonPolygon_(int precision, boolean bFixedPoint, boolean b_export_zs,
- boolean b_export_ms, double xmin, double ymin, double xmax, double ymax, double zmin, double zmax,
- double mmin, double mmax, JsonWriter json_writer) {
- json_writer.startArray();
- json_writer.startArray();
+ if (b_export_ms)
+ json_writer.addValueDouble(mmin, precision, bFixedPoint);
- json_writer.startArray();
- json_writer.addValueDouble(xmin, precision, bFixedPoint);
- json_writer.addValueDouble(ymin, precision, bFixedPoint);
+ json_writer.endArray();
- if (b_export_zs)
- json_writer.addValueDouble(zmin, precision, bFixedPoint);
+ json_writer.startArray();
+ json_writer.addValueDouble(xmax, precision, bFixedPoint);
+ json_writer.addValueDouble(ymin, precision, bFixedPoint);
- if (b_export_ms)
- json_writer.addValueDouble(mmin, precision, bFixedPoint);
+ if (b_export_zs)
+ json_writer.addValueDouble(zmax, precision, bFixedPoint);
- json_writer.endArray();
+ if (b_export_ms)
+ json_writer.addValueDouble(mmax, precision, bFixedPoint);
- json_writer.startArray();
- json_writer.addValueDouble(xmax, precision, bFixedPoint);
- json_writer.addValueDouble(ymin, precision, bFixedPoint);
+ json_writer.endArray();
- if (b_export_zs)
- json_writer.addValueDouble(zmax, precision, bFixedPoint);
+ json_writer.startArray();
+ json_writer.addValueDouble(xmax, precision, bFixedPoint);
+ json_writer.addValueDouble(ymax, precision, bFixedPoint);
- if (b_export_ms)
- json_writer.addValueDouble(mmax, precision, bFixedPoint);
+ if (b_export_zs)
+ json_writer.addValueDouble(zmin, precision, bFixedPoint);
- json_writer.endArray();
+ if (b_export_ms)
+ json_writer.addValueDouble(mmin, precision, bFixedPoint);
- json_writer.startArray();
- json_writer.addValueDouble(xmax, precision, bFixedPoint);
- json_writer.addValueDouble(ymax, precision, bFixedPoint);
+ json_writer.endArray();
- if (b_export_zs)
- json_writer.addValueDouble(zmin, precision, bFixedPoint);
+ json_writer.startArray();
+ json_writer.addValueDouble(xmin, precision, bFixedPoint);
+ json_writer.addValueDouble(ymax, precision, bFixedPoint);
- if (b_export_ms)
- json_writer.addValueDouble(mmin, precision, bFixedPoint);
+ if (b_export_zs)
+ json_writer.addValueDouble(zmax, precision, bFixedPoint);
- json_writer.endArray();
+ if (b_export_ms)
+ json_writer.addValueDouble(mmax, precision, bFixedPoint);
- json_writer.startArray();
- json_writer.addValueDouble(xmin, precision, bFixedPoint);
- json_writer.addValueDouble(ymax, precision, bFixedPoint);
+ json_writer.endArray();
- if (b_export_zs)
- json_writer.addValueDouble(zmax, precision, bFixedPoint);
+ json_writer.startArray();
+ json_writer.addValueDouble(xmin, precision, bFixedPoint);
+ json_writer.addValueDouble(ymin, precision, bFixedPoint);
- if (b_export_ms)
- json_writer.addValueDouble(mmax, precision, bFixedPoint);
+ if (b_export_zs)
+ json_writer.addValueDouble(zmin, precision, bFixedPoint);
- json_writer.endArray();
+ if (b_export_ms)
+ json_writer.addValueDouble(mmin, precision, bFixedPoint);
- json_writer.startArray();
- json_writer.addValueDouble(xmin, precision, bFixedPoint);
- json_writer.addValueDouble(ymin, precision, bFixedPoint);
+ json_writer.endArray();
- if (b_export_zs)
- json_writer.addValueDouble(zmin, precision, bFixedPoint);
-
- if (b_export_ms)
- json_writer.addValueDouble(mmin, precision, bFixedPoint);
-
- json_writer.endArray();
-
- json_writer.endArray();
- json_writer.endArray();
- }
+ json_writer.endArray();
+ json_writer.endArray();
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorExportToGeoJsonLocal.java b/src/main/java/com/esri/core/geometry/OperatorExportToGeoJsonLocal.java
index 30bd7ad2..9412cd83 100644
--- a/src/main/java/com/esri/core/geometry/OperatorExportToGeoJsonLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorExportToGeoJsonLocal.java
@@ -23,28 +23,28 @@
package com.esri.core.geometry;
class OperatorExportToGeoJsonLocal extends OperatorExportToGeoJson {
- @Override
- public StringCursor execute(SpatialReference spatialReference, GeometryCursor geometryCursor) {
- return new OperatorExportToGeoJsonCursor(GeoJsonExportFlags.geoJsonExportDefaults, spatialReference, geometryCursor);
- }
-
- @Override
- public String execute(SpatialReference spatialReference, Geometry geometry) {
- return OperatorExportToGeoJsonCursor.exportToGeoJson(GeoJsonExportFlags.geoJsonExportDefaults, geometry, spatialReference);
- }
-
- @Override
- public String execute(int exportFlags, SpatialReference spatialReference, Geometry geometry) {
- return OperatorExportToGeoJsonCursor.exportToGeoJson(exportFlags, geometry, spatialReference);
- }
-
- @Override
- public String execute(Geometry geometry) {
- return OperatorExportToGeoJsonCursor.exportToGeoJson(GeoJsonExportFlags.geoJsonExportSkipCRS, geometry, null);
- }
-
- @Override
- public String exportSpatialReference(int export_flags, SpatialReference spatial_reference) {
- return OperatorExportToGeoJsonCursor.exportSpatialReference(export_flags, spatial_reference);
- }
+ @Override
+ public StringCursor execute(SpatialReference spatialReference, GeometryCursor geometryCursor) {
+ return new OperatorExportToGeoJsonCursor(GeoJsonExportFlags.geoJsonExportDefaults, spatialReference, geometryCursor);
+ }
+
+ @Override
+ public String execute(SpatialReference spatialReference, Geometry geometry) {
+ return OperatorExportToGeoJsonCursor.exportToGeoJson(GeoJsonExportFlags.geoJsonExportDefaults, geometry, spatialReference);
+ }
+
+ @Override
+ public String execute(int exportFlags, SpatialReference spatialReference, Geometry geometry) {
+ return OperatorExportToGeoJsonCursor.exportToGeoJson(exportFlags, geometry, spatialReference);
+ }
+
+ @Override
+ public String execute(Geometry geometry) {
+ return OperatorExportToGeoJsonCursor.exportToGeoJson(GeoJsonExportFlags.geoJsonExportSkipCRS, geometry, null);
+ }
+
+ @Override
+ public String exportSpatialReference(int export_flags, SpatialReference spatial_reference) {
+ return OperatorExportToGeoJsonCursor.exportSpatialReference(export_flags, spatial_reference);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorExportToJson.java b/src/main/java/com/esri/core/geometry/OperatorExportToJson.java
index 63cf5958..2bb814c0 100644
--- a/src/main/java/com/esri/core/geometry/OperatorExportToJson.java
+++ b/src/main/java/com/esri/core/geometry/OperatorExportToJson.java
@@ -32,37 +32,37 @@
*/
public abstract class OperatorExportToJson extends Operator {
- @Override
- public Type getType() {
- return Type.ExportToJson;
- }
+ @Override
+ public Type getType() {
+ return Type.ExportToJson;
+ }
- /**
- * Performs the ExportToJson operation
- *
- * @return Returns a StringCursor.
- */
- public abstract StringCursor execute(SpatialReference spatialReference,
- GeometryCursor geometryCursor);
+ /**
+ * Performs the ExportToJson operation
+ *
+ * @return Returns a StringCursor.
+ */
+ public abstract StringCursor execute(SpatialReference spatialReference,
+ GeometryCursor geometryCursor);
- /**
- * Performs the ExportToJson operation
- *
- * @return Returns a String.
- */
- public abstract String execute(SpatialReference spatialReference,
- Geometry geometry);
+ /**
+ * Performs the ExportToJson operation
+ *
+ * @return Returns a String.
+ */
+ public abstract String execute(SpatialReference spatialReference,
+ Geometry geometry);
- /**
- * Performs the ExportToJson operation
- *
- * @return Returns a String.
- */
- public abstract String execute(SpatialReference spatialReference,
- Geometry geometry, Map
- * Note the behavior is not determined for any geodetic curve segments that connect two poles, or for loxodrome segments that connect to any pole.
- */
- public abstract GeometryCursor execute(
- GeometryCursor geoms,
- SpatialReference sr,
- double maxSegmentLengthMeters,
- int curveType,
- ProgressTracker progressTracker);
+ /**
+ * Densifies input geometries. Attributes are interpolated along the scalar t-values of the input segments obtained from the length ratios along the densified segments.
+ *
+ * @param geoms The geometries to be densified.
+ * @param sr The SpatialReference of the Geometry.
+ * @param maxSegmentLengthMeters The maximum segment length (in meters) allowed. Must be a positive value.
+ * @param curveType The interpretation of a line connecting two points.
+ * @return Returns the densified geometries (It does nothing to geometries with dim less than 1, but simply passes them along).
+ *
+ * Note the behavior is not determined for any geodetic curve segments that connect two poles, or for loxodrome segments that connect to any pole.
+ */
+ public abstract GeometryCursor execute(
+ GeometryCursor geoms,
+ SpatialReference sr,
+ double maxSegmentLengthMeters,
+ int curveType,
+ ProgressTracker progressTracker);
- /**
- * Same as above, but works with a single geometry.
- */
- public abstract Geometry execute(
- Geometry geom,
- SpatialReference sr,
- double maxSegmentLengthMeters,
- int curveType,
- ProgressTracker progressTracker);
+ /**
+ * Same as above, but works with a single geometry.
+ */
+ public abstract Geometry execute(
+ Geometry geom,
+ SpatialReference sr,
+ double maxSegmentLengthMeters,
+ int curveType,
+ ProgressTracker progressTracker);
- public static OperatorGeodeticDensifyByLength local() {
- return (OperatorGeodeticDensifyByLength) OperatorFactoryLocal.getInstance().getOperator(Type.GeodeticDensifyByLength);
- }
+ public static OperatorGeodeticDensifyByLength local() {
+ return (OperatorGeodeticDensifyByLength) OperatorFactoryLocal.getInstance().getOperator(Type.GeodeticDensifyByLength);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorGeodeticDensifyCursor.java b/src/main/java/com/esri/core/geometry/OperatorGeodeticDensifyCursor.java
index b767a1fe..b2eb6a27 100644
--- a/src/main/java/com/esri/core/geometry/OperatorGeodeticDensifyCursor.java
+++ b/src/main/java/com/esri/core/geometry/OperatorGeodeticDensifyCursor.java
@@ -4,29 +4,29 @@
* Created by davidraleigh on 2/21/16.
*/
public class OperatorGeodeticDensifyCursor extends GeometryCursor {
- SpatialReferenceImpl m_spatialReference;
- double m_maxLength;
- Point m_startPoint;
- Point m_endPoint;
- ProgressTracker m_progressTracker;
+ SpatialReferenceImpl m_spatialReference;
+ double m_maxLength;
+ Point m_startPoint;
+ Point m_endPoint;
+ ProgressTracker m_progressTracker;
- public OperatorGeodeticDensifyCursor(GeometryCursor inputGeoms1,
- SpatialReference spatialReference,
- double maxLength,
- ProgressTracker progressTracker) {
- m_inputGeoms = inputGeoms1;
- m_maxLength = maxLength;
- m_spatialReference = (SpatialReferenceImpl) spatialReference;
- m_startPoint = new Point();
- m_endPoint = new Point();
- m_progressTracker = progressTracker;
- }
+ public OperatorGeodeticDensifyCursor(GeometryCursor inputGeoms1,
+ SpatialReference spatialReference,
+ double maxLength,
+ ProgressTracker progressTracker) {
+ m_inputGeoms = inputGeoms1;
+ m_maxLength = maxLength;
+ m_spatialReference = (SpatialReferenceImpl) spatialReference;
+ m_startPoint = new Point();
+ m_endPoint = new Point();
+ m_progressTracker = progressTracker;
+ }
- @Override
- public Geometry next() {
- if (hasNext())
- return GeodesicDensifier.densifyByLength(m_inputGeoms.next(), m_spatialReference, m_maxLength, m_progressTracker);
+ @Override
+ public Geometry next() {
+ if (hasNext())
+ return GeodesicDensifier.densifyByLength(m_inputGeoms.next(), m_spatialReference, m_maxLength, m_progressTracker);
- return null;
- }
+ return null;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorGeodeticDensifyLocal.java b/src/main/java/com/esri/core/geometry/OperatorGeodeticDensifyLocal.java
index da1ff5dd..1518885e 100644
--- a/src/main/java/com/esri/core/geometry/OperatorGeodeticDensifyLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorGeodeticDensifyLocal.java
@@ -27,27 +27,27 @@
//This is a stub
class OperatorGeodeticDensifyLocal extends OperatorGeodeticDensifyByLength {
- @Override
- public GeometryCursor execute(GeometryCursor geoms,
- SpatialReference sr,
- double maxSegmentLengthMeters,
- int curveType,
- ProgressTracker progressTracker) {
- if (maxSegmentLengthMeters <= 0)
- // TODO fix geometry exception to match native implementation
- throw new GeometryException("max segment length must be positive and greater than 0");// GEOMTHROW(invalid_argument);
-
- return new OperatorGeodeticDensifyCursor(geoms, sr, maxSegmentLengthMeters, progressTracker);
- }
-
- @Override
- public Geometry execute(Geometry geom,
- SpatialReference sr,
- double maxSegmentLengthMeters,
- int curveType,
- ProgressTracker progressTracker) {
- SimpleGeometryCursor inputCursor = new SimpleGeometryCursor(geom);
- GeometryCursor outputCursor = execute(inputCursor, sr, maxSegmentLengthMeters, curveType, progressTracker);
- return outputCursor.next();
- }
+ @Override
+ public GeometryCursor execute(GeometryCursor geoms,
+ SpatialReference sr,
+ double maxSegmentLengthMeters,
+ int curveType,
+ ProgressTracker progressTracker) {
+ if (maxSegmentLengthMeters <= 0)
+ // TODO fix geometry exception to match native implementation
+ throw new GeometryException("max segment length must be positive and greater than 0");// GEOMTHROW(invalid_argument);
+
+ return new OperatorGeodeticDensifyCursor(geoms, sr, maxSegmentLengthMeters, progressTracker);
+ }
+
+ @Override
+ public Geometry execute(Geometry geom,
+ SpatialReference sr,
+ double maxSegmentLengthMeters,
+ int curveType,
+ ProgressTracker progressTracker) {
+ SimpleGeometryCursor inputCursor = new SimpleGeometryCursor(geom);
+ GeometryCursor outputCursor = execute(inputCursor, sr, maxSegmentLengthMeters, curveType, progressTracker);
+ return outputCursor.next();
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorGeodeticInverse.java b/src/main/java/com/esri/core/geometry/OperatorGeodeticInverse.java
index f5a03234..757a5e2e 100644
--- a/src/main/java/com/esri/core/geometry/OperatorGeodeticInverse.java
+++ b/src/main/java/com/esri/core/geometry/OperatorGeodeticInverse.java
@@ -29,31 +29,32 @@
*/
public abstract class OperatorGeodeticInverse extends Operator {
- @Override
- public Type getType() {
- return Type.GeodeticInverse;
- }
-
- /**
- * calculate the ngs forward equations for distance and azimuth calculations
- * @param geom1 point1 (for now only supports point, could support centroids in future)
- * @param geom2 point2 (for now only supports point, could support centroids in future)
- * @param sr1 spatial reference of point one (this is the ellipsoid that the calculation will use)
- * @param sr2 spatial reference of point two
- * @param geodeticCurveType for now only ellipsoid geodesic
- * @param progressTracker not used
- * @return forward results of azimuth from 1 to 2, azimuth from 2 to 1, and the distance
- */
- public abstract InverseResult execute(Geometry geom1,
- Geometry geom2,
- SpatialReference sr1,
- SpatialReference sr2,
- int geodeticCurveType,
- ProgressTracker progressTracker);
-
- public static OperatorGeodeticInverse local() {
- return (OperatorGeodeticInverse) OperatorFactoryLocal.getInstance()
- .getOperator(Type.GeodeticInverse);
- }
+ @Override
+ public Type getType() {
+ return Type.GeodeticInverse;
+ }
+
+ /**
+ * calculate the ngs forward equations for distance and azimuth calculations
+ *
+ * @param geom1 point1 (for now only supports point, could support centroids in future)
+ * @param geom2 point2 (for now only supports point, could support centroids in future)
+ * @param sr1 spatial reference of point one (this is the ellipsoid that the calculation will use)
+ * @param sr2 spatial reference of point two
+ * @param geodeticCurveType for now only ellipsoid geodesic
+ * @param progressTracker not used
+ * @return forward results of azimuth from 1 to 2, azimuth from 2 to 1, and the distance
+ */
+ public abstract InverseResult execute(Geometry geom1,
+ Geometry geom2,
+ SpatialReference sr1,
+ SpatialReference sr2,
+ int geodeticCurveType,
+ ProgressTracker progressTracker);
+
+ public static OperatorGeodeticInverse local() {
+ return (OperatorGeodeticInverse) OperatorFactoryLocal.getInstance()
+ .getOperator(Type.GeodeticInverse);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorGeodeticInverseLocal.java b/src/main/java/com/esri/core/geometry/OperatorGeodeticInverseLocal.java
index b8a4ea40..d52f81a8 100644
--- a/src/main/java/com/esri/core/geometry/OperatorGeodeticInverseLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorGeodeticInverseLocal.java
@@ -26,35 +26,35 @@
//This is a stub
class OperatorGeodeticInverseLocal extends OperatorGeodeticInverse {
- @Override
- public InverseResult execute(Geometry geom1, Geometry geom2, SpatialReference sr1, SpatialReference sr2, int geodeticCurveType, ProgressTracker progressTracker) {
- if (geodeticCurveType != GeodeticCurveType.Geodesic) {
- throw new GeometryException("only Geodesic implemented");
- }
- if (geom1.getType() != Geometry.Type.Point || geom2.getType() != Geometry.Type.Point) {
- throw new GeometryException("only implemented for points");
- }
-
- double a, e2;
- Point projected1;
- ProjectionTransformation projectionTransformation;
- if (sr1.getCoordinateSystemType() != SpatialReference.CoordinateSystemType.GEOGRAPHIC) {
- SpatialReference wgs84 = SpatialReference.create(4326);
- projectionTransformation = new ProjectionTransformation(sr1, wgs84);
- sr1 = wgs84;
- projected1 = (Point)OperatorProject.local().execute(geom1, projectionTransformation, progressTracker);
- a = wgs84.getMajorAxis();
- e2 = wgs84.getEccentricitySquared();
- } else {
- projected1 = (Point)geom1;
- a = sr1.getMajorAxis();
- e2 = sr1.getEccentricitySquared();
- }
-
- // TODO it'd be great if this was reusable so we didn't have this mem allocaiton
- projectionTransformation = new ProjectionTransformation(sr2, sr1);
- Point projected2 = (Point)OperatorProject.local().execute(geom2, projectionTransformation, progressTracker);
-
- return GeoDist.geodesicInverse(a, e2, projected1.getXY(), projected2.getXY());
- }
+ @Override
+ public InverseResult execute(Geometry geom1, Geometry geom2, SpatialReference sr1, SpatialReference sr2, int geodeticCurveType, ProgressTracker progressTracker) {
+ if (geodeticCurveType != GeodeticCurveType.Geodesic) {
+ throw new GeometryException("only Geodesic implemented");
+ }
+ if (geom1.getType() != Geometry.Type.Point || geom2.getType() != Geometry.Type.Point) {
+ throw new GeometryException("only implemented for points");
+ }
+
+ double a, e2;
+ Point projected1;
+ ProjectionTransformation projectionTransformation;
+ if (sr1.getCoordinateSystemType() != SpatialReference.CoordinateSystemType.GEOGRAPHIC) {
+ SpatialReference wgs84 = SpatialReference.create(4326);
+ projectionTransformation = new ProjectionTransformation(sr1, wgs84);
+ sr1 = wgs84;
+ projected1 = (Point) OperatorProject.local().execute(geom1, projectionTransformation, progressTracker);
+ a = wgs84.getMajorAxis();
+ e2 = wgs84.getEccentricitySquared();
+ } else {
+ projected1 = (Point) geom1;
+ a = sr1.getMajorAxis();
+ e2 = sr1.getEccentricitySquared();
+ }
+
+ // TODO it'd be great if this was reusable so we didn't have this mem allocaiton
+ projectionTransformation = new ProjectionTransformation(sr2, sr1);
+ Point projected2 = (Point) OperatorProject.local().execute(geom2, projectionTransformation, progressTracker);
+
+ return GeoDist.geodesicInverse(a, e2, projected1.getXY(), projected2.getXY());
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorGeodeticLength.java b/src/main/java/com/esri/core/geometry/OperatorGeodeticLength.java
index 665c7227..a58a4fb1 100644
--- a/src/main/java/com/esri/core/geometry/OperatorGeodeticLength.java
+++ b/src/main/java/com/esri/core/geometry/OperatorGeodeticLength.java
@@ -29,27 +29,27 @@
*/
public abstract class OperatorGeodeticLength extends Operator {
- @Override
- public Type getType() {
- return Operator.Type.GeodeticLength;
- }
-
- /**
- * Calculates the geodetic length of the input Geometry.
- *
- * @param geom The input Geometry for the geodetic length calculation.
- * @param sr The SpatialReference of the Geometry.
- * @param geodeticCurveType Use the {@link GeodeticCurveType} interface to choose the
- * interpretation of a line connecting two points.
- * @param progressTracker
- * @return Returns the geoetic length of the Geometry.
- */
- public abstract double execute(Geometry geom, SpatialReference sr,
- int geodeticCurveType, ProgressTracker progressTracker);
-
- public static OperatorGeodeticLength local() {
- return (OperatorGeodeticLength) OperatorFactoryLocal.getInstance()
- .getOperator(Type.GeodeticLength);
- }
+ @Override
+ public Type getType() {
+ return Operator.Type.GeodeticLength;
+ }
+
+ /**
+ * Calculates the geodetic length of the input Geometry.
+ *
+ * @param geom The input Geometry for the geodetic length calculation.
+ * @param sr The SpatialReference of the Geometry.
+ * @param geodeticCurveType Use the {@link GeodeticCurveType} interface to choose the
+ * interpretation of a line connecting two points.
+ * @param progressTracker
+ * @return Returns the geoetic length of the Geometry.
+ */
+ public abstract double execute(Geometry geom, SpatialReference sr,
+ int geodeticCurveType, ProgressTracker progressTracker);
+
+ public static OperatorGeodeticLength local() {
+ return (OperatorGeodeticLength) OperatorFactoryLocal.getInstance()
+ .getOperator(Type.GeodeticLength);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorGeodeticLengthLocal.java b/src/main/java/com/esri/core/geometry/OperatorGeodeticLengthLocal.java
index 822c311d..e1ba8048 100644
--- a/src/main/java/com/esri/core/geometry/OperatorGeodeticLengthLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorGeodeticLengthLocal.java
@@ -26,43 +26,43 @@
//This is a stub
class OperatorGeodeticLengthLocal extends OperatorGeodeticLength {
- @Override
- public double execute(Geometry geom,
- SpatialReference sr,
- int geodeticCurveType,
- ProgressTracker progressTracker) {
- if (geodeticCurveType != GeodeticCurveType.Geodesic) {
- throw new GeometryException("only Geodesic implemented");
- }
- if (geom.getType() == Geometry.Type.MultiPoint || geom.getType() == Geometry.Type.Point) {
- return 0;
- }
+ @Override
+ public double execute(Geometry geom,
+ SpatialReference sr,
+ int geodeticCurveType,
+ ProgressTracker progressTracker) {
+ if (geodeticCurveType != GeodeticCurveType.Geodesic) {
+ throw new GeometryException("only Geodesic implemented");
+ }
+ if (geom.getType() == Geometry.Type.MultiPoint || geom.getType() == Geometry.Type.Point) {
+ return 0;
+ }
- SegmentIteratorImpl segIter;
- double a, e2;
- if (sr.getCoordinateSystemType() != SpatialReference.CoordinateSystemType.GEOGRAPHIC) {
- SpatialReference wgs84 = SpatialReference.create(4326);
- ProjectionTransformation projectionTransformation = new ProjectionTransformation(sr, wgs84);
- Geometry projected = OperatorProject.local().execute(geom, projectionTransformation, progressTracker);
- segIter = ((MultiPathImpl)projected._getImpl()).querySegmentIterator();
- a = wgs84.getMajorAxis();
- e2 = wgs84.getEccentricitySquared();
- } else {
- segIter = ((MultiPathImpl)geom._getImpl()).querySegmentIterator();
- a = sr.getMajorAxis();
- e2 = sr.getEccentricitySquared();
- }
+ SegmentIteratorImpl segIter;
+ double a, e2;
+ if (sr.getCoordinateSystemType() != SpatialReference.CoordinateSystemType.GEOGRAPHIC) {
+ SpatialReference wgs84 = SpatialReference.create(4326);
+ ProjectionTransformation projectionTransformation = new ProjectionTransformation(sr, wgs84);
+ Geometry projected = OperatorProject.local().execute(geom, projectionTransformation, progressTracker);
+ segIter = ((MultiPathImpl) projected._getImpl()).querySegmentIterator();
+ a = wgs84.getMajorAxis();
+ e2 = wgs84.getEccentricitySquared();
+ } else {
+ segIter = ((MultiPathImpl) geom._getImpl()).querySegmentIterator();
+ a = sr.getMajorAxis();
+ e2 = sr.getEccentricitySquared();
+ }
- MathUtils.KahanSummator len = new MathUtils.KahanSummator(0);
+ MathUtils.KahanSummator len = new MathUtils.KahanSummator(0);
- while (segIter.nextPath()) {
- while (segIter.hasNextSegment()) {
- Segment segment = segIter.nextSegment();
- double dist = GeoDist.geodesicDistance(a, e2, segment.getStartXY(), segment.getEndXY(), null, null);
- len.add(dist);
- }
- }
+ while (segIter.nextPath()) {
+ while (segIter.hasNextSegment()) {
+ Segment segment = segIter.nextSegment();
+ double dist = GeoDist.geodesicDistance(a, e2, segment.getStartXY(), segment.getEndXY(), null, null);
+ len.add(dist);
+ }
+ }
- return len.getResult();
- }
+ return len.getResult();
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorImportFromESRIShape.java b/src/main/java/com/esri/core/geometry/OperatorImportFromESRIShape.java
index 469359c4..f41e4554 100644
--- a/src/main/java/com/esri/core/geometry/OperatorImportFromESRIShape.java
+++ b/src/main/java/com/esri/core/geometry/OperatorImportFromESRIShape.java
@@ -32,41 +32,41 @@
* Import from ESRI shape format.
*/
public abstract class OperatorImportFromESRIShape extends Operator {
- @Override
- public Type getType() {
- return Type.ImportFromESRIShape;
- }
+ @Override
+ public Type getType() {
+ return Type.ImportFromESRIShape;
+ }
- /**
- * Performs the ImportFromESRIShape operation on a stream of shape buffers
- *
- * @param importFlags Use the {@link ShapeImportFlags} interface. The default is 0, which means geometry comes
- * from a trusted source and is topologically simple.
- * If the geometry comes from non-trusted source (that is it can be non-simple), pass ShapeImportNonTrusted.
- * @param type The geometry type that you want to import. Use the {@link Geometry.Type} enum. It can be
- * Geometry.Type.Unknown if the type of geometry has to be
- * figured out from the shape buffer.
- * @param shapeBuffers The cursor over shape buffers that hold the Geometries in ESRIShape format.
- * @return Returns a GeometryCursor.
- */
- public abstract GeometryCursor execute(int importFlags, Geometry.Type type, ByteBufferCursor shapeBuffers);
+ /**
+ * Performs the ImportFromESRIShape operation on a stream of shape buffers
+ *
+ * @param importFlags Use the {@link ShapeImportFlags} interface. The default is 0, which means geometry comes
+ * from a trusted source and is topologically simple.
+ * If the geometry comes from non-trusted source (that is it can be non-simple), pass ShapeImportNonTrusted.
+ * @param type The geometry type that you want to import. Use the {@link Geometry.Type} enum. It can be
+ * Geometry.Type.Unknown if the type of geometry has to be
+ * figured out from the shape buffer.
+ * @param shapeBuffers The cursor over shape buffers that hold the Geometries in ESRIShape format.
+ * @return Returns a GeometryCursor.
+ */
+ public abstract GeometryCursor execute(int importFlags, Geometry.Type type, ByteBufferCursor shapeBuffers);
- /**
- * Performs the ImportFromESRIShape operation.
- *
- * @param importFlags Use the {@link ShapeImportFlags} interface. The default is 0, which means geometry
- * comes from a trusted source and is topologically simple.
- * If the geometry comes from non-trusted source (that is it can be non-simple), pass ShapeImportNonTrusted.
- * @param type The geometry type that you want to import. Use the {@link Geometry.Type} enum. It can be
- * Geometry.Type.Unknown if the type of geometry has to be
- * figured out from the shape buffer.
- * @param shapeBuffer The buffer holding the Geometry in ESRIShape format.
- * @return Returns the imported Geometry.
- */
- public abstract Geometry execute(int importFlags, Geometry.Type type, ByteBuffer shapeBuffer);
+ /**
+ * Performs the ImportFromESRIShape operation.
+ *
+ * @param importFlags Use the {@link ShapeImportFlags} interface. The default is 0, which means geometry
+ * comes from a trusted source and is topologically simple.
+ * If the geometry comes from non-trusted source (that is it can be non-simple), pass ShapeImportNonTrusted.
+ * @param type The geometry type that you want to import. Use the {@link Geometry.Type} enum. It can be
+ * Geometry.Type.Unknown if the type of geometry has to be
+ * figured out from the shape buffer.
+ * @param shapeBuffer The buffer holding the Geometry in ESRIShape format.
+ * @return Returns the imported Geometry.
+ */
+ public abstract Geometry execute(int importFlags, Geometry.Type type, ByteBuffer shapeBuffer);
- public static OperatorImportFromESRIShape local() {
- return (OperatorImportFromESRIShape) OperatorFactoryLocal.getInstance().getOperator(Type.ImportFromESRIShape);
- }
+ public static OperatorImportFromESRIShape local() {
+ return (OperatorImportFromESRIShape) OperatorFactoryLocal.getInstance().getOperator(Type.ImportFromESRIShape);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorImportFromESRIShapeCursor.java b/src/main/java/com/esri/core/geometry/OperatorImportFromESRIShapeCursor.java
index 2176eeb9..ce7e0cd9 100644
--- a/src/main/java/com/esri/core/geometry/OperatorImportFromESRIShapeCursor.java
+++ b/src/main/java/com/esri/core/geometry/OperatorImportFromESRIShapeCursor.java
@@ -32,989 +32,993 @@
public class OperatorImportFromESRIShapeCursor extends GeometryCursor {
- ByteBufferCursor m_inputShapeBuffers;
- int m_importFlags;
- int m_type;
-
- public OperatorImportFromESRIShapeCursor(int importFlags, int type, ByteBufferCursor shapeBuffers) {
- if (shapeBuffers == null)
- throw new GeometryException("invalid argument");
-
- m_importFlags = importFlags;
- m_type = type;
- m_inputShapeBuffers = shapeBuffers;
- }
-
- @Override
- public boolean hasNext() { return m_inputShapeBuffers != null && m_inputShapeBuffers.hasNext(); }
-
- @Override
- public Geometry next() {
- ByteBuffer shapeBuffer = m_inputShapeBuffers.next();
- if (shapeBuffer != null) {
- return importFromESRIShape(shapeBuffer);
- }
- return null;
- }
-
- @Override
- public SimpleStateEnum getSimpleState() {
- return m_inputShapeBuffers.getSimpleState();
- }
-
- @Override
- public String getFeatureID() { return m_inputShapeBuffers.getFeatureID(); }
-
- @Override
- public long getGeometryID() {
- return m_inputShapeBuffers.getByteBufferID();
- }
-
- private Geometry importFromESRIShape(ByteBuffer shapeBuffer) {
- ByteOrder initialOrder = shapeBuffer.order();
- shapeBuffer.order(ByteOrder.LITTLE_ENDIAN);
-
- try {
- // read type
- int shapetype = shapeBuffer.getInt(0);
-
- // Extract general type and modifiers
- int generaltype;
- int modifiers;
- switch (shapetype & ShapeModifiers.ShapeBasicTypeMask) {
- // Polygon
- case ShapeType.ShapePolygon:
- generaltype = ShapeType.ShapeGeneralPolygon;
- modifiers = 0;
- break;
- case ShapeType.ShapePolygonZM:
- generaltype = ShapeType.ShapeGeneralPolygon;
- modifiers = ShapeModifiers.ShapeHasZs | ShapeModifiers.ShapeHasMs;
- break;
- case ShapeType.ShapePolygonM:
- generaltype = ShapeType.ShapeGeneralPolygon;
- modifiers = ShapeModifiers.ShapeHasMs;
- break;
- case ShapeType.ShapePolygonZ:
- generaltype = ShapeType.ShapeGeneralPolygon;
- modifiers = ShapeModifiers.ShapeHasZs;
- break;
- case ShapeType.ShapeGeneralPolygon:
- generaltype = ShapeType.ShapeGeneralPolygon;
- modifiers = shapetype & ShapeModifiers.ShapeModifierMask;
- break;
-
- // Polyline
- case ShapeType.ShapePolyline:
- generaltype = ShapeType.ShapeGeneralPolyline;
- modifiers = 0;
- break;
- case ShapeType.ShapePolylineZM:
- generaltype = ShapeType.ShapeGeneralPolyline;
- modifiers = ShapeModifiers.ShapeHasZs
- | (int) ShapeModifiers.ShapeHasMs;
- break;
- case ShapeType.ShapePolylineM:
- generaltype = ShapeType.ShapeGeneralPolyline;
- modifiers = ShapeModifiers.ShapeHasMs;
- break;
- case ShapeType.ShapePolylineZ:
- generaltype = ShapeType.ShapeGeneralPolyline;
- modifiers = ShapeModifiers.ShapeHasZs;
- break;
- case ShapeType.ShapeGeneralPolyline:
- generaltype = ShapeType.ShapeGeneralPolyline;
- modifiers = shapetype & ShapeModifiers.ShapeModifierMask;
- break;
-
- // MultiPoint
- case ShapeType.ShapeMultiPoint:
- generaltype = ShapeType.ShapeGeneralMultiPoint;
- modifiers = 0;
- break;
- case ShapeType.ShapeMultiPointZM:
- generaltype = ShapeType.ShapeGeneralMultiPoint;
- modifiers = (int) ShapeModifiers.ShapeHasZs
- | (int) ShapeModifiers.ShapeHasMs;
- break;
- case ShapeType.ShapeMultiPointM:
- generaltype = ShapeType.ShapeGeneralMultiPoint;
- modifiers = ShapeModifiers.ShapeHasMs;
- break;
- case ShapeType.ShapeMultiPointZ:
- generaltype = ShapeType.ShapeGeneralMultiPoint;
- modifiers = ShapeModifiers.ShapeHasZs;
- break;
- case ShapeType.ShapeGeneralMultiPoint:
- generaltype = ShapeType.ShapeGeneralMultiPoint;
- modifiers = shapetype & ShapeModifiers.ShapeModifierMask;
- break;
-
- // Point
- case ShapeType.ShapePoint:
- generaltype = ShapeType.ShapeGeneralPoint;
- modifiers = 0;
- break;
- case ShapeType.ShapePointZM:
- generaltype = ShapeType.ShapeGeneralPoint;
- modifiers = ShapeModifiers.ShapeHasZs
- | (int) ShapeModifiers.ShapeHasMs;
- break;
- case ShapeType.ShapePointM:
- generaltype = ShapeType.ShapeGeneralPoint;
- modifiers = ShapeModifiers.ShapeHasMs;
- break;
- case ShapeType.ShapePointZ:
- generaltype = ShapeType.ShapeGeneralPoint;
- modifiers = ShapeModifiers.ShapeHasZs;
- break;
- case ShapeType.ShapeGeneralPoint:
- generaltype = ShapeType.ShapeGeneralPoint;
- modifiers = shapetype & ShapeModifiers.ShapeModifierMask;
- break;
-
- // Null Geometry
- case ShapeType.ShapeNull:
- return null;
-
- default:
- throw new GeometryException("invalid shape type");
- }
-
- switch (generaltype) {
- case ShapeType.ShapeGeneralPolygon:
- if (m_type != Geometry.GeometryType.Polygon
- && m_type != Geometry.GeometryType.Unknown
- && m_type != Geometry.GeometryType.Envelope)
- throw new GeometryException("invalid shape type");
- return importFromESRIShapeMultiPath(true, modifiers,
- shapeBuffer);
-
- case ShapeType.ShapeGeneralPolyline:
- if (m_type != Geometry.GeometryType.Polyline
- && m_type != Geometry.GeometryType.Unknown
- && m_type != Geometry.GeometryType.Envelope)
- throw new GeometryException("invalid shape type");
- return importFromESRIShapeMultiPath(false, modifiers,
- shapeBuffer);
-
- case ShapeType.ShapeGeneralMultiPoint:
- if (m_type != Geometry.GeometryType.MultiPoint
- && m_type != Geometry.GeometryType.Unknown
- && m_type != Geometry.GeometryType.Envelope)
- throw new GeometryException("invalid shape type");
- return importFromESRIShapeMultiPoint(modifiers, shapeBuffer);
-
- case ShapeType.ShapeGeneralPoint:
- if (m_type != Geometry.GeometryType.Point
- && m_type != Geometry.GeometryType.MultiPoint
- && m_type != Geometry.GeometryType.Unknown
- && m_type != Geometry.GeometryType.Envelope)
- throw new GeometryException("invalid shape type");
- return importFromESRIShapePoint(modifiers, shapeBuffer);
- }
-
- return null;
- } finally {
- shapeBuffer.order(initialOrder);
- }
- }
-
- private Geometry importFromESRIShapeMultiPath(boolean bPolygon,
- int modifiers, ByteBuffer shapeBuffer) {
- int offset = 4;
-
- boolean bZs = (modifiers & (int) ShapeModifiers.ShapeHasZs) != 0;
- boolean bMs = (modifiers & (int) ShapeModifiers.ShapeHasMs) != 0;
- boolean bIDs = (modifiers & (int) ShapeModifiers.ShapeHasIDs) != 0;
-
- boolean bHasAttributes = bZs || bMs || bIDs;
- boolean bHasBadRings = false;
-
- // read Envelope
- double xmin = shapeBuffer.getDouble(offset);
- offset += 8;
- double ymin = shapeBuffer.getDouble(offset);
- offset += 8;
- double xmax = shapeBuffer.getDouble(offset);
- offset += 8;
- double ymax = shapeBuffer.getDouble(offset);
- offset += 8;
-
- // read part count
- int originalPartCount = shapeBuffer.getInt(offset);
- offset += 4;
- int partCount = 0;
-
- // read point count
- int pointCount = shapeBuffer.getInt(offset);
- offset += 4;
-
- AttributeStreamOfDbl position = null;
- AttributeStreamOfDbl zs = null;
- AttributeStreamOfDbl ms = null;
- AttributeStreamOfInt32 ids = null;
- AttributeStreamOfInt32 parts = null;
- AttributeStreamOfInt8 pathFlags = null;
-
- Envelope bbox = null;
- MultiPath multipath = null;
- MultiPathImpl multipathImpl = null;
- if (m_type == Geometry.GeometryType.Polygon
- || m_type == Geometry.GeometryType.Polyline
- || m_type == Geometry.GeometryType.Unknown) {
- if (bPolygon)
- multipath = new Polygon();
- else
- multipath = new Polyline();
-
- multipathImpl = (MultiPathImpl) multipath._getImpl();
-
- if (pointCount > 0) {
- bbox = new Envelope();
- bbox.setCoords(xmin, ymin, xmax, ymax);
- parts = (AttributeStreamOfInt32) AttributeStreamBase
- .createIndexStream(originalPartCount + 1);
-
- int previstart = -1;
- int lastCount = 0;
- for (int i = 0; i < originalPartCount; i++) {
- int istart = shapeBuffer.getInt(offset);
- offset += 4;
- lastCount = istart;
- if (previstart > istart || istart < 0)// check that the part
- // indices in the
- // buffer are not
- // corrupted
- throw new GeometryException("corrupted geometry");
-
- if (istart != previstart) {
- parts.write(partCount, istart);
- previstart = istart;
- partCount++;
- }
- }
-
- parts.resize(partCount + 1);
- if (pointCount < lastCount)// check that the point count in the
- // buffer is not corrupted
- throw new GeometryException("corrupted geometry");
-
- parts.write(partCount, pointCount);
- pathFlags = (AttributeStreamOfInt8) AttributeStreamBase
- .createByteStream(parts.size(), (byte) 0);
-
- // Create empty position stream
- position = (AttributeStreamOfDbl) AttributeStreamBase
- .createAttributeStreamWithSemantics(Semantics.POSITION,
- pointCount);
-
- int startpart = parts.read(0);
- // read xy coordinates
- int xyindex = 0;
- for (int ipart = 0; ipart < partCount; ipart++) {
- int endpartActual = parts.read(ipart + 1);
- // for polygons we read one point less, then analyze if the
- // polygon is closed.
- int endpart = (bPolygon) ? endpartActual - 1
- : endpartActual;
-
- double startx = shapeBuffer.getDouble(offset);
- offset += 8;
- double starty = shapeBuffer.getDouble(offset);
- offset += 8;
- position.write(2 * xyindex, startx);
- position.write(2 * xyindex + 1, starty);
- xyindex++;
-
- for (int i = startpart + 1; i < endpart; i++) {
- double x = shapeBuffer.getDouble(offset);
- offset += 8;
- double y = shapeBuffer.getDouble(offset);
- offset += 8;
- position.write(2 * xyindex, x);
- position.write(2 * xyindex + 1, y);
- xyindex++;
- }
-
- if (endpart - startpart < 2) {// a part with only one point
- multipathImpl.setIsSimple(GeometryXSimple.Unknown, 0.0,
- false);
- }
-
- if (bPolygon) {// read the last point of the part to decide
- // if we need to close the polygon
- if (startpart == endpart) {// a part with only one point
- parts.write(ipart + 1, xyindex);
- } else {
- double x = shapeBuffer.getDouble(offset);
- offset += 8;
- double y = shapeBuffer.getDouble(offset);
- offset += 8;
-
- if (x != startx || y != starty) {// bad polygon. The
- // last point is
- // not the same
- // as the last
- // one. We need
- // to add it so
- // that we do
- // not loose it.
- position.write(2 * xyindex, x);
- position.write(2 * xyindex + 1, y);
- xyindex++;
- multipathImpl.setIsSimple(
- GeometryXSimple.Unknown, 0.0, false);
- bHasBadRings = true;
- // write part count to indicate we need to
- // account for one extra point
- // The count will be fixed after the attributes
- // are processed. So we write negative only when
- // there are attributes.
- parts.write(ipart + 1,
- bHasAttributes ? -xyindex : xyindex);
- } else
- parts.write(ipart + 1, xyindex);
- }
-
- pathFlags.setBits(ipart, (byte) PathFlags.enumClosed);
- }
-
- startpart = endpartActual;
- }
-
- if (bZs)
- bbox.addAttribute(Semantics.Z);
-
- if (bMs)
- bbox.addAttribute(Semantics.M);
-
- if (bIDs)
- bbox.addAttribute(Semantics.ID);
- }
- } else {
- bbox = new Envelope();
-
- if (bZs)
- bbox.addAttribute(Semantics.Z);
-
- if (bMs)
- bbox.addAttribute(Semantics.M);
-
- if (bIDs)
- bbox.addAttribute(Semantics.ID);
-
- if (pointCount > 0) {
- bbox.setCoords(xmin, ymin, xmax, ymax);
- offset += pointCount * 16 + originalPartCount * 4;
- } else
- return (Geometry) bbox;
- }
-
- // read Zs
- if (bZs) {
- if (pointCount > 0) {
- double zmin = Interop.translateFromAVNaN(shapeBuffer
- .getDouble(offset));
- offset += 8;
- double zmax = Interop.translateFromAVNaN(shapeBuffer
- .getDouble(offset));
- offset += 8;
-
- Envelope1D env = new Envelope1D();
- env.setCoords(zmin, zmax);
- bbox.setInterval(Semantics.Z, 0, env);
-
- if (m_type == Geometry.GeometryType.Polygon
- || m_type == Geometry.GeometryType.Polyline
- || m_type == Geometry.GeometryType.Unknown) {
- zs = (AttributeStreamOfDbl) AttributeStreamBase
- .createAttributeStreamWithSemantics(Semantics.Z,
- pointCount);
-
- boolean bCreate = false;
- int startpart = parts.read(0);
- for (int ipart = 0; ipart < partCount; ipart++) {
- int endpartActual = parts.read(ipart + 1);
- int endpart = Math.abs(endpartActual);
-
- double startz = Interop.translateFromAVNaN(shapeBuffer
- .getDouble(offset));
- offset += 8;
- zs.write(startpart, startz);
- if (!VertexDescription.isDefaultValue(Semantics.Z,
- startz))
- bCreate = true;
-
- for (int i = startpart + 1; i < endpart; i++) {
- double z = Interop.translateFromAVNaN(shapeBuffer
- .getDouble(offset));
- offset += 8;
- zs.write(i, z);
- if (!VertexDescription.isDefaultValue(Semantics.Z,
- z))
- bCreate = true;
- }
-
- if (bPolygon && endpartActual > 0) {
- offset += 8;
- }
-
- startpart = endpart;
- }
-
- if (!bCreate)
- zs = null;
- } else
- offset += pointCount * 8;
- }
-
- if (m_type == Geometry.GeometryType.Polygon
- || m_type == Geometry.GeometryType.Polyline
- || m_type == Geometry.GeometryType.Unknown)
- multipathImpl.setAttributeStreamRef(Semantics.Z, zs);
- }
-
- // read Ms
- if (bMs) {
- if (pointCount > 0) {
- double mmin = Interop.translateFromAVNaN(shapeBuffer
- .getDouble(offset));
- offset += 8;
- double mmax = Interop.translateFromAVNaN(shapeBuffer
- .getDouble(offset));
- offset += 8;
-
- Envelope1D env = new Envelope1D();
- env.setCoords(mmin, mmax);
- bbox.setInterval(Semantics.M, 0, env);
-
- if (m_type == Geometry.GeometryType.Polygon
- || m_type == Geometry.GeometryType.Polyline
- || m_type == Geometry.GeometryType.Unknown) {
- ms = (AttributeStreamOfDbl) AttributeStreamBase
- .createAttributeStreamWithSemantics(Semantics.M,
- pointCount);
-
- boolean bCreate = false;
- int startpart = parts.read(0);
- for (int ipart = 0; ipart < partCount; ipart++) {
- int endpartActual = parts.read(ipart + 1);
- int endpart = Math.abs(endpartActual);
-
- double startm = Interop.translateFromAVNaN(shapeBuffer
- .getDouble(offset));
- offset += 8;
- ms.write(startpart, startm);
- if (!VertexDescription.isDefaultValue(Semantics.M,
- startm))
- bCreate = true;
-
- for (int i = startpart + 1; i < endpart; i++) {
- double m = Interop.translateFromAVNaN(shapeBuffer
- .getDouble(offset));
- offset += 8;
- ms.write(i, m);
- if (!VertexDescription.isDefaultValue(Semantics.M,
- m))
- bCreate = true;
- }
-
- if (bPolygon && endpartActual > 0) {
- offset += 8;
- }
-
- startpart = endpart;
- }
-
- if (!bCreate)
- ms = null;
- } else
- offset += pointCount * 8;
- }
-
- if (m_type == Geometry.GeometryType.Polygon
- || m_type == Geometry.GeometryType.Polyline
- || m_type == Geometry.GeometryType.Unknown)
- multipathImpl.setAttributeStreamRef(Semantics.M, ms);
- }
-
- // read IDs
- if (bIDs) {
- if (pointCount > 0) {
- double idmin = NumberUtils.doubleMax();
- double idmax = -NumberUtils.doubleMax();
-
- if (m_type == Geometry.GeometryType.Polygon
- || m_type == Geometry.GeometryType.Polyline
- || m_type == Geometry.GeometryType.Unknown) {
- ids = (AttributeStreamOfInt32) AttributeStreamBase
- .createAttributeStreamWithSemantics(Semantics.ID,
- pointCount);
-
- boolean bCreate = false;
- int startpart = parts.read(0);
- for (int ipart = 0; ipart < partCount; ipart++) {
- int endpartActual = parts.read(ipart + 1);
- int endpart = Math.abs(endpartActual);
-
- int startid = shapeBuffer.getInt(offset);
- offset += 4;
- ids.write(startpart, startid);
- if (!VertexDescription.isDefaultValue(Semantics.ID,
- startid))
- bCreate = true;
-
- for (int i = startpart + 1; i < endpart; i++) {
- int id = shapeBuffer.getInt(offset);
- offset += 4;
- ids.write(i, id);
- if (!bCreate
- && !VertexDescription.isDefaultValue(
- Semantics.ID, id))
- bCreate = true;
-
- if (idmin > id)
- idmin = id;
- else if (idmax < id)
- idmax = id;
- }
-
- if (bPolygon && endpartActual > 0) {
- offset += 4;
- }
-
- startpart = endpart;
- }
-
- if (!bCreate)
- ids = null;
- } else {
- for (int i = 0; i < pointCount; i++) {
- int id = shapeBuffer.getInt(offset);
- offset += 4;
-
- if (idmin > id)
- idmin = id;
- else if (idmax < id)
- idmax = id;
- }
- }
-
- Envelope1D env = new Envelope1D();
- env.setCoords(idmin, idmax);
- bbox.setInterval(Semantics.ID, 0, env);
- }
-
- if (m_type == Geometry.GeometryType.Polygon
- || m_type == Geometry.GeometryType.Polyline
- || m_type == Geometry.GeometryType.Unknown)
- multipathImpl.setAttributeStreamRef(Semantics.ID, ids);
- }
-
- if (bHasBadRings && bHasAttributes) {// revert our hack for bad polygons
- for (int ipart = 1; ipart < partCount + 1; ipart++) {
- int v = parts.read(ipart);
- if (v < 0)
- parts.write(ipart, -v);
- }
- }
-
- if (m_type == Geometry.GeometryType.Envelope)
- return (Geometry) bbox;
-
- if (pointCount > 0) {
- multipathImpl.setPathStreamRef(parts);
- multipathImpl.setPathFlagsStreamRef(pathFlags);
- multipathImpl.setAttributeStreamRef(Semantics.POSITION, position);
- multipathImpl.setEnvelope(bbox);
- }
-
- if ((m_importFlags & ShapeImportFlags.ShapeImportNonTrusted) == 0)
- multipathImpl.setIsSimple(GeometryXSimple.Weak, 0.0, false);// We
- // use
- // tolerance
- // of 0.
- // What
- // should
- // we
- // instead?
-
- return (Geometry) multipath;
- }
-
- private Geometry importFromESRIShapeMultiPoint(int modifiers,
- ByteBuffer shapeBuffer) {
- int offset = 4;
-
- boolean bZs = (modifiers & (int) ShapeModifiers.ShapeHasZs) != 0;
- boolean bMs = (modifiers & (int) ShapeModifiers.ShapeHasMs) != 0;
- boolean bIDs = (modifiers & modifiers & (int) ShapeModifiers.ShapeHasIDs) != 0;
-
- double xmin = shapeBuffer.getDouble(offset);
- offset += 8;
- double ymin = shapeBuffer.getDouble(offset);
- offset += 8;
- double xmax = shapeBuffer.getDouble(offset);
- offset += 8;
- double ymax = shapeBuffer.getDouble(offset);
- offset += 8;
-
- int cPoints = shapeBuffer.getInt(offset);
- offset += 4;
-
- AttributeStreamOfDbl position = null;
- AttributeStreamOfDbl zs = null;
- AttributeStreamOfDbl ms = null;
- AttributeStreamOfInt32 ids = null;
-
- Envelope bbox = null;
- MultiPoint multipoint = null;
- MultiPointImpl multipointImpl = null;
-
- if (m_type == Geometry.GeometryType.MultiPoint
- || m_type == Geometry.GeometryType.Unknown) {
- multipoint = new MultiPoint();
- multipointImpl = (MultiPointImpl) multipoint._getImpl();
-
- if (cPoints > 0) {
- bbox = new Envelope();
- multipointImpl.resize(cPoints);
- position = (AttributeStreamOfDbl) AttributeStreamBase
- .createAttributeStreamWithSemantics(Semantics.POSITION,
- cPoints);
-
- for (int i = 0; i < cPoints; i++) {
- double x = shapeBuffer.getDouble(offset);
- offset += 8;
- double y = shapeBuffer.getDouble(offset);
- offset += 8;
- position.write(2 * i, x);
- position.write(2 * i + 1, y);
- }
-
- multipointImpl.resize(cPoints);
- bbox.setCoords(xmin, ymin, xmax, ymax);
-
- if (bZs)
- bbox.addAttribute(Semantics.Z);
-
- if (bMs)
- bbox.addAttribute(Semantics.M);
-
- if (bIDs)
- bbox.addAttribute(Semantics.ID);
- }
- } else {
- bbox = new Envelope();
-
- if (bZs)
- bbox.addAttribute(Semantics.Z);
-
- if (bMs)
- bbox.addAttribute(Semantics.M);
-
- if (bIDs)
- bbox.addAttribute(Semantics.ID);
-
- if (cPoints > 0) {
- bbox.setCoords(xmin, ymin, xmax, ymax);
- offset += cPoints * 16;
- } else
- return (Geometry) bbox;
- }
-
- if (bZs) {
- if (cPoints > 0) {
- double zmin = Interop.translateFromAVNaN(shapeBuffer
- .getDouble(offset));
- offset += 8;
- double zmax = Interop.translateFromAVNaN(shapeBuffer
- .getDouble(offset));
- offset += 8;
-
- Envelope1D env = new Envelope1D();
- env.setCoords(zmin, zmax);
- bbox.setInterval(Semantics.Z, 0, env);
-
- if (m_type == Geometry.GeometryType.MultiPoint
- || m_type == Geometry.GeometryType.Unknown) {
- zs = (AttributeStreamOfDbl) AttributeStreamBase
- .createAttributeStreamWithSemantics(Semantics.Z,
- cPoints);
-
- boolean bCreate = false;
- for (int i = 0; i < cPoints; i++) {
- double value = Interop.translateFromAVNaN(shapeBuffer
- .getDouble(offset));
- offset += 8;
- zs.write(i, value);
- if (!VertexDescription.isDefaultValue(Semantics.Z,
- value))
- bCreate = true;
- }
-
- if (!bCreate)
- zs = null;
- } else
- offset += cPoints * 8;
- }
-
- if (m_type == Geometry.GeometryType.MultiPoint
- || m_type == Geometry.GeometryType.Unknown)
- multipointImpl.setAttributeStreamRef(Semantics.Z, zs);
- }
-
- if (bMs) {
- if (cPoints > 0) {
- double mmin = Interop.translateFromAVNaN(shapeBuffer
- .getDouble(offset));
- offset += 8;
- double mmax = Interop.translateFromAVNaN(shapeBuffer
- .getDouble(offset));
- offset += 8;
-
- Envelope1D env = new Envelope1D();
- env.setCoords(mmin, mmax);
- bbox.setInterval(Semantics.M, 0, env);
- if (m_type == Geometry.GeometryType.MultiPoint
- || m_type == Geometry.GeometryType.Unknown) {
- ms = (AttributeStreamOfDbl) AttributeStreamBase
- .createAttributeStreamWithSemantics(Semantics.M,
- cPoints);
-
- boolean bCreate = false;
- for (int i = 0; i < cPoints; i++) {
- double value = Interop.translateFromAVNaN(shapeBuffer
- .getDouble(offset));
- offset += 8;
- ms.write(i, value);
- if (!VertexDescription.isDefaultValue(Semantics.M,
- value))
- bCreate = true;
- }
-
- if (!bCreate)
- ms = null;
- } else
- offset += cPoints * 8;
- }
-
- if (m_type == Geometry.GeometryType.MultiPoint
- || m_type == Geometry.GeometryType.Unknown)
- multipointImpl.setAttributeStreamRef(Semantics.M, ms);
- }
-
- if (bIDs) {
- if (cPoints > 0) {
- double idmin = NumberUtils.doubleMax();
- double idmax = -NumberUtils.doubleMax();
-
- if (m_type == Geometry.GeometryType.MultiPoint
- || m_type == Geometry.GeometryType.Unknown) {
- ids = (AttributeStreamOfInt32) AttributeStreamBase
- .createAttributeStreamWithSemantics(Semantics.ID,
- cPoints);
-
- boolean bCreate = false;
- for (int i = 0; i < cPoints; i++) {
- int value = shapeBuffer.getInt(offset);
- offset += 4;
- ids.write(i, value);
- if (!VertexDescription.isDefaultValue(Semantics.ID,
- value))
- bCreate = true;
-
- if (idmin > value)
- idmin = value;
- else if (idmax < value)
- idmax = value;
- }
-
- if (!bCreate)
- ids = null;
- } else {
- for (int i = 0; i < cPoints; i++) {
- int id = shapeBuffer.getInt(offset);
- offset += 4;
-
- if (idmin > id)
- idmin = id;
- else if (idmax < id)
- idmax = id;
- }
- }
-
- Envelope1D env = new Envelope1D();
- env.setCoords(idmin, idmax);
- bbox.setInterval(Semantics.ID, 0, env);
- }
-
- if (m_type == Geometry.GeometryType.MultiPoint
- || m_type == Geometry.GeometryType.Unknown)
- multipointImpl.setAttributeStreamRef(Semantics.ID, ids);
- }
-
- if (m_type == Geometry.GeometryType.Envelope)
- return (Geometry) bbox;
-
- if (cPoints > 0) {
- multipointImpl.setAttributeStreamRef(Semantics.POSITION, position);
- multipointImpl.setEnvelope(bbox);
- }
-
- return (Geometry) multipoint;
- }
-
- private Geometry importFromESRIShapePoint(int modifiers,
- ByteBuffer shapeBuffer) {
- int offset = 4;
-
- boolean bZs = (modifiers & (int) ShapeModifiers.ShapeHasZs) != 0;
- boolean bMs = (modifiers & (int) ShapeModifiers.ShapeHasMs) != 0;
- boolean bIDs = (modifiers & modifiers & (int) ShapeModifiers.ShapeHasIDs) != 0;
-
- // read XY
- double x = shapeBuffer.getDouble(offset);
- offset += 8;
- double y = shapeBuffer.getDouble(offset);
- offset += 8;
-
- boolean bEmpty = NumberUtils.isNaN(x);
-
- double z = NumberUtils.NaN();
- if (bZs) {
- z = Interop.translateFromAVNaN(shapeBuffer.getDouble(offset));
- offset += 8;
- }
-
- double m = NumberUtils.NaN();
- if (bMs) {
- m = Interop.translateFromAVNaN(shapeBuffer.getDouble(offset));
- offset += 8;
- }
-
- int id = -1;
- if (bIDs) {
- id = shapeBuffer.getInt(offset);
- offset += 4;
- }
-
- if (m_type == Geometry.GeometryType.MultiPoint) {
- MultiPoint newmultipoint = new MultiPoint();
- MultiPointImpl multipointImpl = (MultiPointImpl) newmultipoint
- ._getImpl();
-
- if (!bEmpty) {
- AttributeStreamBase newPositionStream = AttributeStreamBase
- .createAttributeStreamWithSemantics(Semantics.POSITION,
- 1);
- AttributeStreamOfDbl position = (AttributeStreamOfDbl) newPositionStream;
- position.write(0, x);
- position.write(1, y);
-
- multipointImpl.setAttributeStreamRef(Semantics.POSITION,
- newPositionStream);
- multipointImpl.resize(1);
- }
-
- if (bZs) {
- multipointImpl.addAttribute(Semantics.Z);
- if (!bEmpty
- && !VertexDescription.isDefaultValue(Semantics.Z, z)) {
- AttributeStreamBase newZStream = AttributeStreamBase
- .createAttributeStreamWithSemantics(Semantics.Z, 1);
- newZStream.writeAsDbl(0, z);
- multipointImpl.setAttributeStreamRef(Semantics.Z,
- newZStream);
- }
- }
-
- if (bMs) {
- multipointImpl.addAttribute(Semantics.M);
- if (!bEmpty
- && !VertexDescription.isDefaultValue(Semantics.M, m)) {
- AttributeStreamBase newMStream = AttributeStreamBase
- .createAttributeStreamWithSemantics(Semantics.M, 1);
- newMStream.writeAsDbl(0, m);
- multipointImpl.setAttributeStreamRef(Semantics.M,
- newMStream);
- }
- }
-
- if (bIDs) {
- multipointImpl.addAttribute(Semantics.ID);
- if (!bEmpty
- && !VertexDescription.isDefaultValue(Semantics.ID, id)) {
- AttributeStreamBase newIDStream = AttributeStreamBase
- .createAttributeStreamWithSemantics(Semantics.ID, 1);
- newIDStream.writeAsInt(0, id);
- multipointImpl.setAttributeStreamRef(Semantics.ID,
- newIDStream);
- }
- }
-
- return (Geometry) newmultipoint;
- } else if (m_type == Geometry.GeometryType.Envelope) {
- Envelope envelope = new Envelope();
- envelope.setCoords(x, y, x, y);
-
- if (bZs) {
- Envelope1D interval = new Envelope1D();
- interval.vmin = z;
- interval.vmax = z;
- envelope.addAttribute(Semantics.Z);
- envelope.setInterval(Semantics.Z, 0, interval);
- }
-
- if (bMs) {
- Envelope1D interval = new Envelope1D();
- interval.vmin = m;
- interval.vmax = m;
- envelope.addAttribute(Semantics.M);
- envelope.setInterval(Semantics.M, 0, interval);
- }
-
- if (bIDs) {
- Envelope1D interval = new Envelope1D();
- interval.vmin = id;
- interval.vmax = id;
- envelope.addAttribute(Semantics.ID);
- envelope.setInterval(Semantics.ID, 0, interval);
- }
-
- return (Geometry) envelope;
- }
-
- Point point = new Point();
-
- if (!bEmpty) {
- point.setX(Interop.translateFromAVNaN(x));
- point.setY(Interop.translateFromAVNaN(y));
- }
-
- // read Z
- if (bZs) {
- point.addAttribute(Semantics.Z);
- if (!bEmpty)
- point.setZ(Interop.translateFromAVNaN(z));
- }
-
- // read M
- if (bMs) {
- point.addAttribute(Semantics.M);
- if (!bEmpty)
- point.setM(Interop.translateFromAVNaN(m));
- }
-
- // read ID
- if (bIDs) {
- point.addAttribute(Semantics.ID);
- if (!bEmpty)
- point.setID(id);
- }
-
- return (Geometry) point;
- }
+ ByteBufferCursor m_inputShapeBuffers;
+ int m_importFlags;
+ int m_type;
+
+ public OperatorImportFromESRIShapeCursor(int importFlags, int type, ByteBufferCursor shapeBuffers) {
+ if (shapeBuffers == null)
+ throw new GeometryException("invalid argument");
+
+ m_importFlags = importFlags;
+ m_type = type;
+ m_inputShapeBuffers = shapeBuffers;
+ }
+
+ @Override
+ public boolean hasNext() {
+ return m_inputShapeBuffers != null && m_inputShapeBuffers.hasNext();
+ }
+
+ @Override
+ public Geometry next() {
+ ByteBuffer shapeBuffer = m_inputShapeBuffers.next();
+ if (shapeBuffer != null) {
+ return importFromESRIShape(shapeBuffer);
+ }
+ return null;
+ }
+
+ @Override
+ public SimpleStateEnum getSimpleState() {
+ return m_inputShapeBuffers.getSimpleState();
+ }
+
+ @Override
+ public String getFeatureID() {
+ return m_inputShapeBuffers.getFeatureID();
+ }
+
+ @Override
+ public long getGeometryID() {
+ return m_inputShapeBuffers.getByteBufferID();
+ }
+
+ private Geometry importFromESRIShape(ByteBuffer shapeBuffer) {
+ ByteOrder initialOrder = shapeBuffer.order();
+ shapeBuffer.order(ByteOrder.LITTLE_ENDIAN);
+
+ try {
+ // read type
+ int shapetype = shapeBuffer.getInt(0);
+
+ // Extract general type and modifiers
+ int generaltype;
+ int modifiers;
+ switch (shapetype & ShapeModifiers.ShapeBasicTypeMask) {
+ // Polygon
+ case ShapeType.ShapePolygon:
+ generaltype = ShapeType.ShapeGeneralPolygon;
+ modifiers = 0;
+ break;
+ case ShapeType.ShapePolygonZM:
+ generaltype = ShapeType.ShapeGeneralPolygon;
+ modifiers = ShapeModifiers.ShapeHasZs | ShapeModifiers.ShapeHasMs;
+ break;
+ case ShapeType.ShapePolygonM:
+ generaltype = ShapeType.ShapeGeneralPolygon;
+ modifiers = ShapeModifiers.ShapeHasMs;
+ break;
+ case ShapeType.ShapePolygonZ:
+ generaltype = ShapeType.ShapeGeneralPolygon;
+ modifiers = ShapeModifiers.ShapeHasZs;
+ break;
+ case ShapeType.ShapeGeneralPolygon:
+ generaltype = ShapeType.ShapeGeneralPolygon;
+ modifiers = shapetype & ShapeModifiers.ShapeModifierMask;
+ break;
+
+ // Polyline
+ case ShapeType.ShapePolyline:
+ generaltype = ShapeType.ShapeGeneralPolyline;
+ modifiers = 0;
+ break;
+ case ShapeType.ShapePolylineZM:
+ generaltype = ShapeType.ShapeGeneralPolyline;
+ modifiers = ShapeModifiers.ShapeHasZs
+ | (int) ShapeModifiers.ShapeHasMs;
+ break;
+ case ShapeType.ShapePolylineM:
+ generaltype = ShapeType.ShapeGeneralPolyline;
+ modifiers = ShapeModifiers.ShapeHasMs;
+ break;
+ case ShapeType.ShapePolylineZ:
+ generaltype = ShapeType.ShapeGeneralPolyline;
+ modifiers = ShapeModifiers.ShapeHasZs;
+ break;
+ case ShapeType.ShapeGeneralPolyline:
+ generaltype = ShapeType.ShapeGeneralPolyline;
+ modifiers = shapetype & ShapeModifiers.ShapeModifierMask;
+ break;
+
+ // MultiPoint
+ case ShapeType.ShapeMultiPoint:
+ generaltype = ShapeType.ShapeGeneralMultiPoint;
+ modifiers = 0;
+ break;
+ case ShapeType.ShapeMultiPointZM:
+ generaltype = ShapeType.ShapeGeneralMultiPoint;
+ modifiers = (int) ShapeModifiers.ShapeHasZs
+ | (int) ShapeModifiers.ShapeHasMs;
+ break;
+ case ShapeType.ShapeMultiPointM:
+ generaltype = ShapeType.ShapeGeneralMultiPoint;
+ modifiers = ShapeModifiers.ShapeHasMs;
+ break;
+ case ShapeType.ShapeMultiPointZ:
+ generaltype = ShapeType.ShapeGeneralMultiPoint;
+ modifiers = ShapeModifiers.ShapeHasZs;
+ break;
+ case ShapeType.ShapeGeneralMultiPoint:
+ generaltype = ShapeType.ShapeGeneralMultiPoint;
+ modifiers = shapetype & ShapeModifiers.ShapeModifierMask;
+ break;
+
+ // Point
+ case ShapeType.ShapePoint:
+ generaltype = ShapeType.ShapeGeneralPoint;
+ modifiers = 0;
+ break;
+ case ShapeType.ShapePointZM:
+ generaltype = ShapeType.ShapeGeneralPoint;
+ modifiers = ShapeModifiers.ShapeHasZs
+ | (int) ShapeModifiers.ShapeHasMs;
+ break;
+ case ShapeType.ShapePointM:
+ generaltype = ShapeType.ShapeGeneralPoint;
+ modifiers = ShapeModifiers.ShapeHasMs;
+ break;
+ case ShapeType.ShapePointZ:
+ generaltype = ShapeType.ShapeGeneralPoint;
+ modifiers = ShapeModifiers.ShapeHasZs;
+ break;
+ case ShapeType.ShapeGeneralPoint:
+ generaltype = ShapeType.ShapeGeneralPoint;
+ modifiers = shapetype & ShapeModifiers.ShapeModifierMask;
+ break;
+
+ // Null Geometry
+ case ShapeType.ShapeNull:
+ return null;
+
+ default:
+ throw new GeometryException("invalid shape type");
+ }
+
+ switch (generaltype) {
+ case ShapeType.ShapeGeneralPolygon:
+ if (m_type != Geometry.GeometryType.Polygon
+ && m_type != Geometry.GeometryType.Unknown
+ && m_type != Geometry.GeometryType.Envelope)
+ throw new GeometryException("invalid shape type");
+ return importFromESRIShapeMultiPath(true, modifiers,
+ shapeBuffer);
+
+ case ShapeType.ShapeGeneralPolyline:
+ if (m_type != Geometry.GeometryType.Polyline
+ && m_type != Geometry.GeometryType.Unknown
+ && m_type != Geometry.GeometryType.Envelope)
+ throw new GeometryException("invalid shape type");
+ return importFromESRIShapeMultiPath(false, modifiers,
+ shapeBuffer);
+
+ case ShapeType.ShapeGeneralMultiPoint:
+ if (m_type != Geometry.GeometryType.MultiPoint
+ && m_type != Geometry.GeometryType.Unknown
+ && m_type != Geometry.GeometryType.Envelope)
+ throw new GeometryException("invalid shape type");
+ return importFromESRIShapeMultiPoint(modifiers, shapeBuffer);
+
+ case ShapeType.ShapeGeneralPoint:
+ if (m_type != Geometry.GeometryType.Point
+ && m_type != Geometry.GeometryType.MultiPoint
+ && m_type != Geometry.GeometryType.Unknown
+ && m_type != Geometry.GeometryType.Envelope)
+ throw new GeometryException("invalid shape type");
+ return importFromESRIShapePoint(modifiers, shapeBuffer);
+ }
+
+ return null;
+ } finally {
+ shapeBuffer.order(initialOrder);
+ }
+ }
+
+ private Geometry importFromESRIShapeMultiPath(boolean bPolygon,
+ int modifiers, ByteBuffer shapeBuffer) {
+ int offset = 4;
+
+ boolean bZs = (modifiers & (int) ShapeModifiers.ShapeHasZs) != 0;
+ boolean bMs = (modifiers & (int) ShapeModifiers.ShapeHasMs) != 0;
+ boolean bIDs = (modifiers & (int) ShapeModifiers.ShapeHasIDs) != 0;
+
+ boolean bHasAttributes = bZs || bMs || bIDs;
+ boolean bHasBadRings = false;
+
+ // read Envelope
+ double xmin = shapeBuffer.getDouble(offset);
+ offset += 8;
+ double ymin = shapeBuffer.getDouble(offset);
+ offset += 8;
+ double xmax = shapeBuffer.getDouble(offset);
+ offset += 8;
+ double ymax = shapeBuffer.getDouble(offset);
+ offset += 8;
+
+ // read part count
+ int originalPartCount = shapeBuffer.getInt(offset);
+ offset += 4;
+ int partCount = 0;
+
+ // read point count
+ int pointCount = shapeBuffer.getInt(offset);
+ offset += 4;
+
+ AttributeStreamOfDbl position = null;
+ AttributeStreamOfDbl zs = null;
+ AttributeStreamOfDbl ms = null;
+ AttributeStreamOfInt32 ids = null;
+ AttributeStreamOfInt32 parts = null;
+ AttributeStreamOfInt8 pathFlags = null;
+
+ Envelope bbox = null;
+ MultiPath multipath = null;
+ MultiPathImpl multipathImpl = null;
+ if (m_type == Geometry.GeometryType.Polygon
+ || m_type == Geometry.GeometryType.Polyline
+ || m_type == Geometry.GeometryType.Unknown) {
+ if (bPolygon)
+ multipath = new Polygon();
+ else
+ multipath = new Polyline();
+
+ multipathImpl = (MultiPathImpl) multipath._getImpl();
+
+ if (pointCount > 0) {
+ bbox = new Envelope();
+ bbox.setCoords(xmin, ymin, xmax, ymax);
+ parts = (AttributeStreamOfInt32) AttributeStreamBase
+ .createIndexStream(originalPartCount + 1);
+
+ int previstart = -1;
+ int lastCount = 0;
+ for (int i = 0; i < originalPartCount; i++) {
+ int istart = shapeBuffer.getInt(offset);
+ offset += 4;
+ lastCount = istart;
+ if (previstart > istart || istart < 0)// check that the part
+ // indices in the
+ // buffer are not
+ // corrupted
+ throw new GeometryException("corrupted geometry");
+
+ if (istart != previstart) {
+ parts.write(partCount, istart);
+ previstart = istart;
+ partCount++;
+ }
+ }
+
+ parts.resize(partCount + 1);
+ if (pointCount < lastCount)// check that the point count in the
+ // buffer is not corrupted
+ throw new GeometryException("corrupted geometry");
+
+ parts.write(partCount, pointCount);
+ pathFlags = (AttributeStreamOfInt8) AttributeStreamBase
+ .createByteStream(parts.size(), (byte) 0);
+
+ // Create empty position stream
+ position = (AttributeStreamOfDbl) AttributeStreamBase
+ .createAttributeStreamWithSemantics(Semantics.POSITION,
+ pointCount);
+
+ int startpart = parts.read(0);
+ // read xy coordinates
+ int xyindex = 0;
+ for (int ipart = 0; ipart < partCount; ipart++) {
+ int endpartActual = parts.read(ipart + 1);
+ // for polygons we read one point less, then analyze if the
+ // polygon is closed.
+ int endpart = (bPolygon) ? endpartActual - 1
+ : endpartActual;
+
+ double startx = shapeBuffer.getDouble(offset);
+ offset += 8;
+ double starty = shapeBuffer.getDouble(offset);
+ offset += 8;
+ position.write(2 * xyindex, startx);
+ position.write(2 * xyindex + 1, starty);
+ xyindex++;
+
+ for (int i = startpart + 1; i < endpart; i++) {
+ double x = shapeBuffer.getDouble(offset);
+ offset += 8;
+ double y = shapeBuffer.getDouble(offset);
+ offset += 8;
+ position.write(2 * xyindex, x);
+ position.write(2 * xyindex + 1, y);
+ xyindex++;
+ }
+
+ if (endpart - startpart < 2) {// a part with only one point
+ multipathImpl.setIsSimple(GeometryXSimple.Unknown, 0.0,
+ false);
+ }
+
+ if (bPolygon) {// read the last point of the part to decide
+ // if we need to close the polygon
+ if (startpart == endpart) {// a part with only one point
+ parts.write(ipart + 1, xyindex);
+ } else {
+ double x = shapeBuffer.getDouble(offset);
+ offset += 8;
+ double y = shapeBuffer.getDouble(offset);
+ offset += 8;
+
+ if (x != startx || y != starty) {// bad polygon. The
+ // last point is
+ // not the same
+ // as the last
+ // one. We need
+ // to add it so
+ // that we do
+ // not loose it.
+ position.write(2 * xyindex, x);
+ position.write(2 * xyindex + 1, y);
+ xyindex++;
+ multipathImpl.setIsSimple(
+ GeometryXSimple.Unknown, 0.0, false);
+ bHasBadRings = true;
+ // write part count to indicate we need to
+ // account for one extra point
+ // The count will be fixed after the attributes
+ // are processed. So we write negative only when
+ // there are attributes.
+ parts.write(ipart + 1,
+ bHasAttributes ? -xyindex : xyindex);
+ } else
+ parts.write(ipart + 1, xyindex);
+ }
+
+ pathFlags.setBits(ipart, (byte) PathFlags.enumClosed);
+ }
+
+ startpart = endpartActual;
+ }
+
+ if (bZs)
+ bbox.addAttribute(Semantics.Z);
+
+ if (bMs)
+ bbox.addAttribute(Semantics.M);
+
+ if (bIDs)
+ bbox.addAttribute(Semantics.ID);
+ }
+ } else {
+ bbox = new Envelope();
+
+ if (bZs)
+ bbox.addAttribute(Semantics.Z);
+
+ if (bMs)
+ bbox.addAttribute(Semantics.M);
+
+ if (bIDs)
+ bbox.addAttribute(Semantics.ID);
+
+ if (pointCount > 0) {
+ bbox.setCoords(xmin, ymin, xmax, ymax);
+ offset += pointCount * 16 + originalPartCount * 4;
+ } else
+ return (Geometry) bbox;
+ }
+
+ // read Zs
+ if (bZs) {
+ if (pointCount > 0) {
+ double zmin = Interop.translateFromAVNaN(shapeBuffer
+ .getDouble(offset));
+ offset += 8;
+ double zmax = Interop.translateFromAVNaN(shapeBuffer
+ .getDouble(offset));
+ offset += 8;
+
+ Envelope1D env = new Envelope1D();
+ env.setCoords(zmin, zmax);
+ bbox.setInterval(Semantics.Z, 0, env);
+
+ if (m_type == Geometry.GeometryType.Polygon
+ || m_type == Geometry.GeometryType.Polyline
+ || m_type == Geometry.GeometryType.Unknown) {
+ zs = (AttributeStreamOfDbl) AttributeStreamBase
+ .createAttributeStreamWithSemantics(Semantics.Z,
+ pointCount);
+
+ boolean bCreate = false;
+ int startpart = parts.read(0);
+ for (int ipart = 0; ipart < partCount; ipart++) {
+ int endpartActual = parts.read(ipart + 1);
+ int endpart = Math.abs(endpartActual);
+
+ double startz = Interop.translateFromAVNaN(shapeBuffer
+ .getDouble(offset));
+ offset += 8;
+ zs.write(startpart, startz);
+ if (!VertexDescription.isDefaultValue(Semantics.Z,
+ startz))
+ bCreate = true;
+
+ for (int i = startpart + 1; i < endpart; i++) {
+ double z = Interop.translateFromAVNaN(shapeBuffer
+ .getDouble(offset));
+ offset += 8;
+ zs.write(i, z);
+ if (!VertexDescription.isDefaultValue(Semantics.Z,
+ z))
+ bCreate = true;
+ }
+
+ if (bPolygon && endpartActual > 0) {
+ offset += 8;
+ }
+
+ startpart = endpart;
+ }
+
+ if (!bCreate)
+ zs = null;
+ } else
+ offset += pointCount * 8;
+ }
+
+ if (m_type == Geometry.GeometryType.Polygon
+ || m_type == Geometry.GeometryType.Polyline
+ || m_type == Geometry.GeometryType.Unknown)
+ multipathImpl.setAttributeStreamRef(Semantics.Z, zs);
+ }
+
+ // read Ms
+ if (bMs) {
+ if (pointCount > 0) {
+ double mmin = Interop.translateFromAVNaN(shapeBuffer
+ .getDouble(offset));
+ offset += 8;
+ double mmax = Interop.translateFromAVNaN(shapeBuffer
+ .getDouble(offset));
+ offset += 8;
+
+ Envelope1D env = new Envelope1D();
+ env.setCoords(mmin, mmax);
+ bbox.setInterval(Semantics.M, 0, env);
+
+ if (m_type == Geometry.GeometryType.Polygon
+ || m_type == Geometry.GeometryType.Polyline
+ || m_type == Geometry.GeometryType.Unknown) {
+ ms = (AttributeStreamOfDbl) AttributeStreamBase
+ .createAttributeStreamWithSemantics(Semantics.M,
+ pointCount);
+
+ boolean bCreate = false;
+ int startpart = parts.read(0);
+ for (int ipart = 0; ipart < partCount; ipart++) {
+ int endpartActual = parts.read(ipart + 1);
+ int endpart = Math.abs(endpartActual);
+
+ double startm = Interop.translateFromAVNaN(shapeBuffer
+ .getDouble(offset));
+ offset += 8;
+ ms.write(startpart, startm);
+ if (!VertexDescription.isDefaultValue(Semantics.M,
+ startm))
+ bCreate = true;
+
+ for (int i = startpart + 1; i < endpart; i++) {
+ double m = Interop.translateFromAVNaN(shapeBuffer
+ .getDouble(offset));
+ offset += 8;
+ ms.write(i, m);
+ if (!VertexDescription.isDefaultValue(Semantics.M,
+ m))
+ bCreate = true;
+ }
+
+ if (bPolygon && endpartActual > 0) {
+ offset += 8;
+ }
+
+ startpart = endpart;
+ }
+
+ if (!bCreate)
+ ms = null;
+ } else
+ offset += pointCount * 8;
+ }
+
+ if (m_type == Geometry.GeometryType.Polygon
+ || m_type == Geometry.GeometryType.Polyline
+ || m_type == Geometry.GeometryType.Unknown)
+ multipathImpl.setAttributeStreamRef(Semantics.M, ms);
+ }
+
+ // read IDs
+ if (bIDs) {
+ if (pointCount > 0) {
+ double idmin = NumberUtils.doubleMax();
+ double idmax = -NumberUtils.doubleMax();
+
+ if (m_type == Geometry.GeometryType.Polygon
+ || m_type == Geometry.GeometryType.Polyline
+ || m_type == Geometry.GeometryType.Unknown) {
+ ids = (AttributeStreamOfInt32) AttributeStreamBase
+ .createAttributeStreamWithSemantics(Semantics.ID,
+ pointCount);
+
+ boolean bCreate = false;
+ int startpart = parts.read(0);
+ for (int ipart = 0; ipart < partCount; ipart++) {
+ int endpartActual = parts.read(ipart + 1);
+ int endpart = Math.abs(endpartActual);
+
+ int startid = shapeBuffer.getInt(offset);
+ offset += 4;
+ ids.write(startpart, startid);
+ if (!VertexDescription.isDefaultValue(Semantics.ID,
+ startid))
+ bCreate = true;
+
+ for (int i = startpart + 1; i < endpart; i++) {
+ int id = shapeBuffer.getInt(offset);
+ offset += 4;
+ ids.write(i, id);
+ if (!bCreate
+ && !VertexDescription.isDefaultValue(
+ Semantics.ID, id))
+ bCreate = true;
+
+ if (idmin > id)
+ idmin = id;
+ else if (idmax < id)
+ idmax = id;
+ }
+
+ if (bPolygon && endpartActual > 0) {
+ offset += 4;
+ }
+
+ startpart = endpart;
+ }
+
+ if (!bCreate)
+ ids = null;
+ } else {
+ for (int i = 0; i < pointCount; i++) {
+ int id = shapeBuffer.getInt(offset);
+ offset += 4;
+
+ if (idmin > id)
+ idmin = id;
+ else if (idmax < id)
+ idmax = id;
+ }
+ }
+
+ Envelope1D env = new Envelope1D();
+ env.setCoords(idmin, idmax);
+ bbox.setInterval(Semantics.ID, 0, env);
+ }
+
+ if (m_type == Geometry.GeometryType.Polygon
+ || m_type == Geometry.GeometryType.Polyline
+ || m_type == Geometry.GeometryType.Unknown)
+ multipathImpl.setAttributeStreamRef(Semantics.ID, ids);
+ }
+
+ if (bHasBadRings && bHasAttributes) {// revert our hack for bad polygons
+ for (int ipart = 1; ipart < partCount + 1; ipart++) {
+ int v = parts.read(ipart);
+ if (v < 0)
+ parts.write(ipart, -v);
+ }
+ }
+
+ if (m_type == Geometry.GeometryType.Envelope)
+ return (Geometry) bbox;
+
+ if (pointCount > 0) {
+ multipathImpl.setPathStreamRef(parts);
+ multipathImpl.setPathFlagsStreamRef(pathFlags);
+ multipathImpl.setAttributeStreamRef(Semantics.POSITION, position);
+ multipathImpl.setEnvelope(bbox);
+ }
+
+ if ((m_importFlags & ShapeImportFlags.ShapeImportNonTrusted) == 0)
+ multipathImpl.setIsSimple(GeometryXSimple.Weak, 0.0, false);// We
+ // use
+ // tolerance
+ // of 0.
+ // What
+ // should
+ // we
+ // instead?
+
+ return (Geometry) multipath;
+ }
+
+ private Geometry importFromESRIShapeMultiPoint(int modifiers,
+ ByteBuffer shapeBuffer) {
+ int offset = 4;
+
+ boolean bZs = (modifiers & (int) ShapeModifiers.ShapeHasZs) != 0;
+ boolean bMs = (modifiers & (int) ShapeModifiers.ShapeHasMs) != 0;
+ boolean bIDs = (modifiers & modifiers & (int) ShapeModifiers.ShapeHasIDs) != 0;
+
+ double xmin = shapeBuffer.getDouble(offset);
+ offset += 8;
+ double ymin = shapeBuffer.getDouble(offset);
+ offset += 8;
+ double xmax = shapeBuffer.getDouble(offset);
+ offset += 8;
+ double ymax = shapeBuffer.getDouble(offset);
+ offset += 8;
+
+ int cPoints = shapeBuffer.getInt(offset);
+ offset += 4;
+
+ AttributeStreamOfDbl position = null;
+ AttributeStreamOfDbl zs = null;
+ AttributeStreamOfDbl ms = null;
+ AttributeStreamOfInt32 ids = null;
+
+ Envelope bbox = null;
+ MultiPoint multipoint = null;
+ MultiPointImpl multipointImpl = null;
+
+ if (m_type == Geometry.GeometryType.MultiPoint
+ || m_type == Geometry.GeometryType.Unknown) {
+ multipoint = new MultiPoint();
+ multipointImpl = (MultiPointImpl) multipoint._getImpl();
+
+ if (cPoints > 0) {
+ bbox = new Envelope();
+ multipointImpl.resize(cPoints);
+ position = (AttributeStreamOfDbl) AttributeStreamBase
+ .createAttributeStreamWithSemantics(Semantics.POSITION,
+ cPoints);
+
+ for (int i = 0; i < cPoints; i++) {
+ double x = shapeBuffer.getDouble(offset);
+ offset += 8;
+ double y = shapeBuffer.getDouble(offset);
+ offset += 8;
+ position.write(2 * i, x);
+ position.write(2 * i + 1, y);
+ }
+
+ multipointImpl.resize(cPoints);
+ bbox.setCoords(xmin, ymin, xmax, ymax);
+
+ if (bZs)
+ bbox.addAttribute(Semantics.Z);
+
+ if (bMs)
+ bbox.addAttribute(Semantics.M);
+
+ if (bIDs)
+ bbox.addAttribute(Semantics.ID);
+ }
+ } else {
+ bbox = new Envelope();
+
+ if (bZs)
+ bbox.addAttribute(Semantics.Z);
+
+ if (bMs)
+ bbox.addAttribute(Semantics.M);
+
+ if (bIDs)
+ bbox.addAttribute(Semantics.ID);
+
+ if (cPoints > 0) {
+ bbox.setCoords(xmin, ymin, xmax, ymax);
+ offset += cPoints * 16;
+ } else
+ return (Geometry) bbox;
+ }
+
+ if (bZs) {
+ if (cPoints > 0) {
+ double zmin = Interop.translateFromAVNaN(shapeBuffer
+ .getDouble(offset));
+ offset += 8;
+ double zmax = Interop.translateFromAVNaN(shapeBuffer
+ .getDouble(offset));
+ offset += 8;
+
+ Envelope1D env = new Envelope1D();
+ env.setCoords(zmin, zmax);
+ bbox.setInterval(Semantics.Z, 0, env);
+
+ if (m_type == Geometry.GeometryType.MultiPoint
+ || m_type == Geometry.GeometryType.Unknown) {
+ zs = (AttributeStreamOfDbl) AttributeStreamBase
+ .createAttributeStreamWithSemantics(Semantics.Z,
+ cPoints);
+
+ boolean bCreate = false;
+ for (int i = 0; i < cPoints; i++) {
+ double value = Interop.translateFromAVNaN(shapeBuffer
+ .getDouble(offset));
+ offset += 8;
+ zs.write(i, value);
+ if (!VertexDescription.isDefaultValue(Semantics.Z,
+ value))
+ bCreate = true;
+ }
+
+ if (!bCreate)
+ zs = null;
+ } else
+ offset += cPoints * 8;
+ }
+
+ if (m_type == Geometry.GeometryType.MultiPoint
+ || m_type == Geometry.GeometryType.Unknown)
+ multipointImpl.setAttributeStreamRef(Semantics.Z, zs);
+ }
+
+ if (bMs) {
+ if (cPoints > 0) {
+ double mmin = Interop.translateFromAVNaN(shapeBuffer
+ .getDouble(offset));
+ offset += 8;
+ double mmax = Interop.translateFromAVNaN(shapeBuffer
+ .getDouble(offset));
+ offset += 8;
+
+ Envelope1D env = new Envelope1D();
+ env.setCoords(mmin, mmax);
+ bbox.setInterval(Semantics.M, 0, env);
+ if (m_type == Geometry.GeometryType.MultiPoint
+ || m_type == Geometry.GeometryType.Unknown) {
+ ms = (AttributeStreamOfDbl) AttributeStreamBase
+ .createAttributeStreamWithSemantics(Semantics.M,
+ cPoints);
+
+ boolean bCreate = false;
+ for (int i = 0; i < cPoints; i++) {
+ double value = Interop.translateFromAVNaN(shapeBuffer
+ .getDouble(offset));
+ offset += 8;
+ ms.write(i, value);
+ if (!VertexDescription.isDefaultValue(Semantics.M,
+ value))
+ bCreate = true;
+ }
+
+ if (!bCreate)
+ ms = null;
+ } else
+ offset += cPoints * 8;
+ }
+
+ if (m_type == Geometry.GeometryType.MultiPoint
+ || m_type == Geometry.GeometryType.Unknown)
+ multipointImpl.setAttributeStreamRef(Semantics.M, ms);
+ }
+
+ if (bIDs) {
+ if (cPoints > 0) {
+ double idmin = NumberUtils.doubleMax();
+ double idmax = -NumberUtils.doubleMax();
+
+ if (m_type == Geometry.GeometryType.MultiPoint
+ || m_type == Geometry.GeometryType.Unknown) {
+ ids = (AttributeStreamOfInt32) AttributeStreamBase
+ .createAttributeStreamWithSemantics(Semantics.ID,
+ cPoints);
+
+ boolean bCreate = false;
+ for (int i = 0; i < cPoints; i++) {
+ int value = shapeBuffer.getInt(offset);
+ offset += 4;
+ ids.write(i, value);
+ if (!VertexDescription.isDefaultValue(Semantics.ID,
+ value))
+ bCreate = true;
+
+ if (idmin > value)
+ idmin = value;
+ else if (idmax < value)
+ idmax = value;
+ }
+
+ if (!bCreate)
+ ids = null;
+ } else {
+ for (int i = 0; i < cPoints; i++) {
+ int id = shapeBuffer.getInt(offset);
+ offset += 4;
+
+ if (idmin > id)
+ idmin = id;
+ else if (idmax < id)
+ idmax = id;
+ }
+ }
+
+ Envelope1D env = new Envelope1D();
+ env.setCoords(idmin, idmax);
+ bbox.setInterval(Semantics.ID, 0, env);
+ }
+
+ if (m_type == Geometry.GeometryType.MultiPoint
+ || m_type == Geometry.GeometryType.Unknown)
+ multipointImpl.setAttributeStreamRef(Semantics.ID, ids);
+ }
+
+ if (m_type == Geometry.GeometryType.Envelope)
+ return (Geometry) bbox;
+
+ if (cPoints > 0) {
+ multipointImpl.setAttributeStreamRef(Semantics.POSITION, position);
+ multipointImpl.setEnvelope(bbox);
+ }
+
+ return (Geometry) multipoint;
+ }
+
+ private Geometry importFromESRIShapePoint(int modifiers,
+ ByteBuffer shapeBuffer) {
+ int offset = 4;
+
+ boolean bZs = (modifiers & (int) ShapeModifiers.ShapeHasZs) != 0;
+ boolean bMs = (modifiers & (int) ShapeModifiers.ShapeHasMs) != 0;
+ boolean bIDs = (modifiers & modifiers & (int) ShapeModifiers.ShapeHasIDs) != 0;
+
+ // read XY
+ double x = shapeBuffer.getDouble(offset);
+ offset += 8;
+ double y = shapeBuffer.getDouble(offset);
+ offset += 8;
+
+ boolean bEmpty = NumberUtils.isNaN(x);
+
+ double z = NumberUtils.NaN();
+ if (bZs) {
+ z = Interop.translateFromAVNaN(shapeBuffer.getDouble(offset));
+ offset += 8;
+ }
+
+ double m = NumberUtils.NaN();
+ if (bMs) {
+ m = Interop.translateFromAVNaN(shapeBuffer.getDouble(offset));
+ offset += 8;
+ }
+
+ int id = -1;
+ if (bIDs) {
+ id = shapeBuffer.getInt(offset);
+ offset += 4;
+ }
+
+ if (m_type == Geometry.GeometryType.MultiPoint) {
+ MultiPoint newmultipoint = new MultiPoint();
+ MultiPointImpl multipointImpl = (MultiPointImpl) newmultipoint
+ ._getImpl();
+
+ if (!bEmpty) {
+ AttributeStreamBase newPositionStream = AttributeStreamBase
+ .createAttributeStreamWithSemantics(Semantics.POSITION,
+ 1);
+ AttributeStreamOfDbl position = (AttributeStreamOfDbl) newPositionStream;
+ position.write(0, x);
+ position.write(1, y);
+
+ multipointImpl.setAttributeStreamRef(Semantics.POSITION,
+ newPositionStream);
+ multipointImpl.resize(1);
+ }
+
+ if (bZs) {
+ multipointImpl.addAttribute(Semantics.Z);
+ if (!bEmpty
+ && !VertexDescription.isDefaultValue(Semantics.Z, z)) {
+ AttributeStreamBase newZStream = AttributeStreamBase
+ .createAttributeStreamWithSemantics(Semantics.Z, 1);
+ newZStream.writeAsDbl(0, z);
+ multipointImpl.setAttributeStreamRef(Semantics.Z,
+ newZStream);
+ }
+ }
+
+ if (bMs) {
+ multipointImpl.addAttribute(Semantics.M);
+ if (!bEmpty
+ && !VertexDescription.isDefaultValue(Semantics.M, m)) {
+ AttributeStreamBase newMStream = AttributeStreamBase
+ .createAttributeStreamWithSemantics(Semantics.M, 1);
+ newMStream.writeAsDbl(0, m);
+ multipointImpl.setAttributeStreamRef(Semantics.M,
+ newMStream);
+ }
+ }
+
+ if (bIDs) {
+ multipointImpl.addAttribute(Semantics.ID);
+ if (!bEmpty
+ && !VertexDescription.isDefaultValue(Semantics.ID, id)) {
+ AttributeStreamBase newIDStream = AttributeStreamBase
+ .createAttributeStreamWithSemantics(Semantics.ID, 1);
+ newIDStream.writeAsInt(0, id);
+ multipointImpl.setAttributeStreamRef(Semantics.ID,
+ newIDStream);
+ }
+ }
+
+ return (Geometry) newmultipoint;
+ } else if (m_type == Geometry.GeometryType.Envelope) {
+ Envelope envelope = new Envelope();
+ envelope.setCoords(x, y, x, y);
+
+ if (bZs) {
+ Envelope1D interval = new Envelope1D();
+ interval.vmin = z;
+ interval.vmax = z;
+ envelope.addAttribute(Semantics.Z);
+ envelope.setInterval(Semantics.Z, 0, interval);
+ }
+
+ if (bMs) {
+ Envelope1D interval = new Envelope1D();
+ interval.vmin = m;
+ interval.vmax = m;
+ envelope.addAttribute(Semantics.M);
+ envelope.setInterval(Semantics.M, 0, interval);
+ }
+
+ if (bIDs) {
+ Envelope1D interval = new Envelope1D();
+ interval.vmin = id;
+ interval.vmax = id;
+ envelope.addAttribute(Semantics.ID);
+ envelope.setInterval(Semantics.ID, 0, interval);
+ }
+
+ return (Geometry) envelope;
+ }
+
+ Point point = new Point();
+
+ if (!bEmpty) {
+ point.setX(Interop.translateFromAVNaN(x));
+ point.setY(Interop.translateFromAVNaN(y));
+ }
+
+ // read Z
+ if (bZs) {
+ point.addAttribute(Semantics.Z);
+ if (!bEmpty)
+ point.setZ(Interop.translateFromAVNaN(z));
+ }
+
+ // read M
+ if (bMs) {
+ point.addAttribute(Semantics.M);
+ if (!bEmpty)
+ point.setM(Interop.translateFromAVNaN(m));
+ }
+
+ // read ID
+ if (bIDs) {
+ point.addAttribute(Semantics.ID);
+ if (!bEmpty)
+ point.setID(id);
+ }
+
+ return (Geometry) point;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorImportFromESRIShapeLocal.java b/src/main/java/com/esri/core/geometry/OperatorImportFromESRIShapeLocal.java
index 496e0605..ed7f959c 100644
--- a/src/main/java/com/esri/core/geometry/OperatorImportFromESRIShapeLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorImportFromESRIShapeLocal.java
@@ -31,16 +31,16 @@
*/
class OperatorImportFromESRIShapeLocal extends OperatorImportFromESRIShape {
- @Override
- public GeometryCursor execute(int importFlags, Geometry.Type type, ByteBufferCursor shapeBuffers) {
- return new OperatorImportFromESRIShapeCursor(importFlags, type.value(), shapeBuffers);
- }
-
- @Override
- public Geometry execute(int importFlags, Geometry.Type type, ByteBuffer shapeBuffer) {
- SimpleByteBufferCursor byteBufferCursor = new SimpleByteBufferCursor(shapeBuffer);
- GeometryCursor geometryCursor = execute(importFlags, type, byteBufferCursor);
-
- return geometryCursor.next();
- }
+ @Override
+ public GeometryCursor execute(int importFlags, Geometry.Type type, ByteBufferCursor shapeBuffers) {
+ return new OperatorImportFromESRIShapeCursor(importFlags, type.value(), shapeBuffers);
+ }
+
+ @Override
+ public Geometry execute(int importFlags, Geometry.Type type, ByteBuffer shapeBuffer) {
+ SimpleByteBufferCursor byteBufferCursor = new SimpleByteBufferCursor(shapeBuffer);
+ GeometryCursor geometryCursor = execute(importFlags, type, byteBufferCursor);
+
+ return geometryCursor.next();
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJson.java b/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJson.java
index 2eb37f61..d40a2373 100644
--- a/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJson.java
+++ b/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJson.java
@@ -25,48 +25,48 @@
public abstract class OperatorImportFromGeoJson extends Operator {
- @Override
- public Type getType() {
- return Type.ImportFromGeoJson;
- }
+ @Override
+ public Type getType() {
+ return Type.ImportFromGeoJson;
+ }
- // TODO, this was never implemented. Maybe remove?
+ // TODO, this was never implemented. Maybe remove?
// abstract MapGeometryCursor execute(int import_flags, String geoJsonString, ProgressTracker progressTracker);
- abstract MapGeometryCursor execute(int import_flags, StringCursor stringCursor, ProgressTracker progressTracker);
+ abstract MapGeometryCursor execute(int import_flags, StringCursor stringCursor, ProgressTracker progressTracker);
- /**
- * Performs the ImportFromGeoJson operation.
- *
- * @param type Use the {@link Geometry.Type} enum.
- * @param jsonObject The JSONObject holding the geometry and spatial reference.
- * @return Returns the imported MapGeometry.
- * @throws JsonGeometryException
- */
- public abstract MapGeometry execute(int importFlags, Geometry.Type type, JsonReader jsonReader, ProgressTracker progressTracker);
+ /**
+ * Performs the ImportFromGeoJson operation.
+ *
+ * @param type Use the {@link Geometry.Type} enum.
+ * @param jsonObject The JSONObject holding the geometry and spatial reference.
+ * @return Returns the imported MapGeometry.
+ * @throws JsonGeometryException
+ */
+ public abstract MapGeometry execute(int importFlags, Geometry.Type type, JsonReader jsonReader, ProgressTracker progressTracker);
- /**
- * Deprecated, use version without import_flags.
- *
- * Performs the ImportFromGeoJson operation.
- *
- * @param import_flags Use the {@link GeoJsonImportFlags} interface.
- * @param type Use the {@link Geometry.Type} enum.
- * @param geoJsonString The string holding the Geometry in geoJson format.
- * @return Returns the imported MapGeometry.
- */
- public abstract MapGeometry execute(int import_flags, Geometry.Type type, String geoJsonString, ProgressTracker progress_tracker);
+ /**
+ * Deprecated, use version without import_flags.
+ *
+ * Performs the ImportFromGeoJson operation.
+ *
+ * @param import_flags Use the {@link GeoJsonImportFlags} interface.
+ * @param type Use the {@link Geometry.Type} enum.
+ * @param geoJsonString The string holding the Geometry in geoJson format.
+ * @return Returns the imported MapGeometry.
+ */
+ public abstract MapGeometry execute(int import_flags, Geometry.Type type, String geoJsonString, ProgressTracker progress_tracker);
- /**
- * Performs the ImportFromGeoJson operation.
- *
- * @param import_flags Use the {@link GeoJsonImportFlags} interface.
- * @param geoJsonString The string holding the Geometry in geoJson format.
- * @return Returns the imported MapOGCStructure.
- */
- public abstract MapOGCStructure executeOGC(int import_flags, String geoJsonString, ProgressTracker progress_tracker);
+ /**
+ * Performs the ImportFromGeoJson operation.
+ *
+ * @param import_flags Use the {@link GeoJsonImportFlags} interface.
+ * @param geoJsonString The string holding the Geometry in geoJson format.
+ * @return Returns the imported MapOGCStructure.
+ */
+ public abstract MapOGCStructure executeOGC(int import_flags, String geoJsonString, ProgressTracker progress_tracker);
- public static OperatorImportFromGeoJson local() {
- return (OperatorImportFromGeoJson) OperatorFactoryLocal.getInstance().getOperator(Type.ImportFromGeoJson);
- }
+ public static OperatorImportFromGeoJson local() {
+ return (OperatorImportFromGeoJson) OperatorFactoryLocal.getInstance().getOperator(Type.ImportFromGeoJson);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJsonCursor.java b/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJsonCursor.java
index 17b4de98..152c7b4d 100644
--- a/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJsonCursor.java
+++ b/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJsonCursor.java
@@ -1,11 +1,11 @@
package com.esri.core.geometry;
public class OperatorImportFromGeoJsonCursor extends MapGeometryCursor {
- StringCursor m_jsonStringCursor;
- int m_import_flags;
- int m_count;
+ StringCursor m_jsonStringCursor;
+ int m_import_flags;
+ int m_count;
- // TODO, this was never implemented. Maybe remove?
+ // TODO, this was never implemented. Maybe remove?
// public OperatorImportFromGeoJsonCursor(int import_flags, String geoJsonString, ProgressTracker progressTracker) {
// m_geoJsonString = geoJsonString;
// m_import_flags = import_flags;
@@ -13,35 +13,39 @@ public class OperatorImportFromGeoJsonCursor extends MapGeometryCursor {
// m_count = 1;
// }
- public OperatorImportFromGeoJsonCursor(int import_flags, StringCursor stringCursor, ProgressTracker progressTracker) {
- m_jsonStringCursor = stringCursor;
- m_import_flags = import_flags;
- m_count = 1;
- }
-
- @Override
- public MapGeometry next() {
- String nextString;
- if ((nextString = m_jsonStringCursor.next()) != null) {
- JsonReader jsonReader = JsonParserReader.createFromString(nextString);
- return OperatorImportFromGeoJsonLocal.OperatorImportFromGeoJsonHelper.importFromGeoJson(m_import_flags, Geometry.Type.Unknown, jsonReader, null, false);
- }
- return null;
- }
-
- @Override
- public SimpleStateEnum getSimpleState() { return m_jsonStringCursor.getSimpleState(); }
-
- @Override
- public String getFeatureID() { return m_jsonStringCursor.getFeatureID(); }
-
- @Override
- public long getGeometryID() {
- return m_jsonStringCursor.getID();
- }
-
- @Override
- public boolean hasNext() {
- return m_jsonStringCursor != null && m_jsonStringCursor.hasNext();
- }
+ public OperatorImportFromGeoJsonCursor(int import_flags, StringCursor stringCursor, ProgressTracker progressTracker) {
+ m_jsonStringCursor = stringCursor;
+ m_import_flags = import_flags;
+ m_count = 1;
+ }
+
+ @Override
+ public MapGeometry next() {
+ String nextString;
+ if ((nextString = m_jsonStringCursor.next()) != null) {
+ JsonReader jsonReader = JsonParserReader.createFromString(nextString);
+ return OperatorImportFromGeoJsonLocal.OperatorImportFromGeoJsonHelper.importFromGeoJson(m_import_flags, Geometry.Type.Unknown, jsonReader, null, false);
+ }
+ return null;
+ }
+
+ @Override
+ public SimpleStateEnum getSimpleState() {
+ return m_jsonStringCursor.getSimpleState();
+ }
+
+ @Override
+ public String getFeatureID() {
+ return m_jsonStringCursor.getFeatureID();
+ }
+
+ @Override
+ public long getGeometryID() {
+ return m_jsonStringCursor.getID();
+ }
+
+ @Override
+ public boolean hasNext() {
+ return m_jsonStringCursor != null && m_jsonStringCursor.hasNext();
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJsonLocal.java b/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJsonLocal.java
index 2e3c78aa..4df7676b 100644
--- a/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJsonLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorImportFromGeoJsonLocal.java
@@ -28,1305 +28,1305 @@
import java.util.ArrayList;
class OperatorImportFromGeoJsonLocal extends OperatorImportFromGeoJson {
- static enum GeoJsonType {
- Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, GeometryCollection;
-
- static GeoJsonType fromGeoJsonValue(int v) {
- return GeoJsonType.values()[v - 1];
- }
-
- public int geogsjonvalue() {
- return ordinal() + 1;
- }
- }
-
- static interface GeoJsonValues {
- public final static int Point = GeoJsonType.Point.geogsjonvalue();
- public final static int LineString = GeoJsonType.LineString.geogsjonvalue();
- public final static int Polygon = GeoJsonType.Polygon.geogsjonvalue();
- public final static int MultiPoint = GeoJsonType.MultiPoint.geogsjonvalue();
- public final static int MultiLineString = GeoJsonType.MultiLineString.geogsjonvalue();
- public final static int MultiPolygon = GeoJsonType.MultiPolygon.geogsjonvalue();
- public final static int GeometryCollection = GeoJsonType.GeometryCollection.geogsjonvalue();
- }
-
-
- // TODO, this was never implemented. Maybe remove?
+ static enum GeoJsonType {
+ Point, LineString, Polygon, MultiPoint, MultiLineString, MultiPolygon, GeometryCollection;
+
+ static GeoJsonType fromGeoJsonValue(int v) {
+ return GeoJsonType.values()[v - 1];
+ }
+
+ public int geogsjonvalue() {
+ return ordinal() + 1;
+ }
+ }
+
+ static interface GeoJsonValues {
+ public final static int Point = GeoJsonType.Point.geogsjonvalue();
+ public final static int LineString = GeoJsonType.LineString.geogsjonvalue();
+ public final static int Polygon = GeoJsonType.Polygon.geogsjonvalue();
+ public final static int MultiPoint = GeoJsonType.MultiPoint.geogsjonvalue();
+ public final static int MultiLineString = GeoJsonType.MultiLineString.geogsjonvalue();
+ public final static int MultiPolygon = GeoJsonType.MultiPolygon.geogsjonvalue();
+ public final static int GeometryCollection = GeoJsonType.GeometryCollection.geogsjonvalue();
+ }
+
+
+ // TODO, this was never implemented. Maybe remove?
// @Override
// MapGeometryCursor execute(int import_flags, String geoJsonString, ProgressTracker progressTracker) {
// return new OperatorImportFromGeoJsonCursor(import_flags, geoJsonString, progressTracker);
// }
- @Override
- MapGeometryCursor execute(int import_flags, StringCursor stringCursor, ProgressTracker progressTracker) {
- return new OperatorImportFromGeoJsonCursor(import_flags, stringCursor, progressTracker);
- }
-
- @Override
- public MapGeometry execute(int importFlags, Geometry.Type type,
- String geoJsonString, ProgressTracker progressTracker)
- throws JsonGeometryException {
- MapGeometry map_geometry = OperatorImportFromGeoJsonHelper
- .importFromGeoJson(importFlags, type, JsonParserReader.createFromString(geoJsonString), progressTracker, false);
- return map_geometry;
- }
-
- @Override
- public MapGeometry execute(int importFlags, Geometry.Type type,
- JsonReader jsonReader, ProgressTracker progressTracker)
- throws JsonGeometryException {
- if (jsonReader == null)
- return null;
-
- return OperatorImportFromGeoJsonHelper.importFromGeoJson(importFlags,
- type, jsonReader, progressTracker, false);
- }
-
- static final class OperatorImportFromGeoJsonHelper {
-
- private AttributeStreamOfDbl m_position;
- private AttributeStreamOfDbl m_zs;
- private AttributeStreamOfDbl m_ms;
- private AttributeStreamOfInt32 m_paths;
- private AttributeStreamOfInt8 m_path_flags;
- private Point m_point; // special case for Points
- private boolean m_b_has_zs;
- private boolean m_b_has_ms;
- private boolean m_b_has_zs_known;
- private boolean m_b_has_ms_known;
- private int m_num_embeddings;
-
- int m_ogcType;
-
- OperatorImportFromGeoJsonHelper() {
- m_position = null;
- m_zs = null;
- m_ms = null;
- m_paths = null;
- m_path_flags = null;
- m_point = null;
- m_b_has_zs = false;
- m_b_has_ms = false;
- m_b_has_zs_known = false;
- m_b_has_ms_known = false;
- m_num_embeddings = 0;
- m_ogcType = 0;
- }
-
- static MapGeometry importFromGeoJson(int importFlags,
- Geometry.Type type, JsonReader json_iterator,
- ProgressTracker progress_tracker, boolean skip_coordinates)
- throws JsonGeometryException {
- OperatorImportFromGeoJsonHelper geo_json_helper = new OperatorImportFromGeoJsonHelper();
- MapOGCStructure ms = geo_json_helper.importFromGeoJsonImpl(
- importFlags, type, json_iterator, progress_tracker,
- skip_coordinates, 0);
-
- if (geo_json_helper.m_ogcType == GeoJsonValues.GeometryCollection && !skip_coordinates)
- throw new JsonGeometryException("parsing error");
-
- return new MapGeometry(ms.m_ogcStructure.m_geometry,
- ms.m_spatialReference);
- }
-
- static MapOGCStructure importFromGeoJson(int importFlags,
- Geometry.Type type, JsonReader json_iterator,
- ProgressTracker progress_tracker, boolean skip_coordinates,
- int recursion) throws JsonGeometryException {
- OperatorImportFromGeoJsonHelper geo_json_helper = new OperatorImportFromGeoJsonHelper();
- MapOGCStructure ms = geo_json_helper.importFromGeoJsonImpl(
- importFlags, type, json_iterator, progress_tracker,
- skip_coordinates, recursion);
-
- if (geo_json_helper.m_ogcType == GeoJsonValues.GeometryCollection && !skip_coordinates)
- throw new JsonGeometryException("parsing error");
-
- return ms;
- }
-
- MapOGCStructure importFromGeoJsonImpl(int importFlags,
- Geometry.Type type, JsonReader json_iterator,
- ProgressTracker progress_tracker, boolean skip_coordinates,
- int recursion) throws JsonGeometryException {
- OperatorImportFromGeoJsonHelper geo_json_helper = this;
- boolean b_type_found = false;
- boolean b_coordinates_found = false;
- boolean b_crs_found = false;
- boolean b_crsURN_found = false;
- boolean b_geometry_collection = false;
- boolean b_geometries_found = false;
- GeoJsonType geo_json_type = null;
-
- Geometry geometry = null;
- SpatialReference spatial_reference = null;
-
- JsonReader.Token current_token;
- String field_name = null;
- MapOGCStructure ms = new MapOGCStructure();
-
- while ((current_token = json_iterator.nextToken()) != JsonReader.Token.END_OBJECT) {
- field_name = json_iterator.currentString();
-
- if (field_name.equals("type")) {
- if (b_type_found) {
- throw new JsonGeometryException("parsing error");
- }
-
- b_type_found = true;
- current_token = json_iterator.nextToken();
-
- if (current_token != JsonReader.Token.VALUE_STRING) {
- throw new JsonGeometryException("parsing error");
- }
-
- String s = json_iterator.currentString();
- try {
- geo_json_type = GeoJsonType.valueOf(s);
- } catch (Exception ex) {
- throw new JsonGeometryException(s);
- }
-
- if (geo_json_type == GeoJsonType.GeometryCollection) {
- if (type != Geometry.Type.Unknown)
- throw new JsonGeometryException("parsing error");
-
- b_geometry_collection = true;
- }
- } else if (field_name.equals("geometries")) {
- b_geometries_found = true;
- if (type != Geometry.Type.Unknown)
- throw new JsonGeometryException("parsing error");
-
- if (recursion > 10) {
- throw new JsonGeometryException("deep geojson");
- }
-
- if (skip_coordinates) {
- json_iterator.skipChildren();
- } else {
- current_token = json_iterator.nextToken();
-
- ms.m_ogcStructure = new OGCStructure();
- ms.m_ogcStructure.m_type = GeoJsonValues.GeometryCollection;
- ms.m_ogcStructure.m_structures = new ArrayList
- * The operator intersects every geometry in the inputGeometries with the first geometry of the intersector and returns the result.
- */
- public abstract GeometryCursor execute(GeometryCursor inputGeometries,
- GeometryCursor intersector, SpatialReference sr,
- ProgressTracker progressTracker);
+ /**
+ * Performs the Topological Intersection operation on the geometry set.
+ *
+ * @param inputGeometries is the set of Geometry instances to be intersected by the intersector.
+ * @param intersector is the intersector Geometry.
+ *
+ * The operator intersects every geometry in the inputGeometries with the first geometry of the intersector and returns the result.
+ */
+ public abstract GeometryCursor execute(GeometryCursor inputGeometries,
+ GeometryCursor intersector, SpatialReference sr,
+ ProgressTracker progressTracker);
- /**
- *Performs the Topological intersection operation on the geometry set.
- *@param input_geometries is the set of Geometry instances to be intersected by the intersector.
- *@param intersector is the intersector Geometry. Only single intersector is used, therefore, the intersector.next() is called only once.
- *@param sr The spatial reference is used to get tolerance value. Can be null, then the tolerance is not used and the operation is performed with
- *a small tolerance value just enough to make the operation robust.
- *@param progress_tracker Allows to cancel the operation. Can be null.
- *@param dimensionMask The dimension of the intersection. The value is either -1, or a bitmask mask of values (1 << dim).
- *The value of -1 means the lower dimension in the intersecting pair.
- *This is a fastest option when intersecting polygons with polygons or polylines.
- *The bitmask of values (1 << dim), where dim is the desired dimension value, is used to indicate
- *what dimensions of geometry one wants to be returned. For example, to return
- *multipoints and lines only, pass (1 << 0) | (1 << 1), which is equivalen to 1 | 2, or 3.
- *@return Returns the cursor of the intersection result. The cursors' getGeometryID method returns the current ID of the input geometry
- *being processed. When dimensionMask is a bitmask, there will be n result geometries per one input geometry returned, where n is the number
- *of bits set in the bitmask. For example, if the dimensionMask is 5, there will be two geometries per one input geometry.
- *
- *The operator intersects every geometry in the input_geometries with the first geometry of the intersector and returns the result.
- *
- *Note, when the dimensionMask is -1, then for each intersected pair of geometries,
- *the result has the lower of dimentions of the two geometries. That is, the dimension of the Polyline/Polyline intersection
- *is always 1 (that is, for polylines it never returns crossing points, but the overlaps only).
- *If dimensionMask is 7, the operation will return any possible intersections.
- */
- public abstract GeometryCursor execute(GeometryCursor input_geometries,
- GeometryCursor intersector, SpatialReference sr,
- ProgressTracker progress_tracker, int dimensionMask);
+ /**
+ * Performs the Topological intersection operation on the geometry set.
+ *
+ * @param input_geometries is the set of Geometry instances to be intersected by the intersector.
+ * @param intersector is the intersector Geometry. Only single intersector is used, therefore, the intersector.next() is called only once.
+ * @param sr The spatial reference is used to get tolerance value. Can be null, then the tolerance is not used and the operation is performed with
+ * a small tolerance value just enough to make the operation robust.
+ * @param progress_tracker Allows to cancel the operation. Can be null.
+ * @param dimensionMask The dimension of the intersection. The value is either -1, or a bitmask mask of values (1 << dim).
+ * The value of -1 means the lower dimension in the intersecting pair.
+ * This is a fastest option when intersecting polygons with polygons or polylines.
+ * The bitmask of values (1 << dim), where dim is the desired dimension value, is used to indicate
+ * what dimensions of geometry one wants to be returned. For example, to return
+ * multipoints and lines only, pass (1 << 0) | (1 << 1), which is equivalen to 1 | 2, or 3.
+ * @return Returns the cursor of the intersection result. The cursors' getGeometryID method returns the current ID of the input geometry
+ * being processed. When dimensionMask is a bitmask, there will be n result geometries per one input geometry returned, where n is the number
+ * of bits set in the bitmask. For example, if the dimensionMask is 5, there will be two geometries per one input geometry.
+ *
+ * The operator intersects every geometry in the input_geometries with the first geometry of the intersector and returns the result.
+ *
+ * Note, when the dimensionMask is -1, then for each intersected pair of geometries,
+ * the result has the lower of dimentions of the two geometries. That is, the dimension of the Polyline/Polyline intersection
+ * is always 1 (that is, for polylines it never returns crossing points, but the overlaps only).
+ * If dimensionMask is 7, the operation will return any possible intersections.
+ */
+ public abstract GeometryCursor execute(GeometryCursor input_geometries,
+ GeometryCursor intersector, SpatialReference sr,
+ ProgressTracker progress_tracker, int dimensionMask);
- /**
- *Performs the Topological Intersection operation on the geometry.
- *The result has the lower of dimentions of the two geometries. That is, the dimension of the
- *Polyline/Polyline intersection is always 1 (that is, for polylines it never returns crossing
- *points, but the overlaps only).
- *The call is equivalent to calling the overloaded method using cursors:
- *execute(new SimpleGeometryCursor(input_geometry), new SimpleGeometryCursor(intersector), sr, progress_tracker, mask).next();
- *where mask can be either -1 or min(1 << input_geometry.getDimension(), 1 << intersector.getDimension());
- *@param inputGeometry is the Geometry instance to be intersected by the intersector.
- *@param intersector is the intersector Geometry.
- *@param sr The spatial reference to get the tolerance value from. Can be null, then the tolerance is calculated from the input geometries.
- *@return Returns the intersected Geometry.
- */
- public abstract Geometry execute(Geometry inputGeometry,
- Geometry intersector, SpatialReference sr,
- ProgressTracker progressTracker);
+ /**
+ * Performs the Topological Intersection operation on the geometry.
+ * The result has the lower of dimentions of the two geometries. That is, the dimension of the
+ * Polyline/Polyline intersection is always 1 (that is, for polylines it never returns crossing
+ * points, but the overlaps only).
+ * The call is equivalent to calling the overloaded method using cursors:
+ * execute(new SimpleGeometryCursor(input_geometry), new SimpleGeometryCursor(intersector), sr, progress_tracker, mask).next();
+ * where mask can be either -1 or min(1 << input_geometry.getDimension(), 1 << intersector.getDimension());
+ *
+ * @param inputGeometry is the Geometry instance to be intersected by the intersector.
+ * @param intersector is the intersector Geometry.
+ * @param sr The spatial reference to get the tolerance value from. Can be null, then the tolerance is calculated from the input geometries.
+ * @return Returns the intersected Geometry.
+ */
+ public abstract Geometry execute(Geometry inputGeometry,
+ Geometry intersector, SpatialReference sr,
+ ProgressTracker progressTracker);
- public static OperatorIntersection local() {
- return (OperatorIntersection) OperatorFactoryLocal.getInstance()
- .getOperator(Type.Intersection);
- }
+ public static OperatorIntersection local() {
+ return (OperatorIntersection) OperatorFactoryLocal.getInstance()
+ .getOperator(Type.Intersection);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorIntersectionCursor.java b/src/main/java/com/esri/core/geometry/OperatorIntersectionCursor.java
index 223f36f9..5e23bc82 100644
--- a/src/main/java/com/esri/core/geometry/OperatorIntersectionCursor.java
+++ b/src/main/java/com/esri/core/geometry/OperatorIntersectionCursor.java
@@ -26,775 +26,775 @@
// TODO test this
public class OperatorIntersectionCursor extends GeometryCursor {
- GeometryCursor m_smallCursor;
- ProgressTracker m_progress_tracker;
- SpatialReference m_spatial_reference;
- Geometry m_geomIntersector;
- Geometry m_geomIntersectorEmptyGeom;// holds empty geometry of intersector
- // type.
- int m_geomIntersectorType;
- int m_currentGeomType;
- int m_dimensionMask;
- boolean m_bEmpty;
-
- OperatorIntersectionCursor(GeometryCursor inputGeoms,
- GeometryCursor geomIntersector,
- SpatialReference sr,
- ProgressTracker progress_tracker,
- int dimensionMask) {
- m_bEmpty = geomIntersector == null;
- m_inputGeoms = inputGeoms;
- m_spatial_reference = sr;
- m_geomIntersector = geomIntersector.next();
- m_geomIntersectorType = m_geomIntersector.getType().value();
- m_currentGeomType = Geometry.Type.Unknown.value();
- m_progress_tracker = progress_tracker;
- m_dimensionMask = dimensionMask;
- if (m_dimensionMask != -1
- && (m_dimensionMask <= 0 || m_dimensionMask > 7))
- throw new IllegalArgumentException("bad dimension mask");// dimension
- // mask
- // can
- // be
- // -1,
- // for
- // the
- // default
- // behavior,
- // or a
- // value
- // between
- // 1 and
- // 7.
- }
-
- @Override
- public Geometry next() {
- if (m_bEmpty)
- return null;
-
- Geometry geom;
- if (m_smallCursor != null && m_smallCursor.hasNext()) {// when dimension mask is used, we produce a
- geom = m_smallCursor.next();
- if (geom != null)
- return geom;
- else
- m_smallCursor = null;// done with the small cursor
- }
-
- if (m_inputGeoms.hasNext()) {
- geom = m_inputGeoms.next();
- if (m_dimensionMask == -1) {
- Geometry resGeom = intersect(geom);
- assert (resGeom != null);
- return resGeom;
- } else {
- m_smallCursor = intersectEx(geom);
- Geometry resGeom = m_smallCursor.next();
- assert (resGeom != null);
- return resGeom;
- }
- }
- return null;
- }
-
- Geometry intersect(Geometry input_geom) {
- Geometry dst_geom = tryNativeImplementation_(input_geom);
- if (dst_geom != null)
- return dst_geom;
-
- Envelope2D commonExtent = InternalUtils.getMergedExtent(
- m_geomIntersector, input_geom);
-
- // return Topological_operations::intersection(input_geom,
- // m_geomIntersector, m_spatial_reference, m_progress_tracker);
- // Preprocess geometries to be clipped to the extent of intersection to
- // get rid of extra segments.
- double t = InternalUtils.calculateToleranceFromGeometry(m_spatial_reference, commonExtent, true);
- Envelope2D env = new Envelope2D();
- m_geomIntersector.queryEnvelope2D(env);
- Envelope2D env1 = new Envelope2D();
- input_geom.queryEnvelope2D(env1);
- env.inflate(2.0 * t, 2.0 * t);
- env.intersect(env1);
- assert (!env.isEmpty());
- env.inflate(100 * t, 100 * t);
- double tol = 0;
- Geometry clippedIntersector = Clipper.clip(m_geomIntersector, env, tol,
- 0.0);
- Geometry clippedInputGeom = Clipper.clip(input_geom, env, tol, 0.0);
- // perform the clip
- return TopologicalOperations.intersection(clippedInputGeom,
- clippedIntersector, m_spatial_reference, m_progress_tracker);
- }
-
- // Parses the input vector to ensure the out result contains only geometries
- // as indicated with the dimensionMask
- GeometryCursor prepareVector_(VertexDescription descr, int dimensionMask,
- Geometry[] res_vec) {
- int inext = 0;
- if ((dimensionMask & 1) != 0) {
- if (res_vec[0] == null)
- res_vec[0] = new MultiPoint(descr);
- inext++;
- } else {
- for (int i = 0; i < res_vec.length - 1; i++)
- res_vec[i] = res_vec[i + 1];
- }
-
- if ((dimensionMask & 2) != 0) {
- if (res_vec[inext] == null)
- res_vec[inext] = new Polyline(descr);
- inext++;
- } else {
- for (int i = inext; i < res_vec.length - 1; i++)
- res_vec[i] = res_vec[i + 1];
- }
-
- if ((dimensionMask & 4) != 0) {
- if (res_vec[inext] == null)
- res_vec[inext] = new Polygon(descr);
- inext++;
- } else {
- for (int i = inext; i < res_vec.length - 1; i++)
- res_vec[i] = res_vec[i + 1];
- }
-
- if (inext != 3) {
- Geometry[] r = new Geometry[inext];
- for (int i = 0; i < inext; i++)
- r[i] = res_vec[i];
-
- return new SimpleGeometryCursor(r);
- } else {
- return new SimpleGeometryCursor(res_vec);
- }
- }
-
- GeometryCursor intersectEx(Geometry input_geom) {
- assert (m_dimensionMask != -1);
- Geometry dst_geom = tryNativeImplementation_(input_geom);
- if (dst_geom != null) {
- Geometry[] res_vec = new Geometry[3];
- res_vec[dst_geom.getDimension()] = dst_geom;
- return prepareVector_(input_geom.getDescription(), m_dimensionMask,
- res_vec);
- }
-
- Envelope2D commonExtent = InternalUtils.getMergedExtent(
- m_geomIntersector, input_geom);
- double t = InternalUtils.calculateToleranceFromGeometry(
- m_spatial_reference, commonExtent, true);
-
- // Preprocess geometries to be clipped to the extent of intersection to
- // get rid of extra segments.
-
- Envelope2D env = new Envelope2D();
- m_geomIntersector.queryEnvelope2D(env);
- env.inflate(2 * t, 2 * t);
- Envelope2D env1 = new Envelope2D();
- input_geom.queryEnvelope2D(env1);
- env.intersect(env1);
- assert (!env.isEmpty());
- env.inflate(100 * t, 100 * t);
- double tol = 0;
- Geometry clippedIntersector = Clipper.clip(m_geomIntersector, env, tol,
- 0.0);
- Geometry clippedInputGeom = Clipper.clip(input_geom, env, tol, 0.0);
- // perform the clip
- Geometry[] res_vec;
- res_vec = TopologicalOperations.intersectionEx(clippedInputGeom,
- clippedIntersector, m_spatial_reference, m_progress_tracker);
- return prepareVector_(input_geom.getDescription(), m_dimensionMask,
- res_vec);
- }
-
- Geometry tryNativeImplementation_(Geometry input_geom) {
- // A note on attributes:
- // 1. The geometry with lower dimension wins in regard to the
- // attributes.
- // 2. If the dimensions are the same, the input_geometry attributes win.
- // 3. The exception to the 2. is when the input is an Envelope, and the
- // intersector is a polygon, then the intersector wins.
-
- // A note on the tolerance:
- // This operator performs a simple intersection operation. Should it use
- // the tolerance?
- // Example: Point is intersected by the envelope.
- // If it is slightly outside of the envelope, should we still return it
- // if it is closer than the tolerance?
- // Should we do crack and cluster and snap the point coordinates to the
- // envelope boundary?
- //
- // Consider floating point arithmetics approach. When you compare
- // doubles, you should use an epsilon (equals means ::fabs(a - b) <
- // eps), however when you add/subtract, etc them, you do not use
- // epsilon.
- // Shouldn't we do same here? Relational operators use tolerance, but
- // the action operators don't.
-
- Envelope2D mergedExtent = InternalUtils.getMergedExtent(input_geom,
- m_geomIntersector);
- double tolerance = InternalUtils.calculateToleranceFromGeometry(
- m_spatial_reference, mergedExtent, false);
-
- int gtInput = input_geom.getType().value();
- boolean bInputEmpty = input_geom.isEmpty();
- boolean bGeomIntersectorEmpty = m_geomIntersector.isEmpty();
- boolean bResultIsEmpty = bInputEmpty || bGeomIntersectorEmpty;
- if (!bResultIsEmpty) {// test envelopes
- Envelope2D env2D1 = new Envelope2D();
- input_geom.queryEnvelope2D(env2D1);
- Envelope2D env2D2 = new Envelope2D();
- m_geomIntersector.queryEnvelope2D(env2D2);
- env2D2.inflate(2.0 * tolerance, 2.0 * tolerance);
- bResultIsEmpty = !env2D1.isIntersecting(env2D2);
- }
-
- if (!bResultIsEmpty) {// try accelerated test
- int res = OperatorInternalRelationUtils
- .quickTest2D_Accelerated_DisjointOrContains(
- m_geomIntersector, input_geom, tolerance);
- if (res == OperatorInternalRelationUtils.Relation.Disjoint) {// disjoint
- bResultIsEmpty = true;
- } else if ((res & OperatorInternalRelationUtils.Relation.Within) != 0) {// intersector
- // is
- // within
- // the
- // input_geom
- // TODO:
- // assign
- // input_geom
- // attributes
- // first
- return m_geomIntersector;
- } else if ((res & OperatorInternalRelationUtils.Relation.Contains) != 0) {// intersector
- // contains
- // input_geom
- return input_geom;
- }
- }
-
- if (bResultIsEmpty) {// When one geometry or both are empty, we need to
- // return an empty geometry.
- // Here we do that end also ensure the type is
- // correct.
- // That is the lower dimension need to be
- // returned. Also, for Point vs Multi_point, an
- // empty Point need to be returned.
- int dim1 = Geometry.getDimensionFromType(gtInput);
- int dim2 = Geometry.getDimensionFromType(m_geomIntersectorType);
- if (dim1 < dim2)
- return returnEmpty_(input_geom, bInputEmpty);
- else if (dim1 > dim2)
- return returnEmptyIntersector_();
- else if (dim1 == 0) {
- if (gtInput == Geometry.GeometryType.MultiPoint
- && m_geomIntersectorType == Geometry.GeometryType.Point) {// point
- // vs
- // Multi_point
- // need
- // special
- // treatment
- // to
- // ensure
- // Point
- // is
- // returned
- // always.
- return returnEmptyIntersector_();
- } else
- // Both input and intersector have same gtype, or input is
- // Point.
- return returnEmpty_(input_geom, bInputEmpty);
- } else
- return returnEmpty_(input_geom, bInputEmpty);
- }
-
- // Note: No empty geometries after this point!
-
- // Warning: Do not try clip for polylines and polygons.
-
- // Try clip of Envelope with Envelope.
- if ((m_dimensionMask == -1 || m_dimensionMask == (1 << 2))
- && gtInput == Geometry.GeometryType.Envelope
- && m_geomIntersectorType == Geometry.GeometryType.Envelope) {
- Envelope env1 = (Envelope) input_geom;
- Envelope env2 = (Envelope) m_geomIntersector;
- Envelope2D env2D_1 = new Envelope2D();
- env1.queryEnvelope2D(env2D_1);
- Envelope2D env2D_2 = new Envelope2D();
- env2.queryEnvelope2D(env2D_2);
- env2D_1.intersect(env2D_2);
- Envelope result_env = new Envelope();
- env1.copyTo(result_env);
- result_env.setEnvelope2D(env2D_1);
- return result_env;
- }
-
- // Use clip for Point and Multi_point with Envelope
- if ((gtInput == Geometry.GeometryType.Envelope && Geometry
- .getDimensionFromType(m_geomIntersectorType) == 0)
- || (m_geomIntersectorType == Geometry.GeometryType.Envelope && Geometry
- .getDimensionFromType(gtInput) == 0)) {
- Envelope env = gtInput == Geometry.GeometryType.Envelope ? (Envelope) input_geom
- : (Envelope) m_geomIntersector;
- Geometry other = gtInput == Geometry.GeometryType.Envelope ? m_geomIntersector
- : input_geom;
- Envelope2D env_2D = new Envelope2D();
- env.queryEnvelope2D(env_2D);
- return Clipper.clip(other, env_2D, tolerance, 0);
- }
-
- if ((Geometry.getDimensionFromType(gtInput) == 0 && Geometry
- .getDimensionFromType(m_geomIntersectorType) > 0)
- || (Geometry.getDimensionFromType(gtInput) > 0 && Geometry
- .getDimensionFromType(m_geomIntersectorType) == 0)) {// multipoint
- // intersection
- double tolerance1 = InternalUtils.calculateToleranceFromGeometry(
- m_spatial_reference, input_geom, false);
- if (gtInput == Geometry.GeometryType.MultiPoint)
- return TopologicalOperations.intersection(
- (MultiPoint) input_geom, m_geomIntersector, tolerance1);
- if (gtInput == Geometry.GeometryType.Point)
- return TopologicalOperations.intersection((Point) input_geom,
- m_geomIntersector, tolerance1);
- if (m_geomIntersectorType == Geometry.GeometryType.MultiPoint)
- return TopologicalOperations.intersection(
- (MultiPoint) m_geomIntersector, input_geom, tolerance1);
- if (m_geomIntersectorType == Geometry.GeometryType.Point)
- return TopologicalOperations.intersection(
- (Point) m_geomIntersector, input_geom, tolerance1);
- throw GeometryException.GeometryInternalError();
- }
-
- // Try Polyline vs Polygon
- if ((m_dimensionMask == -1 || m_dimensionMask == (1 << 1))
- && (gtInput == Geometry.GeometryType.Polyline)
- && (m_geomIntersectorType == Geometry.GeometryType.Polygon)) {
- return tryFastIntersectPolylinePolygon_((Polyline) (input_geom),
- (Polygon) (m_geomIntersector));
- }
-
- // Try Polygon vs Polyline
- if ((m_dimensionMask == -1 || m_dimensionMask == (1 << 1))
- && (gtInput == Geometry.GeometryType.Polygon)
- && (m_geomIntersectorType == Geometry.GeometryType.Polyline)) {
- return tryFastIntersectPolylinePolygon_(
- (Polyline) (m_geomIntersector), (Polygon) (input_geom));
- }
-
- return null;
- }
-
- Geometry tryFastIntersectPolylinePolygon_(Polyline polyline, Polygon polygon) {
- MultiPathImpl polylineImpl = (MultiPathImpl) polyline._getImpl();
- MultiPathImpl polygonImpl = (MultiPathImpl) polygon._getImpl();
-
- double tolerance = InternalUtils.calculateToleranceFromGeometry(
- m_spatial_reference, polygon, false);
- Envelope2D clipEnvelope = new Envelope2D();
- {
- polygonImpl.queryEnvelope2D(clipEnvelope);
- Envelope2D env1 = new Envelope2D();
- polylineImpl.queryEnvelope2D(env1);
- env1.inflate(2.0 * tolerance, 2.0 * tolerance);
- clipEnvelope.intersect(env1);
- assert (!clipEnvelope.isEmpty());
- }
-
- clipEnvelope.inflate(10 * tolerance, 10 * tolerance);
-
- if (true) {
- double tol = 0;
- Geometry clippedPolyline = Clipper.clip(polyline, clipEnvelope,
- tol, 0.0);
- polyline = (Polyline) clippedPolyline;
- polylineImpl = (MultiPathImpl) polyline._getImpl();
- }
-
- AttributeStreamOfInt32 clipResult = new AttributeStreamOfInt32(0);
- int unresolvedSegments = -1;
- GeometryAccelerators accel = polygonImpl._getAccelerators();
- if (accel != null) {
- RasterizedGeometry2D rgeom = accel.getRasterizedGeometry();
- if (rgeom != null) {
- unresolvedSegments = 0;
- clipResult.reserve(polylineImpl.getPointCount()
- + polylineImpl.getPathCount());
- Envelope2D seg_env = new Envelope2D();
- SegmentIteratorImpl iter = polylineImpl.querySegmentIterator();
- while (iter.nextPath()) {
- while (iter.hasNextSegment()) {
- Segment seg = iter.nextSegment();
- seg.queryEnvelope2D(seg_env);
- RasterizedGeometry2D.HitType hit = rgeom
- .queryEnvelopeInGeometry(seg_env);
- if (hit == RasterizedGeometry2D.HitType.Inside) {
- clipResult.add(1);
- } else if (hit == RasterizedGeometry2D.HitType.Outside) {
- clipResult.add(0);
- } else {
- clipResult.add(-1);
- unresolvedSegments++;
- }
- }
- }
- }
- }
-
- if (polygon.getPointCount() > 5) {
- double tol = 0;
- Geometry clippedPolygon = Clipper.clip(polygon, clipEnvelope, tol,
- 0.0);
-
- polygon = (Polygon) clippedPolygon;
- polygonImpl = (MultiPathImpl) polygon._getImpl();
- accel = polygonImpl._getAccelerators();//update accelerators
- }
-
- if (unresolvedSegments < 0) {
- unresolvedSegments = polylineImpl.getSegmentCount();
- }
-
- // Some heuristics to decide if it makes sense to go with fast intersect
- // vs going with the regular planesweep.
- double totalPoints = (double) (polylineImpl.getPointCount() + polygonImpl
- .getPointCount());
- double thisAlgorithmComplexity = ((double) unresolvedSegments * polygonImpl
- .getPointCount());// assume the worst case.
- double planesweepComplexity = Math.log(totalPoints) * totalPoints;
- double empiricConstantFactorPlaneSweep = 4;
- if (thisAlgorithmComplexity > planesweepComplexity
- * empiricConstantFactorPlaneSweep) {
- // Based on the number of input points, we deduced that the
- // plansweep performance should be better than the brute force
- // performance.
- return null; // resort to planesweep if quadtree does not help
- }
-
- QuadTreeImpl polygonQuadTree = null;
- SegmentIteratorImpl polygonIter = polygonImpl.querySegmentIterator();
- // Some logic to decide if it makes sense to build a quadtree on the
- // polygon segments
- if (accel != null && accel.getQuadTree() != null)
- polygonQuadTree = accel.getQuadTree();
-
- if (polygonQuadTree == null && polygonImpl.getPointCount() > 20) {
- polygonQuadTree = InternalUtils.buildQuadTree(polygonImpl);
- }
-
- Polyline result_polyline = (Polyline) polyline.createInstance();
- MultiPathImpl resultPolylineImpl = (MultiPathImpl) result_polyline
- ._getImpl();
- QuadTreeImpl.QuadTreeIteratorImpl qIter = null;
- SegmentIteratorImpl polylineIter = polylineImpl.querySegmentIterator();
- double[] params = new double[9];
- AttributeStreamOfDbl intersections = new AttributeStreamOfDbl(0);
- SegmentBuffer segmentBuffer = new SegmentBuffer();
- int start_index = -1;
- int inCount = 0;
- int segIndex = 0;
- boolean bOptimized = clipResult.size() > 0;
-
- // The algorithm is like that:
- // Loop through all the segments of the polyline.
- // For each polyline segment, intersect it with each of the polygon
- // segments.
- // If no intersections found then,
- // If the polyline segment is completely inside, it is added to the
- // result polyline.
- // If it is outside, it is thrown out.
- // If it intersects, then cut the polyline segment to pieces and test
- // each part of the intersected result.
- // The cut pieces will either have one point inside, or one point
- // outside, or the middle point inside/outside.
- //
- int polylinePathIndex = -1;
-
- while (polylineIter.nextPath()) {
- polylinePathIndex = polylineIter.getPathIndex();
- int stateNewPath = 0;
- int stateAddSegment = 1;
- int stateManySegments = 2;
- int stateManySegmentsContinuePath = 2;
- int stateManySegmentsNewPath = 3;
- int state = stateNewPath;
- start_index = -1;
- inCount = 0;
-
- while (polylineIter.hasNextSegment()) {
- int clipStatus = bOptimized ? (int) clipResult.get(segIndex)
- : -1;
- segIndex++;
- Segment polylineSeg = polylineIter.nextSegment();
- if (clipStatus < 0) {
- assert (clipStatus == -1);
- // Analyse polyline segment for intersection with the
- // polygon.
- if (polygonQuadTree != null) {
- if (qIter == null) {
- qIter = polygonQuadTree.getIterator(polylineSeg,
- tolerance);
- } else {
- qIter.resetIterator(polylineSeg, tolerance);
- }
-
- int path_index = -1;
- for (int ind = qIter.next(); ind != -1; ind = qIter
- .next()) {
- polygonIter.resetToVertex(polygonQuadTree
- .getElement(ind)); // path_index
- path_index = polygonIter.getPathIndex();
- Segment polygonSeg = polygonIter.nextSegment();
- // intersect polylineSeg and polygonSeg.
- int count = polylineSeg.intersect(polygonSeg, null,
- params, null, tolerance);
- for (int i = 0; i < count; i++)
- intersections.add(params[i]);
- }
- } else {// no quadtree built
- polygonIter.resetToFirstPath();
- while (polygonIter.nextPath()) {
- while (polygonIter.hasNextSegment()) {
- Segment polygonSeg = polygonIter.nextSegment();
- // intersect polylineSeg and polygonSeg.
- int count = polylineSeg.intersect(polygonSeg,
- null, params, null, tolerance);
- for (int i = 0; i < count; i++)
- intersections.add(params[i]);
- }
- }
- }
-
- if (intersections.size() > 0) {// intersections detected.
- intersections.sort(0, intersections.size()); // std::sort(intersections.begin(),
- // intersections.end());
-
- double t0 = 0;
- intersections.add(1.0);
- int status = -1;
- for (int i = 0, n = intersections.size(); i < n; i++) {
- double t = intersections.get(i);
- if (t == t0) {
- continue;
- }
- boolean bWholeSegment = false;
- Segment resSeg;
- if (t0 != 0 || t != 1.0) {
- polylineSeg.cut(t0, t, segmentBuffer);
- resSeg = segmentBuffer.get();
- } else {
- resSeg = polylineSeg;
- bWholeSegment = true;
- }
-
- if (state >= stateManySegments) {
- resultPolylineImpl.addSegmentsFromPath(
- polylineImpl, polylinePathIndex,
- start_index, inCount,
- state == stateManySegmentsNewPath);
- if (analyseClipSegment_(polygon,
- resSeg.getStartXY(), tolerance) != 1) {
- if (analyseClipSegment_(polygon, resSeg,
- tolerance) != 1) {
- return null; //someting went wrong we'll falback to slower but robust planesweep code.
- }
- }
-
- resultPolylineImpl.addSegment(resSeg, false);
- state = stateAddSegment;
- inCount = 0;
- } else {
- status = analyseClipSegment_(polygon, resSeg,
- tolerance);
- switch (status) {
- case 1:
- if (!bWholeSegment) {
- resultPolylineImpl.addSegment(resSeg,
- state == stateNewPath);
- state = stateAddSegment;
- } else {
- if (state < stateManySegments) {
- start_index = polylineIter
- .getStartPointIndex()
- - polylineImpl
- .getPathStart(polylinePathIndex);
- inCount = 1;
-
- if (state == stateNewPath)
- state = stateManySegmentsNewPath;
- else {
- assert (state == stateAddSegment);
- state = stateManySegmentsContinuePath;
- }
- } else
- inCount++;
- }
-
- break;
- case 0:
- state = stateNewPath;
- start_index = -1;
- inCount = 0;
- break;
- default:
- return null;// may happen if a segment
- // coincides with the border.
- }
- }
-
- t0 = t;
- }
- } else {
- clipStatus = analyseClipSegment_(polygon,
- polylineSeg.getStartXY(), tolerance);// simple
- // case
- // no
- // intersection.
- // Both
- // points
- // must
- // be
- // inside.
- if (clipStatus < 0) {
- assert (clipStatus >= 0);
- return null;// something goes wrong, resort to
- // planesweep
- }
-
- assert (analyseClipSegment_(polygon,
- polylineSeg.getEndXY(), tolerance) == clipStatus);
- if (clipStatus == 1) {// the whole segment inside
- if (state < stateManySegments) {
- assert (inCount == 0);
- start_index = polylineIter.getStartPointIndex()
- - polylineImpl
- .getPathStart(polylinePathIndex);
- if (state == stateNewPath)
- state = stateManySegmentsNewPath;
- else {
- assert (state == stateAddSegment);
- state = stateManySegmentsContinuePath;
- }
- }
-
- inCount++;
- } else {
- assert (state < stateManySegments);
- start_index = -1;
- inCount = 0;
- }
- }
-
- intersections.clear(false);
- } else {// clip status is determined by other means
- if (clipStatus == 0) {// outside
- assert (analyseClipSegment_(polygon, polylineSeg,
- tolerance) == 0);
- assert (start_index < 0);
- assert (inCount == 0);
- continue;
- }
-
- if (clipStatus == 1) {
- assert (analyseClipSegment_(polygon, polylineSeg,
- tolerance) == 1);
- if (state == stateNewPath) {
- state = stateManySegmentsNewPath;
- start_index = polylineIter.getStartPointIndex()
- - polylineImpl
- .getPathStart(polylinePathIndex);
- } else if (state == stateAddSegment) {
- state = stateManySegmentsContinuePath;
- start_index = polylineIter.getStartPointIndex()
- - polylineImpl
- .getPathStart(polylinePathIndex);
- } else
- assert (state >= stateManySegments);
-
- inCount++;
- continue;
- }
- }
- }
-
- if (state >= stateManySegments) {
- resultPolylineImpl.addSegmentsFromPath(polylineImpl,
- polylinePathIndex, start_index, inCount,
- state == stateManySegmentsNewPath);
- start_index = -1;
- }
- }
-
- return result_polyline;
- }
-
- int analyseClipSegment_(Polygon polygon, Point2D pt, double tol) {
- int v = PointInPolygonHelper.isPointInPolygon(polygon, pt, tol);
- return v;
- }
-
- int analyseClipSegment_(Polygon polygon, Segment seg, double tol) {
- Point2D pt_1 = seg.getStartXY();
- Point2D pt_2 = seg.getEndXY();
- int v_1 = PointInPolygonHelper.isPointInPolygon(polygon, pt_1, tol);
- int v_2 = PointInPolygonHelper.isPointInPolygon(polygon, pt_2, tol);
- if ((v_1 == 1 && v_2 == 0) || (v_1 == 0 && v_2 == 1)) {
- // Operator_factory_local::SaveJSONToTextFileDbg("c:/temp/badPointInPolygon.json",
- // polygon, m_spatial_reference);
- assert (false);// if happens
- return -1;// something went wrong. One point is inside, the other is
- // outside. Should not happen. We'll resort to
- // planesweep.
- }
- if (v_1 == 0 || v_2 == 0)
- return 0;
- if (v_1 == 1 || v_2 == 1)
- return 1;
-
- Point2D midPt = new Point2D();
- midPt.add(pt_1, pt_2);
- midPt.scale(0.5);// calculate midpoint
- int v = PointInPolygonHelper.isPointInPolygon(polygon, midPt, tol);
- if (v == 0) {
- return 0;
- }
-
- if (v == 1) {
- return 1;
- }
-
- return -1;
- }
-
- Geometry normalizeIntersectionOutput(Geometry geom, int GT_1, int GT_2) {
- if (GT_1 == Geometry.GeometryType.Point
- || GT_2 == Geometry.GeometryType.Point) {
- assert (geom.getType().value() == Geometry.GeometryType.Point);
- }
- if (GT_1 == Geometry.GeometryType.MultiPoint) {
- if (geom.getType().value() == Geometry.GeometryType.Point) {
- MultiPoint mp = new MultiPoint(geom.getDescription());
- if (!geom.isEmpty())
- mp.add((Point) geom);
- return mp;
- }
- }
-
- return geom;
- }
-
- static Geometry returnEmpty_(Geometry geom, boolean bEmpty) {
- return bEmpty ? geom : geom.createInstance();
- }
-
- Geometry returnEmptyIntersector_() {
- if (m_geomIntersectorEmptyGeom == null)
- m_geomIntersectorEmptyGeom = m_geomIntersector.createInstance();
-
- return m_geomIntersectorEmptyGeom;
- }
-
- // virtual boolean IsRecycling() OVERRIDE { return false; }
+ GeometryCursor m_smallCursor;
+ ProgressTracker m_progress_tracker;
+ SpatialReference m_spatial_reference;
+ Geometry m_geomIntersector;
+ Geometry m_geomIntersectorEmptyGeom;// holds empty geometry of intersector
+ // type.
+ int m_geomIntersectorType;
+ int m_currentGeomType;
+ int m_dimensionMask;
+ boolean m_bEmpty;
+
+ OperatorIntersectionCursor(GeometryCursor inputGeoms,
+ GeometryCursor geomIntersector,
+ SpatialReference sr,
+ ProgressTracker progress_tracker,
+ int dimensionMask) {
+ m_bEmpty = geomIntersector == null;
+ m_inputGeoms = inputGeoms;
+ m_spatial_reference = sr;
+ m_geomIntersector = geomIntersector.next();
+ m_geomIntersectorType = m_geomIntersector.getType().value();
+ m_currentGeomType = Geometry.Type.Unknown.value();
+ m_progress_tracker = progress_tracker;
+ m_dimensionMask = dimensionMask;
+ if (m_dimensionMask != -1
+ && (m_dimensionMask <= 0 || m_dimensionMask > 7))
+ throw new IllegalArgumentException("bad dimension mask");// dimension
+ // mask
+ // can
+ // be
+ // -1,
+ // for
+ // the
+ // default
+ // behavior,
+ // or a
+ // value
+ // between
+ // 1 and
+ // 7.
+ }
+
+ @Override
+ public Geometry next() {
+ if (m_bEmpty)
+ return null;
+
+ Geometry geom;
+ if (m_smallCursor != null && m_smallCursor.hasNext()) {// when dimension mask is used, we produce a
+ geom = m_smallCursor.next();
+ if (geom != null)
+ return geom;
+ else
+ m_smallCursor = null;// done with the small cursor
+ }
+
+ if (m_inputGeoms.hasNext()) {
+ geom = m_inputGeoms.next();
+ if (m_dimensionMask == -1) {
+ Geometry resGeom = intersect(geom);
+ assert (resGeom != null);
+ return resGeom;
+ } else {
+ m_smallCursor = intersectEx(geom);
+ Geometry resGeom = m_smallCursor.next();
+ assert (resGeom != null);
+ return resGeom;
+ }
+ }
+ return null;
+ }
+
+ Geometry intersect(Geometry input_geom) {
+ Geometry dst_geom = tryNativeImplementation_(input_geom);
+ if (dst_geom != null)
+ return dst_geom;
+
+ Envelope2D commonExtent = InternalUtils.getMergedExtent(
+ m_geomIntersector, input_geom);
+
+ // return Topological_operations::intersection(input_geom,
+ // m_geomIntersector, m_spatial_reference, m_progress_tracker);
+ // Preprocess geometries to be clipped to the extent of intersection to
+ // get rid of extra segments.
+ double t = InternalUtils.calculateToleranceFromGeometry(m_spatial_reference, commonExtent, true);
+ Envelope2D env = new Envelope2D();
+ m_geomIntersector.queryEnvelope2D(env);
+ Envelope2D env1 = new Envelope2D();
+ input_geom.queryEnvelope2D(env1);
+ env.inflate(2.0 * t, 2.0 * t);
+ env.intersect(env1);
+ assert (!env.isEmpty());
+ env.inflate(100 * t, 100 * t);
+ double tol = 0;
+ Geometry clippedIntersector = Clipper.clip(m_geomIntersector, env, tol,
+ 0.0);
+ Geometry clippedInputGeom = Clipper.clip(input_geom, env, tol, 0.0);
+ // perform the clip
+ return TopologicalOperations.intersection(clippedInputGeom,
+ clippedIntersector, m_spatial_reference, m_progress_tracker);
+ }
+
+ // Parses the input vector to ensure the out result contains only geometries
+ // as indicated with the dimensionMask
+ GeometryCursor prepareVector_(VertexDescription descr, int dimensionMask,
+ Geometry[] res_vec) {
+ int inext = 0;
+ if ((dimensionMask & 1) != 0) {
+ if (res_vec[0] == null)
+ res_vec[0] = new MultiPoint(descr);
+ inext++;
+ } else {
+ for (int i = 0; i < res_vec.length - 1; i++)
+ res_vec[i] = res_vec[i + 1];
+ }
+
+ if ((dimensionMask & 2) != 0) {
+ if (res_vec[inext] == null)
+ res_vec[inext] = new Polyline(descr);
+ inext++;
+ } else {
+ for (int i = inext; i < res_vec.length - 1; i++)
+ res_vec[i] = res_vec[i + 1];
+ }
+
+ if ((dimensionMask & 4) != 0) {
+ if (res_vec[inext] == null)
+ res_vec[inext] = new Polygon(descr);
+ inext++;
+ } else {
+ for (int i = inext; i < res_vec.length - 1; i++)
+ res_vec[i] = res_vec[i + 1];
+ }
+
+ if (inext != 3) {
+ Geometry[] r = new Geometry[inext];
+ for (int i = 0; i < inext; i++)
+ r[i] = res_vec[i];
+
+ return new SimpleGeometryCursor(r);
+ } else {
+ return new SimpleGeometryCursor(res_vec);
+ }
+ }
+
+ GeometryCursor intersectEx(Geometry input_geom) {
+ assert (m_dimensionMask != -1);
+ Geometry dst_geom = tryNativeImplementation_(input_geom);
+ if (dst_geom != null) {
+ Geometry[] res_vec = new Geometry[3];
+ res_vec[dst_geom.getDimension()] = dst_geom;
+ return prepareVector_(input_geom.getDescription(), m_dimensionMask,
+ res_vec);
+ }
+
+ Envelope2D commonExtent = InternalUtils.getMergedExtent(
+ m_geomIntersector, input_geom);
+ double t = InternalUtils.calculateToleranceFromGeometry(
+ m_spatial_reference, commonExtent, true);
+
+ // Preprocess geometries to be clipped to the extent of intersection to
+ // get rid of extra segments.
+
+ Envelope2D env = new Envelope2D();
+ m_geomIntersector.queryEnvelope2D(env);
+ env.inflate(2 * t, 2 * t);
+ Envelope2D env1 = new Envelope2D();
+ input_geom.queryEnvelope2D(env1);
+ env.intersect(env1);
+ assert (!env.isEmpty());
+ env.inflate(100 * t, 100 * t);
+ double tol = 0;
+ Geometry clippedIntersector = Clipper.clip(m_geomIntersector, env, tol,
+ 0.0);
+ Geometry clippedInputGeom = Clipper.clip(input_geom, env, tol, 0.0);
+ // perform the clip
+ Geometry[] res_vec;
+ res_vec = TopologicalOperations.intersectionEx(clippedInputGeom,
+ clippedIntersector, m_spatial_reference, m_progress_tracker);
+ return prepareVector_(input_geom.getDescription(), m_dimensionMask,
+ res_vec);
+ }
+
+ Geometry tryNativeImplementation_(Geometry input_geom) {
+ // A note on attributes:
+ // 1. The geometry with lower dimension wins in regard to the
+ // attributes.
+ // 2. If the dimensions are the same, the input_geometry attributes win.
+ // 3. The exception to the 2. is when the input is an Envelope, and the
+ // intersector is a polygon, then the intersector wins.
+
+ // A note on the tolerance:
+ // This operator performs a simple intersection operation. Should it use
+ // the tolerance?
+ // Example: Point is intersected by the envelope.
+ // If it is slightly outside of the envelope, should we still return it
+ // if it is closer than the tolerance?
+ // Should we do crack and cluster and snap the point coordinates to the
+ // envelope boundary?
+ //
+ // Consider floating point arithmetics approach. When you compare
+ // doubles, you should use an epsilon (equals means ::fabs(a - b) <
+ // eps), however when you add/subtract, etc them, you do not use
+ // epsilon.
+ // Shouldn't we do same here? Relational operators use tolerance, but
+ // the action operators don't.
+
+ Envelope2D mergedExtent = InternalUtils.getMergedExtent(input_geom,
+ m_geomIntersector);
+ double tolerance = InternalUtils.calculateToleranceFromGeometry(
+ m_spatial_reference, mergedExtent, false);
+
+ int gtInput = input_geom.getType().value();
+ boolean bInputEmpty = input_geom.isEmpty();
+ boolean bGeomIntersectorEmpty = m_geomIntersector.isEmpty();
+ boolean bResultIsEmpty = bInputEmpty || bGeomIntersectorEmpty;
+ if (!bResultIsEmpty) {// test envelopes
+ Envelope2D env2D1 = new Envelope2D();
+ input_geom.queryEnvelope2D(env2D1);
+ Envelope2D env2D2 = new Envelope2D();
+ m_geomIntersector.queryEnvelope2D(env2D2);
+ env2D2.inflate(2.0 * tolerance, 2.0 * tolerance);
+ bResultIsEmpty = !env2D1.isIntersecting(env2D2);
+ }
+
+ if (!bResultIsEmpty) {// try accelerated test
+ int res = OperatorInternalRelationUtils
+ .quickTest2D_Accelerated_DisjointOrContains(
+ m_geomIntersector, input_geom, tolerance);
+ if (res == OperatorInternalRelationUtils.Relation.Disjoint) {// disjoint
+ bResultIsEmpty = true;
+ } else if ((res & OperatorInternalRelationUtils.Relation.Within) != 0) {// intersector
+ // is
+ // within
+ // the
+ // input_geom
+ // TODO:
+ // assign
+ // input_geom
+ // attributes
+ // first
+ return m_geomIntersector;
+ } else if ((res & OperatorInternalRelationUtils.Relation.Contains) != 0) {// intersector
+ // contains
+ // input_geom
+ return input_geom;
+ }
+ }
+
+ if (bResultIsEmpty) {// When one geometry or both are empty, we need to
+ // return an empty geometry.
+ // Here we do that end also ensure the type is
+ // correct.
+ // That is the lower dimension need to be
+ // returned. Also, for Point vs Multi_point, an
+ // empty Point need to be returned.
+ int dim1 = Geometry.getDimensionFromType(gtInput);
+ int dim2 = Geometry.getDimensionFromType(m_geomIntersectorType);
+ if (dim1 < dim2)
+ return returnEmpty_(input_geom, bInputEmpty);
+ else if (dim1 > dim2)
+ return returnEmptyIntersector_();
+ else if (dim1 == 0) {
+ if (gtInput == Geometry.GeometryType.MultiPoint
+ && m_geomIntersectorType == Geometry.GeometryType.Point) {// point
+ // vs
+ // Multi_point
+ // need
+ // special
+ // treatment
+ // to
+ // ensure
+ // Point
+ // is
+ // returned
+ // always.
+ return returnEmptyIntersector_();
+ } else
+ // Both input and intersector have same gtype, or input is
+ // Point.
+ return returnEmpty_(input_geom, bInputEmpty);
+ } else
+ return returnEmpty_(input_geom, bInputEmpty);
+ }
+
+ // Note: No empty geometries after this point!
+
+ // Warning: Do not try clip for polylines and polygons.
+
+ // Try clip of Envelope with Envelope.
+ if ((m_dimensionMask == -1 || m_dimensionMask == (1 << 2))
+ && gtInput == Geometry.GeometryType.Envelope
+ && m_geomIntersectorType == Geometry.GeometryType.Envelope) {
+ Envelope env1 = (Envelope) input_geom;
+ Envelope env2 = (Envelope) m_geomIntersector;
+ Envelope2D env2D_1 = new Envelope2D();
+ env1.queryEnvelope2D(env2D_1);
+ Envelope2D env2D_2 = new Envelope2D();
+ env2.queryEnvelope2D(env2D_2);
+ env2D_1.intersect(env2D_2);
+ Envelope result_env = new Envelope();
+ env1.copyTo(result_env);
+ result_env.setEnvelope2D(env2D_1);
+ return result_env;
+ }
+
+ // Use clip for Point and Multi_point with Envelope
+ if ((gtInput == Geometry.GeometryType.Envelope && Geometry
+ .getDimensionFromType(m_geomIntersectorType) == 0)
+ || (m_geomIntersectorType == Geometry.GeometryType.Envelope && Geometry
+ .getDimensionFromType(gtInput) == 0)) {
+ Envelope env = gtInput == Geometry.GeometryType.Envelope ? (Envelope) input_geom
+ : (Envelope) m_geomIntersector;
+ Geometry other = gtInput == Geometry.GeometryType.Envelope ? m_geomIntersector
+ : input_geom;
+ Envelope2D env_2D = new Envelope2D();
+ env.queryEnvelope2D(env_2D);
+ return Clipper.clip(other, env_2D, tolerance, 0);
+ }
+
+ if ((Geometry.getDimensionFromType(gtInput) == 0 && Geometry
+ .getDimensionFromType(m_geomIntersectorType) > 0)
+ || (Geometry.getDimensionFromType(gtInput) > 0 && Geometry
+ .getDimensionFromType(m_geomIntersectorType) == 0)) {// multipoint
+ // intersection
+ double tolerance1 = InternalUtils.calculateToleranceFromGeometry(
+ m_spatial_reference, input_geom, false);
+ if (gtInput == Geometry.GeometryType.MultiPoint)
+ return TopologicalOperations.intersection(
+ (MultiPoint) input_geom, m_geomIntersector, tolerance1);
+ if (gtInput == Geometry.GeometryType.Point)
+ return TopologicalOperations.intersection((Point) input_geom,
+ m_geomIntersector, tolerance1);
+ if (m_geomIntersectorType == Geometry.GeometryType.MultiPoint)
+ return TopologicalOperations.intersection(
+ (MultiPoint) m_geomIntersector, input_geom, tolerance1);
+ if (m_geomIntersectorType == Geometry.GeometryType.Point)
+ return TopologicalOperations.intersection(
+ (Point) m_geomIntersector, input_geom, tolerance1);
+ throw GeometryException.GeometryInternalError();
+ }
+
+ // Try Polyline vs Polygon
+ if ((m_dimensionMask == -1 || m_dimensionMask == (1 << 1))
+ && (gtInput == Geometry.GeometryType.Polyline)
+ && (m_geomIntersectorType == Geometry.GeometryType.Polygon)) {
+ return tryFastIntersectPolylinePolygon_((Polyline) (input_geom),
+ (Polygon) (m_geomIntersector));
+ }
+
+ // Try Polygon vs Polyline
+ if ((m_dimensionMask == -1 || m_dimensionMask == (1 << 1))
+ && (gtInput == Geometry.GeometryType.Polygon)
+ && (m_geomIntersectorType == Geometry.GeometryType.Polyline)) {
+ return tryFastIntersectPolylinePolygon_(
+ (Polyline) (m_geomIntersector), (Polygon) (input_geom));
+ }
+
+ return null;
+ }
+
+ Geometry tryFastIntersectPolylinePolygon_(Polyline polyline, Polygon polygon) {
+ MultiPathImpl polylineImpl = (MultiPathImpl) polyline._getImpl();
+ MultiPathImpl polygonImpl = (MultiPathImpl) polygon._getImpl();
+
+ double tolerance = InternalUtils.calculateToleranceFromGeometry(
+ m_spatial_reference, polygon, false);
+ Envelope2D clipEnvelope = new Envelope2D();
+ {
+ polygonImpl.queryEnvelope2D(clipEnvelope);
+ Envelope2D env1 = new Envelope2D();
+ polylineImpl.queryEnvelope2D(env1);
+ env1.inflate(2.0 * tolerance, 2.0 * tolerance);
+ clipEnvelope.intersect(env1);
+ assert (!clipEnvelope.isEmpty());
+ }
+
+ clipEnvelope.inflate(10 * tolerance, 10 * tolerance);
+
+ if (true) {
+ double tol = 0;
+ Geometry clippedPolyline = Clipper.clip(polyline, clipEnvelope,
+ tol, 0.0);
+ polyline = (Polyline) clippedPolyline;
+ polylineImpl = (MultiPathImpl) polyline._getImpl();
+ }
+
+ AttributeStreamOfInt32 clipResult = new AttributeStreamOfInt32(0);
+ int unresolvedSegments = -1;
+ GeometryAccelerators accel = polygonImpl._getAccelerators();
+ if (accel != null) {
+ RasterizedGeometry2D rgeom = accel.getRasterizedGeometry();
+ if (rgeom != null) {
+ unresolvedSegments = 0;
+ clipResult.reserve(polylineImpl.getPointCount()
+ + polylineImpl.getPathCount());
+ Envelope2D seg_env = new Envelope2D();
+ SegmentIteratorImpl iter = polylineImpl.querySegmentIterator();
+ while (iter.nextPath()) {
+ while (iter.hasNextSegment()) {
+ Segment seg = iter.nextSegment();
+ seg.queryEnvelope2D(seg_env);
+ RasterizedGeometry2D.HitType hit = rgeom
+ .queryEnvelopeInGeometry(seg_env);
+ if (hit == RasterizedGeometry2D.HitType.Inside) {
+ clipResult.add(1);
+ } else if (hit == RasterizedGeometry2D.HitType.Outside) {
+ clipResult.add(0);
+ } else {
+ clipResult.add(-1);
+ unresolvedSegments++;
+ }
+ }
+ }
+ }
+ }
+
+ if (polygon.getPointCount() > 5) {
+ double tol = 0;
+ Geometry clippedPolygon = Clipper.clip(polygon, clipEnvelope, tol,
+ 0.0);
+
+ polygon = (Polygon) clippedPolygon;
+ polygonImpl = (MultiPathImpl) polygon._getImpl();
+ accel = polygonImpl._getAccelerators();//update accelerators
+ }
+
+ if (unresolvedSegments < 0) {
+ unresolvedSegments = polylineImpl.getSegmentCount();
+ }
+
+ // Some heuristics to decide if it makes sense to go with fast intersect
+ // vs going with the regular planesweep.
+ double totalPoints = (double) (polylineImpl.getPointCount() + polygonImpl
+ .getPointCount());
+ double thisAlgorithmComplexity = ((double) unresolvedSegments * polygonImpl
+ .getPointCount());// assume the worst case.
+ double planesweepComplexity = Math.log(totalPoints) * totalPoints;
+ double empiricConstantFactorPlaneSweep = 4;
+ if (thisAlgorithmComplexity > planesweepComplexity
+ * empiricConstantFactorPlaneSweep) {
+ // Based on the number of input points, we deduced that the
+ // plansweep performance should be better than the brute force
+ // performance.
+ return null; // resort to planesweep if quadtree does not help
+ }
+
+ QuadTreeImpl polygonQuadTree = null;
+ SegmentIteratorImpl polygonIter = polygonImpl.querySegmentIterator();
+ // Some logic to decide if it makes sense to build a quadtree on the
+ // polygon segments
+ if (accel != null && accel.getQuadTree() != null)
+ polygonQuadTree = accel.getQuadTree();
+
+ if (polygonQuadTree == null && polygonImpl.getPointCount() > 20) {
+ polygonQuadTree = InternalUtils.buildQuadTree(polygonImpl);
+ }
+
+ Polyline result_polyline = (Polyline) polyline.createInstance();
+ MultiPathImpl resultPolylineImpl = (MultiPathImpl) result_polyline
+ ._getImpl();
+ QuadTreeImpl.QuadTreeIteratorImpl qIter = null;
+ SegmentIteratorImpl polylineIter = polylineImpl.querySegmentIterator();
+ double[] params = new double[9];
+ AttributeStreamOfDbl intersections = new AttributeStreamOfDbl(0);
+ SegmentBuffer segmentBuffer = new SegmentBuffer();
+ int start_index = -1;
+ int inCount = 0;
+ int segIndex = 0;
+ boolean bOptimized = clipResult.size() > 0;
+
+ // The algorithm is like that:
+ // Loop through all the segments of the polyline.
+ // For each polyline segment, intersect it with each of the polygon
+ // segments.
+ // If no intersections found then,
+ // If the polyline segment is completely inside, it is added to the
+ // result polyline.
+ // If it is outside, it is thrown out.
+ // If it intersects, then cut the polyline segment to pieces and test
+ // each part of the intersected result.
+ // The cut pieces will either have one point inside, or one point
+ // outside, or the middle point inside/outside.
+ //
+ int polylinePathIndex = -1;
+
+ while (polylineIter.nextPath()) {
+ polylinePathIndex = polylineIter.getPathIndex();
+ int stateNewPath = 0;
+ int stateAddSegment = 1;
+ int stateManySegments = 2;
+ int stateManySegmentsContinuePath = 2;
+ int stateManySegmentsNewPath = 3;
+ int state = stateNewPath;
+ start_index = -1;
+ inCount = 0;
+
+ while (polylineIter.hasNextSegment()) {
+ int clipStatus = bOptimized ? (int) clipResult.get(segIndex)
+ : -1;
+ segIndex++;
+ Segment polylineSeg = polylineIter.nextSegment();
+ if (clipStatus < 0) {
+ assert (clipStatus == -1);
+ // Analyse polyline segment for intersection with the
+ // polygon.
+ if (polygonQuadTree != null) {
+ if (qIter == null) {
+ qIter = polygonQuadTree.getIterator(polylineSeg,
+ tolerance);
+ } else {
+ qIter.resetIterator(polylineSeg, tolerance);
+ }
+
+ int path_index = -1;
+ for (int ind = qIter.next(); ind != -1; ind = qIter
+ .next()) {
+ polygonIter.resetToVertex(polygonQuadTree
+ .getElement(ind)); // path_index
+ path_index = polygonIter.getPathIndex();
+ Segment polygonSeg = polygonIter.nextSegment();
+ // intersect polylineSeg and polygonSeg.
+ int count = polylineSeg.intersect(polygonSeg, null,
+ params, null, tolerance);
+ for (int i = 0; i < count; i++)
+ intersections.add(params[i]);
+ }
+ } else {// no quadtree built
+ polygonIter.resetToFirstPath();
+ while (polygonIter.nextPath()) {
+ while (polygonIter.hasNextSegment()) {
+ Segment polygonSeg = polygonIter.nextSegment();
+ // intersect polylineSeg and polygonSeg.
+ int count = polylineSeg.intersect(polygonSeg,
+ null, params, null, tolerance);
+ for (int i = 0; i < count; i++)
+ intersections.add(params[i]);
+ }
+ }
+ }
+
+ if (intersections.size() > 0) {// intersections detected.
+ intersections.sort(0, intersections.size()); // std::sort(intersections.begin(),
+ // intersections.end());
+
+ double t0 = 0;
+ intersections.add(1.0);
+ int status = -1;
+ for (int i = 0, n = intersections.size(); i < n; i++) {
+ double t = intersections.get(i);
+ if (t == t0) {
+ continue;
+ }
+ boolean bWholeSegment = false;
+ Segment resSeg;
+ if (t0 != 0 || t != 1.0) {
+ polylineSeg.cut(t0, t, segmentBuffer);
+ resSeg = segmentBuffer.get();
+ } else {
+ resSeg = polylineSeg;
+ bWholeSegment = true;
+ }
+
+ if (state >= stateManySegments) {
+ resultPolylineImpl.addSegmentsFromPath(
+ polylineImpl, polylinePathIndex,
+ start_index, inCount,
+ state == stateManySegmentsNewPath);
+ if (analyseClipSegment_(polygon,
+ resSeg.getStartXY(), tolerance) != 1) {
+ if (analyseClipSegment_(polygon, resSeg,
+ tolerance) != 1) {
+ return null; //someting went wrong we'll falback to slower but robust planesweep code.
+ }
+ }
+
+ resultPolylineImpl.addSegment(resSeg, false);
+ state = stateAddSegment;
+ inCount = 0;
+ } else {
+ status = analyseClipSegment_(polygon, resSeg,
+ tolerance);
+ switch (status) {
+ case 1:
+ if (!bWholeSegment) {
+ resultPolylineImpl.addSegment(resSeg,
+ state == stateNewPath);
+ state = stateAddSegment;
+ } else {
+ if (state < stateManySegments) {
+ start_index = polylineIter
+ .getStartPointIndex()
+ - polylineImpl
+ .getPathStart(polylinePathIndex);
+ inCount = 1;
+
+ if (state == stateNewPath)
+ state = stateManySegmentsNewPath;
+ else {
+ assert (state == stateAddSegment);
+ state = stateManySegmentsContinuePath;
+ }
+ } else
+ inCount++;
+ }
+
+ break;
+ case 0:
+ state = stateNewPath;
+ start_index = -1;
+ inCount = 0;
+ break;
+ default:
+ return null;// may happen if a segment
+ // coincides with the border.
+ }
+ }
+
+ t0 = t;
+ }
+ } else {
+ clipStatus = analyseClipSegment_(polygon,
+ polylineSeg.getStartXY(), tolerance);// simple
+ // case
+ // no
+ // intersection.
+ // Both
+ // points
+ // must
+ // be
+ // inside.
+ if (clipStatus < 0) {
+ assert (clipStatus >= 0);
+ return null;// something goes wrong, resort to
+ // planesweep
+ }
+
+ assert (analyseClipSegment_(polygon,
+ polylineSeg.getEndXY(), tolerance) == clipStatus);
+ if (clipStatus == 1) {// the whole segment inside
+ if (state < stateManySegments) {
+ assert (inCount == 0);
+ start_index = polylineIter.getStartPointIndex()
+ - polylineImpl
+ .getPathStart(polylinePathIndex);
+ if (state == stateNewPath)
+ state = stateManySegmentsNewPath;
+ else {
+ assert (state == stateAddSegment);
+ state = stateManySegmentsContinuePath;
+ }
+ }
+
+ inCount++;
+ } else {
+ assert (state < stateManySegments);
+ start_index = -1;
+ inCount = 0;
+ }
+ }
+
+ intersections.clear(false);
+ } else {// clip status is determined by other means
+ if (clipStatus == 0) {// outside
+ assert (analyseClipSegment_(polygon, polylineSeg,
+ tolerance) == 0);
+ assert (start_index < 0);
+ assert (inCount == 0);
+ continue;
+ }
+
+ if (clipStatus == 1) {
+ assert (analyseClipSegment_(polygon, polylineSeg,
+ tolerance) == 1);
+ if (state == stateNewPath) {
+ state = stateManySegmentsNewPath;
+ start_index = polylineIter.getStartPointIndex()
+ - polylineImpl
+ .getPathStart(polylinePathIndex);
+ } else if (state == stateAddSegment) {
+ state = stateManySegmentsContinuePath;
+ start_index = polylineIter.getStartPointIndex()
+ - polylineImpl
+ .getPathStart(polylinePathIndex);
+ } else
+ assert (state >= stateManySegments);
+
+ inCount++;
+ continue;
+ }
+ }
+ }
+
+ if (state >= stateManySegments) {
+ resultPolylineImpl.addSegmentsFromPath(polylineImpl,
+ polylinePathIndex, start_index, inCount,
+ state == stateManySegmentsNewPath);
+ start_index = -1;
+ }
+ }
+
+ return result_polyline;
+ }
+
+ int analyseClipSegment_(Polygon polygon, Point2D pt, double tol) {
+ int v = PointInPolygonHelper.isPointInPolygon(polygon, pt, tol);
+ return v;
+ }
+
+ int analyseClipSegment_(Polygon polygon, Segment seg, double tol) {
+ Point2D pt_1 = seg.getStartXY();
+ Point2D pt_2 = seg.getEndXY();
+ int v_1 = PointInPolygonHelper.isPointInPolygon(polygon, pt_1, tol);
+ int v_2 = PointInPolygonHelper.isPointInPolygon(polygon, pt_2, tol);
+ if ((v_1 == 1 && v_2 == 0) || (v_1 == 0 && v_2 == 1)) {
+ // Operator_factory_local::SaveJSONToTextFileDbg("c:/temp/badPointInPolygon.json",
+ // polygon, m_spatial_reference);
+ assert (false);// if happens
+ return -1;// something went wrong. One point is inside, the other is
+ // outside. Should not happen. We'll resort to
+ // planesweep.
+ }
+ if (v_1 == 0 || v_2 == 0)
+ return 0;
+ if (v_1 == 1 || v_2 == 1)
+ return 1;
+
+ Point2D midPt = new Point2D();
+ midPt.add(pt_1, pt_2);
+ midPt.scale(0.5);// calculate midpoint
+ int v = PointInPolygonHelper.isPointInPolygon(polygon, midPt, tol);
+ if (v == 0) {
+ return 0;
+ }
+
+ if (v == 1) {
+ return 1;
+ }
+
+ return -1;
+ }
+
+ Geometry normalizeIntersectionOutput(Geometry geom, int GT_1, int GT_2) {
+ if (GT_1 == Geometry.GeometryType.Point
+ || GT_2 == Geometry.GeometryType.Point) {
+ assert (geom.getType().value() == Geometry.GeometryType.Point);
+ }
+ if (GT_1 == Geometry.GeometryType.MultiPoint) {
+ if (geom.getType().value() == Geometry.GeometryType.Point) {
+ MultiPoint mp = new MultiPoint(geom.getDescription());
+ if (!geom.isEmpty())
+ mp.add((Point) geom);
+ return mp;
+ }
+ }
+
+ return geom;
+ }
+
+ static Geometry returnEmpty_(Geometry geom, boolean bEmpty) {
+ return bEmpty ? geom : geom.createInstance();
+ }
+
+ Geometry returnEmptyIntersector_() {
+ if (m_geomIntersectorEmptyGeom == null)
+ m_geomIntersectorEmptyGeom = m_geomIntersector.createInstance();
+
+ return m_geomIntersectorEmptyGeom;
+ }
+
+ // virtual boolean IsRecycling() OVERRIDE { return false; }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorIntersectionLocal.java b/src/main/java/com/esri/core/geometry/OperatorIntersectionLocal.java
index 03d50c31..f2ce196b 100644
--- a/src/main/java/com/esri/core/geometry/OperatorIntersectionLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorIntersectionLocal.java
@@ -28,54 +28,54 @@
class OperatorIntersectionLocal extends OperatorIntersection {
- @Override
- public GeometryCursor execute(GeometryCursor inputGeometries,
- GeometryCursor intersector, SpatialReference sr,
- ProgressTracker progressTracker) {
-
- return new OperatorIntersectionCursor(inputGeometries, intersector, sr,
- progressTracker, -1);
- }
-
- @Override
- public GeometryCursor execute(GeometryCursor input_geometries,
- GeometryCursor intersector, SpatialReference sr,
- ProgressTracker progress_tracker, int dimensionMask) {
- return new OperatorIntersectionCursor(input_geometries, intersector,
- sr, progress_tracker, dimensionMask);
- }
-
- @Override
- public Geometry execute(Geometry inputGeometry, Geometry intersector,
- SpatialReference sr, ProgressTracker progressTracker) {
- SimpleGeometryCursor inputGeomCurs = new SimpleGeometryCursor(
- inputGeometry);
- SimpleGeometryCursor intersectorCurs = new SimpleGeometryCursor(
- intersector);
- GeometryCursor geometryCursor = execute(inputGeomCurs, intersectorCurs,
- sr, progressTracker);
-
- return geometryCursor.next();
- }
-
- @Override
- public boolean accelerateGeometry(Geometry geometry,
- SpatialReference spatialReference,
- GeometryAccelerationDegree accelDegree) {
- if (!canAccelerateGeometry(geometry))
- return false;
-
- double tol = InternalUtils.calculateToleranceFromGeometry(spatialReference, geometry, false);
- boolean accelerated = ((MultiVertexGeometryImpl) geometry._getImpl())
- ._buildQuadTreeAccelerator(accelDegree);
- accelerated |= ((MultiVertexGeometryImpl) geometry._getImpl())
- ._buildRasterizedGeometryAccelerator(tol, accelDegree);
- return accelerated;
- }
-
- @Override
- public boolean canAccelerateGeometry(Geometry geometry) {
- return RasterizedGeometry2D.canUseAccelerator(geometry);
- }
+ @Override
+ public GeometryCursor execute(GeometryCursor inputGeometries,
+ GeometryCursor intersector, SpatialReference sr,
+ ProgressTracker progressTracker) {
+
+ return new OperatorIntersectionCursor(inputGeometries, intersector, sr,
+ progressTracker, -1);
+ }
+
+ @Override
+ public GeometryCursor execute(GeometryCursor input_geometries,
+ GeometryCursor intersector, SpatialReference sr,
+ ProgressTracker progress_tracker, int dimensionMask) {
+ return new OperatorIntersectionCursor(input_geometries, intersector,
+ sr, progress_tracker, dimensionMask);
+ }
+
+ @Override
+ public Geometry execute(Geometry inputGeometry, Geometry intersector,
+ SpatialReference sr, ProgressTracker progressTracker) {
+ SimpleGeometryCursor inputGeomCurs = new SimpleGeometryCursor(
+ inputGeometry);
+ SimpleGeometryCursor intersectorCurs = new SimpleGeometryCursor(
+ intersector);
+ GeometryCursor geometryCursor = execute(inputGeomCurs, intersectorCurs,
+ sr, progressTracker);
+
+ return geometryCursor.next();
+ }
+
+ @Override
+ public boolean accelerateGeometry(Geometry geometry,
+ SpatialReference spatialReference,
+ GeometryAccelerationDegree accelDegree) {
+ if (!canAccelerateGeometry(geometry))
+ return false;
+
+ double tol = InternalUtils.calculateToleranceFromGeometry(spatialReference, geometry, false);
+ boolean accelerated = ((MultiVertexGeometryImpl) geometry._getImpl())
+ ._buildQuadTreeAccelerator(accelDegree);
+ accelerated |= ((MultiVertexGeometryImpl) geometry._getImpl())
+ ._buildRasterizedGeometryAccelerator(tol, accelDegree);
+ return accelerated;
+ }
+
+ @Override
+ public boolean canAccelerateGeometry(Geometry geometry) {
+ return RasterizedGeometry2D.canUseAccelerator(geometry);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorIntersects.java b/src/main/java/com/esri/core/geometry/OperatorIntersects.java
index e42ce750..ace6c277 100644
--- a/src/main/java/com/esri/core/geometry/OperatorIntersects.java
+++ b/src/main/java/com/esri/core/geometry/OperatorIntersects.java
@@ -25,14 +25,14 @@
package com.esri.core.geometry;
public abstract class OperatorIntersects extends OperatorSimpleRelation {
- @Override
- public Type getType() {
- return Type.Intersects;
- }
-
- public static OperatorIntersects local() {
- return (OperatorIntersects) OperatorFactoryLocal.getInstance()
- .getOperator(Type.Intersects);
- }
+ @Override
+ public Type getType() {
+ return Type.Intersects;
+ }
+
+ public static OperatorIntersects local() {
+ return (OperatorIntersects) OperatorFactoryLocal.getInstance()
+ .getOperator(Type.Intersects);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorIntersectsLocal.java b/src/main/java/com/esri/core/geometry/OperatorIntersectsLocal.java
index cf9c358b..d4b47d76 100644
--- a/src/main/java/com/esri/core/geometry/OperatorIntersectsLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorIntersectsLocal.java
@@ -26,13 +26,13 @@
class OperatorIntersectsLocal extends OperatorIntersects {
- OperatorDisjoint m_disjoint = (OperatorDisjoint) OperatorFactoryLocal
- .getInstance().getOperator(Type.Disjoint);
-
- @Override
- public boolean execute(Geometry inputGeom1, Geometry inputGeom2,
- SpatialReference sr, ProgressTracker progressTracker) {
- return !m_disjoint.execute(inputGeom1, inputGeom2, sr, progressTracker);
- }
+ OperatorDisjoint m_disjoint = (OperatorDisjoint) OperatorFactoryLocal
+ .getInstance().getOperator(Type.Disjoint);
+
+ @Override
+ public boolean execute(Geometry inputGeom1, Geometry inputGeom2,
+ SpatialReference sr, ProgressTracker progressTracker) {
+ return !m_disjoint.execute(inputGeom1, inputGeom2, sr, progressTracker);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorOffset.java b/src/main/java/com/esri/core/geometry/OperatorOffset.java
index 68b1c1b8..214ee811 100644
--- a/src/main/java/com/esri/core/geometry/OperatorOffset.java
+++ b/src/main/java/com/esri/core/geometry/OperatorOffset.java
@@ -26,31 +26,32 @@
import com.esri.core.geometry.Operator.Type;
public abstract class OperatorOffset extends Operator {
- @Override
- public Operator.Type getType() {
- return Operator.Type.Offset;
- }
+ @Override
+ public Operator.Type getType() {
+ return Operator.Type.Offset;
+ }
- /**
- * Join types for the offset operation. Updated to match grpc int values
- */
- public enum JoinType {
- Round(0), Bevel(1), Miter(2), Square(3);
- private final int value;
- JoinType(int value) {
- this.value = value;
- }
+ /**
+ * Join types for the offset operation. Updated to match grpc int values
+ */
+ public enum JoinType {
+ Round(0), Bevel(1), Miter(2), Square(3);
+ private final int value;
+
+ JoinType(int value) {
+ this.value = value;
+ }
- public int getValue() {
- return this.value;
- }
- }
+ public int getValue() {
+ return this.value;
+ }
+ }
- ;
+ ;
/**
* Creates offset version of the input geometries.
- *
+ *
* The offset operation creates a geometry that is a constant distance from
* an input polyline or polygon. It is similar to buffering, but produces a
* one sided result. If offsetDistance greater than 0, then the offset geometry is
@@ -61,35 +62,29 @@ public int getValue() {
* multiplied by the offset distance and the result determines how far a
* mitered offset intersection can be from the input curve before it is
* beveled.
- *
- * @param inputGeometries
- * The geometries to calculate offset for. Point and MultiPoint
- * are not supported.
- * @param sr
- * The SpatialReference of the Geometries.
- * @param distance
- * The offset distance for the Geometries.
- * @param joins
- * The join type of the offset geometry.
- * @param bevelRatio
- * The ratio used to produce a bevel join instead of a miter join
- * (used only when joins is Miter)
- * @param flattenError
- * The maximum distance of the resulting segments compared to the
- * true circular arc (used only when joins is Round). If
- * flattenError is 0, tolerance value is used. Also, the
- * algorithm never produces more than around 180 vertices for
- * each round join.
+ *
+ * @param inputGeometries The geometries to calculate offset for. Point and MultiPoint
+ * are not supported.
+ * @param sr The SpatialReference of the Geometries.
+ * @param distance The offset distance for the Geometries.
+ * @param joins The join type of the offset geometry.
+ * @param bevelRatio The ratio used to produce a bevel join instead of a miter join
+ * (used only when joins is Miter)
+ * @param flattenError The maximum distance of the resulting segments compared to the
+ * true circular arc (used only when joins is Round). If
+ * flattenError is 0, tolerance value is used. Also, the
+ * algorithm never produces more than around 180 vertices for
+ * each round join.
* @return Returns the result of the offset operation.
*/
public abstract GeometryCursor execute(GeometryCursor inputGeometries,
- SpatialReference sr, double distance, JoinType joins,
- double bevelRatio, double flattenError,
- ProgressTracker progressTracker);
+ SpatialReference sr, double distance, JoinType joins,
+ double bevelRatio, double flattenError,
+ ProgressTracker progressTracker);
/**
* Creates offset version of the input geometry.
- *
+ *
* The offset operation creates a geometry that is a constant distance from
* an input polyline or polygon. It is similar to buffering, but produces a
* one sided result. If offsetDistance greater than 0, then the offset geometry is
@@ -100,35 +95,29 @@ public abstract GeometryCursor execute(GeometryCursor inputGeometries,
* multiplied by the offset distance and the result determines how far a
* mitered offset intersection can be from the input curve before it is
* beveled.
- *
- * @param inputGeometry
- * The geometry to calculate offset for. Point and MultiPoint are
- * not supported.
- * @param sr
- * The SpatialReference of the Geometries.
- * @param distance
- * The offset distance for the Geometries.
- * @param joins
- * The join type of the offset geometry.
- * @param bevelRatio
- * The ratio used to produce a bevel join instead of a miter join
- * (used only when joins is Miter)
- * @param flattenError
- * The maximum distance of the resulting segments compared to the
- * true circular arc (used only when joins is Round). If
- * flattenError is 0, tolerance value is used. Also, the
- * algorithm never produces more than around 180 vetices for each
- * round join.
+ *
+ * @param inputGeometry The geometry to calculate offset for. Point and MultiPoint are
+ * not supported.
+ * @param sr The SpatialReference of the Geometries.
+ * @param distance The offset distance for the Geometries.
+ * @param joins The join type of the offset geometry.
+ * @param bevelRatio The ratio used to produce a bevel join instead of a miter join
+ * (used only when joins is Miter)
+ * @param flattenError The maximum distance of the resulting segments compared to the
+ * true circular arc (used only when joins is Round). If
+ * flattenError is 0, tolerance value is used. Also, the
+ * algorithm never produces more than around 180 vetices for each
+ * round join.
* @return Returns the result of the offset operation.
*/
public abstract Geometry execute(Geometry inputGeometry,
- SpatialReference sr, double distance, JoinType joins,
- double bevelRatio, double flattenError,
- ProgressTracker progressTracker);
+ SpatialReference sr, double distance, JoinType joins,
+ double bevelRatio, double flattenError,
+ ProgressTracker progressTracker);
- public static OperatorOffset local() {
- return (OperatorOffset) OperatorFactoryLocal.getInstance().getOperator(
- Type.Offset);
- }
+ public static OperatorOffset local() {
+ return (OperatorOffset) OperatorFactoryLocal.getInstance().getOperator(
+ Type.Offset);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorOffsetCursor.java b/src/main/java/com/esri/core/geometry/OperatorOffsetCursor.java
index e6ece9f0..303af8f2 100644
--- a/src/main/java/com/esri/core/geometry/OperatorOffsetCursor.java
+++ b/src/main/java/com/esri/core/geometry/OperatorOffsetCursor.java
@@ -25,45 +25,45 @@
// TODO test this, never been public before
public class OperatorOffsetCursor extends GeometryCursor {
- SpatialReferenceImpl m_spatialReference;
- ProgressTracker m_progressTracker;
- double m_distance;
- double m_miterLimit;
- OperatorOffset.JoinType m_joins;
- double m_flattenError;
+ SpatialReferenceImpl m_spatialReference;
+ ProgressTracker m_progressTracker;
+ double m_distance;
+ double m_miterLimit;
+ OperatorOffset.JoinType m_joins;
+ double m_flattenError;
- OperatorOffsetCursor(GeometryCursor inputGeometries,
- SpatialReference sr,
- double distance, OperatorOffset.JoinType joins,
- double bevelRatio,
- double flattenError,
- ProgressTracker progressTracker) {
- m_inputGeoms = inputGeometries;
- m_spatialReference = (SpatialReferenceImpl) sr;
- m_distance = distance;
- m_joins = joins;
- m_miterLimit = bevelRatio;
- m_flattenError = flattenError;
- m_progressTracker = progressTracker;
- }
+ OperatorOffsetCursor(GeometryCursor inputGeometries,
+ SpatialReference sr,
+ double distance, OperatorOffset.JoinType joins,
+ double bevelRatio,
+ double flattenError,
+ ProgressTracker progressTracker) {
+ m_inputGeoms = inputGeometries;
+ m_spatialReference = (SpatialReferenceImpl) sr;
+ m_distance = distance;
+ m_joins = joins;
+ m_miterLimit = bevelRatio;
+ m_flattenError = flattenError;
+ m_progressTracker = progressTracker;
+ }
- @Override
- public Geometry next() {
- if (hasNext())
- return Offset(m_inputGeoms.next());
+ @Override
+ public Geometry next() {
+ if (hasNext())
+ return Offset(m_inputGeoms.next());
- return null;
- }
+ return null;
+ }
- Geometry Offset(Geometry geom) {
- double tolerance;
- if (m_flattenError <= 0)
- tolerance = InternalUtils.calculateToleranceFromGeometry(
- m_spatialReference, geom, false);
- else
- tolerance = m_flattenError;
- return ConstructOffset.execute(geom, m_distance, m_joins, m_miterLimit,
- tolerance, m_progressTracker);
- }
+ Geometry Offset(Geometry geom) {
+ double tolerance;
+ if (m_flattenError <= 0)
+ tolerance = InternalUtils.calculateToleranceFromGeometry(
+ m_spatialReference, geom, false);
+ else
+ tolerance = m_flattenError;
+ return ConstructOffset.execute(geom, m_distance, m_joins, m_miterLimit,
+ tolerance, m_progressTracker);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorOffsetLocal.java b/src/main/java/com/esri/core/geometry/OperatorOffsetLocal.java
index 5381b120..894f2849 100644
--- a/src/main/java/com/esri/core/geometry/OperatorOffsetLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorOffsetLocal.java
@@ -25,24 +25,24 @@
class OperatorOffsetLocal extends OperatorOffset {
- @Override
- public GeometryCursor execute(GeometryCursor inputGeometries,
- SpatialReference sr, double distance, JoinType joins,
- double bevelRatio, double flattenError,
- ProgressTracker progressTracker) {
- return new OperatorOffsetCursor(inputGeometries, sr, distance, joins,
- bevelRatio, flattenError, progressTracker);
- }
-
- @Override
- public Geometry execute(Geometry inputGeometry, SpatialReference sr,
- double distance, JoinType joins, double bevelRatio,
- double flattenError, ProgressTracker progressTracker) {
- SimpleGeometryCursor inputCursor = new SimpleGeometryCursor(
- inputGeometry);
- GeometryCursor outCursor = execute(inputCursor, sr, distance, joins,
- bevelRatio, flattenError, progressTracker);
- return outCursor.next();
- }
+ @Override
+ public GeometryCursor execute(GeometryCursor inputGeometries,
+ SpatialReference sr, double distance, JoinType joins,
+ double bevelRatio, double flattenError,
+ ProgressTracker progressTracker) {
+ return new OperatorOffsetCursor(inputGeometries, sr, distance, joins,
+ bevelRatio, flattenError, progressTracker);
+ }
+
+ @Override
+ public Geometry execute(Geometry inputGeometry, SpatialReference sr,
+ double distance, JoinType joins, double bevelRatio,
+ double flattenError, ProgressTracker progressTracker) {
+ SimpleGeometryCursor inputCursor = new SimpleGeometryCursor(
+ inputGeometry);
+ GeometryCursor outCursor = execute(inputCursor, sr, distance, joins,
+ bevelRatio, flattenError, progressTracker);
+ return outCursor.next();
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorOverlaps.java b/src/main/java/com/esri/core/geometry/OperatorOverlaps.java
index ca2b4905..c7b3b207 100644
--- a/src/main/java/com/esri/core/geometry/OperatorOverlaps.java
+++ b/src/main/java/com/esri/core/geometry/OperatorOverlaps.java
@@ -26,14 +26,14 @@
import com.esri.core.geometry.Operator.Type;
public abstract class OperatorOverlaps extends OperatorSimpleRelation {
- @Override
- public Type getType() {
- return Type.Equals;
- }
-
- public static OperatorOverlaps local() {
- return (OperatorOverlaps) OperatorFactoryLocal.getInstance()
- .getOperator(Type.Overlaps);
- }
+ @Override
+ public Type getType() {
+ return Type.Equals;
+ }
+
+ public static OperatorOverlaps local() {
+ return (OperatorOverlaps) OperatorFactoryLocal.getInstance()
+ .getOperator(Type.Overlaps);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorOverlapsLocal.java b/src/main/java/com/esri/core/geometry/OperatorOverlapsLocal.java
index 1196e6a7..33a81c5e 100644
--- a/src/main/java/com/esri/core/geometry/OperatorOverlapsLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorOverlapsLocal.java
@@ -24,10 +24,10 @@
package com.esri.core.geometry;
class OperatorOverlapsLocal extends OperatorOverlaps {
- @Override
- public boolean execute(Geometry inputGeom1, Geometry inputGeom2,
- SpatialReference sr, ProgressTracker progressTracker) {
- return RelationalOperations.relate(inputGeom1, inputGeom2, sr,
- RelationalOperations.Relation.overlaps, progressTracker);
- }
+ @Override
+ public boolean execute(Geometry inputGeom1, Geometry inputGeom2,
+ SpatialReference sr, ProgressTracker progressTracker) {
+ return RelationalOperations.relate(inputGeom1, inputGeom2, sr,
+ RelationalOperations.Relation.overlaps, progressTracker);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorProject.java b/src/main/java/com/esri/core/geometry/OperatorProject.java
index 3b9cc296..9f5fe8b2 100644
--- a/src/main/java/com/esri/core/geometry/OperatorProject.java
+++ b/src/main/java/com/esri/core/geometry/OperatorProject.java
@@ -28,135 +28,135 @@
*/
public abstract class OperatorProject extends Operator {
- @Override
- public Type getType() {
- return Type.Project;
- }
-
- /**
- * Performs the Project operation on a geometry cursor
- *
- * @return Returns a GeometryCursor.
- */
- public abstract GeometryCursor execute(GeometryCursor inputGeoms,
- ProjectionTransformation projection,
- ProgressTracker progressTracker);
-
- /**
- * Performs the Project operation on a single geometry instance
- *
- * @return Returns the Geometry after projection
- */
- public abstract Geometry execute(Geometry geometry,
- ProjectionTransformation projection,
- ProgressTracker progressTracker);
-
- /**
- * Transforms an array of points. Returns the number of points transformed.
- */
- public abstract int transform(ProjectionTransformation transform,
- Point[] coordsSrc,
- int length,
- Point[] coordsDst) throws org.proj4.PJException;
-
- /**
- * Transforms an array of 2D points and returns it. The points are stored in
- * an interleaved array (x0, y0, x1, y1, x2, y2, ...).
- *
- * @param transform ProjectionTransformation
- * @param coordsSrc source coordinates to project.
- * @param pointCount the point count in the coordSrc. THere has to be at least
- * pointCount * 2 elements in the coordsSrc array.
- * @param bHasZ does the coordSrc array include z values
- * @return projected coordinates in the interleaved form.
- */
- public abstract double[] transform(ProjectionTransformation transform,
- double[] coordsSrc,
- int pointCount,
- boolean bHasZ) throws org.proj4.PJException;
-
- /**
- * Folds a geometry into the 360 degree range of the associated spatial reference. If the spatial reference be a 'pannable' PROJECTED or GEOGRAPHIC. For other spatial types, the function throws an invalid
- * argument exception. A pannable PROJECTED it a Rectangular PROJECTED where the x coordinate range is equivalent to a 360 degree range on the defining geographic Coordinate System(GEOGRAPHIC). If the spatial
- * reference is a GEOGRAPHIC then it is always pannable(default 360 range for spatial reference in GEOGRAPHIC coordinates is -180 to 180)
- *
- * If the geometry is an Envelope fold_into_360_range returns a polygon, unless the Envelope is empty, in which case the empty envelope is returned. The result geometry will be completely inside of
- * the coordinate system extent. The folding happens where geometry intersects the min or max meridian of the spatial reference and when geometry is completely outside of the min-max meridian range.
- * Folding does not preserve geodetic area or length. Folding does not preserve perimeter of a polygon.
- *
- * @param geom The geometry to be folded.
- * @param pannableSR The pannable Spatial Reference.
- * @return Folded geometry.
- */
- public static Geometry foldInto360Range(Geometry geom, SpatialReference pannableSR) {
- Envelope2D envelope2D = new Envelope2D();
- geom.queryEnvelope2D(envelope2D);
- if (envelope2D.xmax <= 180.0 && envelope2D.xmin >= -180.0) {
- return geom;
- }
-
- // clip by -180 and 180
- MultiPath foldedGeometry = null;
-
- if (geom.getType() != Geometry.Type.Polyline && geom.getType() != Geometry.Type.Polygon)
- return geom;
-
- MultiPathImpl multiPath = (MultiPathImpl)geom._getImpl();
- if (geom.getType() == Geometry.Type.Polygon) {
- foldedGeometry = new Polygon(multiPath.m_description);
- } else if (geom.getType() == Geometry.Type.Polyline) {
- foldedGeometry = new Polyline(multiPath.m_description);
- }
-
- // TODO this should be a static class member
- Polyline cuttee1 = new Polyline();
- cuttee1.startPath(-180, 90);
- cuttee1.lineTo(-180, -90);
- cuttee1.startPath(180, 90);
- cuttee1.lineTo(180, -90);
- Geometry[] parts = GeometryEngine.cut(geom, cuttee1, pannableSR);
-
- if (parts.length == 0) {
- parts = new Geometry[] {geom};
- }
-
- for (Geometry geometryPart : parts) {
- geometryPart.queryEnvelope2D(envelope2D);
- // TODO this only accounts for geometries with lat lon rang of -540 to 540
- if (envelope2D.xmin < -180) {
- // add 180 to all vertices in geometry
- // TODO this should be a static class member
- Transformation2D transformation2D = new Transformation2D();
- transformation2D.xd = 360;
- geometryPart.applyTransformation(transformation2D);
- }
- if (envelope2D.xmax > 180) {
- // TODO this should be a static class member
- Transformation2D transformation2D = new Transformation2D();
- transformation2D.xd = -360;
- geometryPart.applyTransformation(transformation2D);
- }
- foldedGeometry.add((MultiPath) geometryPart, false);
- }
-
- return foldedGeometry;
- }
-
- /**
- * Same as fold_into_360_range. The difference is that this function preserves geodetic area of polygons and geodetic length of polylines. It does not preserve regular area and length or perimeter
- * of polygons. Also, this function might change tangent of the lines at the points of folding.
- *
- * If the geometry is an Envelope fold_into_360_range returns a polygon, unless the Envelope is empty, in which case the empty envelope is returned. The result geometry will be completely inside of
- * the coordinate system extent. The folding happens where geometry intersects the min or max meridian of the spatial reference and when geometry is completely outside of the min-max meridian range.
- *
- * @param geom The geometry to be folded.
- * @param pannableSR The pannable Spatial Reference.
- * @param curveType The type of geodetic curve to use to produce vertices at the points of folding. \return Folded geometry.
- */
- public abstract Geometry foldInto360RangeGeodetic(Geometry geom, SpatialReference pannableSR, int curveType);
-
- public static OperatorProject local() {
- return (OperatorProject) OperatorFactoryLocal.getInstance().getOperator(Type.Project);
- }
+ @Override
+ public Type getType() {
+ return Type.Project;
+ }
+
+ /**
+ * Performs the Project operation on a geometry cursor
+ *
+ * @return Returns a GeometryCursor.
+ */
+ public abstract GeometryCursor execute(GeometryCursor inputGeoms,
+ ProjectionTransformation projection,
+ ProgressTracker progressTracker);
+
+ /**
+ * Performs the Project operation on a single geometry instance
+ *
+ * @return Returns the Geometry after projection
+ */
+ public abstract Geometry execute(Geometry geometry,
+ ProjectionTransformation projection,
+ ProgressTracker progressTracker);
+
+ /**
+ * Transforms an array of points. Returns the number of points transformed.
+ */
+ public abstract int transform(ProjectionTransformation transform,
+ Point[] coordsSrc,
+ int length,
+ Point[] coordsDst) throws org.proj4.PJException;
+
+ /**
+ * Transforms an array of 2D points and returns it. The points are stored in
+ * an interleaved array (x0, y0, x1, y1, x2, y2, ...).
+ *
+ * @param transform ProjectionTransformation
+ * @param coordsSrc source coordinates to project.
+ * @param pointCount the point count in the coordSrc. THere has to be at least
+ * pointCount * 2 elements in the coordsSrc array.
+ * @param bHasZ does the coordSrc array include z values
+ * @return projected coordinates in the interleaved form.
+ */
+ public abstract double[] transform(ProjectionTransformation transform,
+ double[] coordsSrc,
+ int pointCount,
+ boolean bHasZ) throws org.proj4.PJException;
+
+ /**
+ * Folds a geometry into the 360 degree range of the associated spatial reference. If the spatial reference be a 'pannable' PROJECTED or GEOGRAPHIC. For other spatial types, the function throws an invalid
+ * argument exception. A pannable PROJECTED it a Rectangular PROJECTED where the x coordinate range is equivalent to a 360 degree range on the defining geographic Coordinate System(GEOGRAPHIC). If the spatial
+ * reference is a GEOGRAPHIC then it is always pannable(default 360 range for spatial reference in GEOGRAPHIC coordinates is -180 to 180)
+ *
+ * If the geometry is an Envelope fold_into_360_range returns a polygon, unless the Envelope is empty, in which case the empty envelope is returned. The result geometry will be completely inside of
+ * the coordinate system extent. The folding happens where geometry intersects the min or max meridian of the spatial reference and when geometry is completely outside of the min-max meridian range.
+ * Folding does not preserve geodetic area or length. Folding does not preserve perimeter of a polygon.
+ *
+ * @param geom The geometry to be folded.
+ * @param pannableSR The pannable Spatial Reference.
+ * @return Folded geometry.
+ */
+ public static Geometry foldInto360Range(Geometry geom, SpatialReference pannableSR) {
+ Envelope2D envelope2D = new Envelope2D();
+ geom.queryEnvelope2D(envelope2D);
+ if (envelope2D.xmax <= 180.0 && envelope2D.xmin >= -180.0) {
+ return geom;
+ }
+
+ // clip by -180 and 180
+ MultiPath foldedGeometry = null;
+
+ if (geom.getType() != Geometry.Type.Polyline && geom.getType() != Geometry.Type.Polygon)
+ return geom;
+
+ MultiPathImpl multiPath = (MultiPathImpl) geom._getImpl();
+ if (geom.getType() == Geometry.Type.Polygon) {
+ foldedGeometry = new Polygon(multiPath.m_description);
+ } else if (geom.getType() == Geometry.Type.Polyline) {
+ foldedGeometry = new Polyline(multiPath.m_description);
+ }
+
+ // TODO this should be a static class member
+ Polyline cuttee1 = new Polyline();
+ cuttee1.startPath(-180, 90);
+ cuttee1.lineTo(-180, -90);
+ cuttee1.startPath(180, 90);
+ cuttee1.lineTo(180, -90);
+ Geometry[] parts = GeometryEngine.cut(geom, cuttee1, pannableSR);
+
+ if (parts.length == 0) {
+ parts = new Geometry[]{geom};
+ }
+
+ for (Geometry geometryPart : parts) {
+ geometryPart.queryEnvelope2D(envelope2D);
+ // TODO this only accounts for geometries with lat lon rang of -540 to 540
+ if (envelope2D.xmin < -180) {
+ // add 180 to all vertices in geometry
+ // TODO this should be a static class member
+ Transformation2D transformation2D = new Transformation2D();
+ transformation2D.xd = 360;
+ geometryPart.applyTransformation(transformation2D);
+ }
+ if (envelope2D.xmax > 180) {
+ // TODO this should be a static class member
+ Transformation2D transformation2D = new Transformation2D();
+ transformation2D.xd = -360;
+ geometryPart.applyTransformation(transformation2D);
+ }
+ foldedGeometry.add((MultiPath) geometryPart, false);
+ }
+
+ return foldedGeometry;
+ }
+
+ /**
+ * Same as fold_into_360_range. The difference is that this function preserves geodetic area of polygons and geodetic length of polylines. It does not preserve regular area and length or perimeter
+ * of polygons. Also, this function might change tangent of the lines at the points of folding.
+ *
+ * If the geometry is an Envelope fold_into_360_range returns a polygon, unless the Envelope is empty, in which case the empty envelope is returned. The result geometry will be completely inside of
+ * the coordinate system extent. The folding happens where geometry intersects the min or max meridian of the spatial reference and when geometry is completely outside of the min-max meridian range.
+ *
+ * @param geom The geometry to be folded.
+ * @param pannableSR The pannable Spatial Reference.
+ * @param curveType The type of geodetic curve to use to produce vertices at the points of folding. \return Folded geometry.
+ */
+ public abstract Geometry foldInto360RangeGeodetic(Geometry geom, SpatialReference pannableSR, int curveType);
+
+ public static OperatorProject local() {
+ return (OperatorProject) OperatorFactoryLocal.getInstance().getOperator(Type.Project);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorProjectCursor.java b/src/main/java/com/esri/core/geometry/OperatorProjectCursor.java
index 995c8a28..0a4724d3 100644
--- a/src/main/java/com/esri/core/geometry/OperatorProjectCursor.java
+++ b/src/main/java/com/esri/core/geometry/OperatorProjectCursor.java
@@ -4,24 +4,24 @@
* Created by davidraleigh on 5/12/17.
*/
public class OperatorProjectCursor extends GeometryCursor {
- ProjectionTransformation m_projectionTransformation;
- ProgressTracker m_progressTracker;
+ ProjectionTransformation m_projectionTransformation;
+ ProgressTracker m_progressTracker;
- OperatorProjectCursor(
- GeometryCursor inputGeoms,
- ProjectionTransformation projectionTransformation,
- ProgressTracker progressTracker) {
- m_inputGeoms = inputGeoms;
- m_projectionTransformation = projectionTransformation;
- m_progressTracker = progressTracker;
- }
+ OperatorProjectCursor(
+ GeometryCursor inputGeoms,
+ ProjectionTransformation projectionTransformation,
+ ProgressTracker progressTracker) {
+ m_inputGeoms = inputGeoms;
+ m_projectionTransformation = projectionTransformation;
+ m_progressTracker = progressTracker;
+ }
- @Override
- public Geometry next() {
- if (m_inputGeoms.hasNext()) {
- Geometry geometry = m_inputGeoms.next();
- return Projecter.project(geometry, m_projectionTransformation, m_progressTracker);
- }
- return null;
- }
+ @Override
+ public Geometry next() {
+ if (m_inputGeoms.hasNext()) {
+ Geometry geometry = m_inputGeoms.next();
+ return Projecter.project(geometry, m_projectionTransformation, m_progressTracker);
+ }
+ return null;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorProjectLocal.java b/src/main/java/com/esri/core/geometry/OperatorProjectLocal.java
index 49386c12..62b442aa 100644
--- a/src/main/java/com/esri/core/geometry/OperatorProjectLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorProjectLocal.java
@@ -31,37 +31,37 @@
//This is a stub
class OperatorProjectLocal extends OperatorProject {
- @Override
- public GeometryCursor execute(GeometryCursor inputGeoms,
- ProjectionTransformation transform,
- ProgressTracker progressTracker) {
- return new OperatorProjectCursor(inputGeoms, transform, progressTracker);
- }
+ @Override
+ public GeometryCursor execute(GeometryCursor inputGeoms,
+ ProjectionTransformation transform,
+ ProgressTracker progressTracker) {
+ return new OperatorProjectCursor(inputGeoms, transform, progressTracker);
+ }
- public Geometry execute(Geometry inputGeom,
- ProjectionTransformation transform,
- ProgressTracker progressTracker) {
- return execute(new SimpleGeometryCursor(inputGeom), transform, progressTracker).next();
- }
+ public Geometry execute(Geometry inputGeom,
+ ProjectionTransformation transform,
+ ProgressTracker progressTracker) {
+ return execute(new SimpleGeometryCursor(inputGeom), transform, progressTracker).next();
+ }
- @Override
- public int transform(ProjectionTransformation transform,
- Point[] pointsIn,
- int count,
- Point[] pointsOut) throws org.proj4.PJException {
- return Projecter.transform(transform, pointsIn, count, pointsOut);
- }
+ @Override
+ public int transform(ProjectionTransformation transform,
+ Point[] pointsIn,
+ int count,
+ Point[] pointsOut) throws org.proj4.PJException {
+ return Projecter.transform(transform, pointsIn, count, pointsOut);
+ }
- public double[] transform(ProjectionTransformation transform,
- double[] coordsSrc,
- int pointCount,
- boolean bHasZ) throws org.proj4.PJException {
- return Projecter.transform(transform, coordsSrc, bHasZ);
- }
+ public double[] transform(ProjectionTransformation transform,
+ double[] coordsSrc,
+ int pointCount,
+ boolean bHasZ) throws org.proj4.PJException {
+ return Projecter.transform(transform, coordsSrc, bHasZ);
+ }
- @Override
- public Geometry foldInto360RangeGeodetic(Geometry _geom, SpatialReference pannableSR, int curveType) {
- return _geom;
- }
+ @Override
+ public Geometry foldInto360RangeGeodetic(Geometry _geom, SpatialReference pannableSR, int curveType) {
+ return _geom;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorProximity2D.java b/src/main/java/com/esri/core/geometry/OperatorProximity2D.java
index 6b40d72f..bb7e19e1 100644
--- a/src/main/java/com/esri/core/geometry/OperatorProximity2D.java
+++ b/src/main/java/com/esri/core/geometry/OperatorProximity2D.java
@@ -30,70 +30,70 @@
* Finds closest vertices of the Geometry.
*/
public abstract class OperatorProximity2D extends Operator {
- @Override
- public Type getType() {
- return Type.Proximity2D;
- }
+ @Override
+ public Type getType() {
+ return Type.Proximity2D;
+ }
- /**
- * Returns the nearest coordinate on the Geometry to the given input point.
- *
- * @param geom The input Geometry.
- * @param inputPoint The query point.
- * @param bTestPolygonInterior When true and geom is a polygon, the function will test if the input_point is inside of the polygon. Points that are
- * inside of the polygon have zero distance to the polygon. When false, the function will not check if the point is inside of the polygon,
- * but only determine proximity to the boundary.
- * @param bCalculateLeftRightSide The function will calculate left/right side of polylines or polygons when the parameter is True.
- * \return Returns the result of proximity calculation. See Proximity_2D_result.
- */
- public abstract Proximity2DResult getNearestCoordinate(Geometry geom,
- Point inputPoint, boolean bTestPolygonInterior,
- boolean bCalculateLeftRightSide);
+ /**
+ * Returns the nearest coordinate on the Geometry to the given input point.
+ *
+ * @param geom The input Geometry.
+ * @param inputPoint The query point.
+ * @param bTestPolygonInterior When true and geom is a polygon, the function will test if the input_point is inside of the polygon. Points that are
+ * inside of the polygon have zero distance to the polygon. When false, the function will not check if the point is inside of the polygon,
+ * but only determine proximity to the boundary.
+ * @param bCalculateLeftRightSide The function will calculate left/right side of polylines or polygons when the parameter is True.
+ * \return Returns the result of proximity calculation. See Proximity_2D_result.
+ */
+ public abstract Proximity2DResult getNearestCoordinate(Geometry geom,
+ Point inputPoint, boolean bTestPolygonInterior,
+ boolean bCalculateLeftRightSide);
- /**
- * Returns the nearest coordinate on the Geometry to the given input point.
- *
- * @param geom The input Geometry.
- * @param inputPoint The query point.
- * @param bTestPolygonInterior When true and geom is a polygon, the function will test if the input_point is inside of the polygon. Points that are
- * inside of the polygon have zero distance to the polygon. When false, the function will not check if the point is inside of the polygon,
- * but only determine proximity to the boundary.
- * \return Returns the result of proximity calculation. See Proximity_2D_result.
- */
- public abstract Proximity2DResult getNearestCoordinate(Geometry geom,
- Point inputPoint, boolean bTestPolygonInterior);
+ /**
+ * Returns the nearest coordinate on the Geometry to the given input point.
+ *
+ * @param geom The input Geometry.
+ * @param inputPoint The query point.
+ * @param bTestPolygonInterior When true and geom is a polygon, the function will test if the input_point is inside of the polygon. Points that are
+ * inside of the polygon have zero distance to the polygon. When false, the function will not check if the point is inside of the polygon,
+ * but only determine proximity to the boundary.
+ * \return Returns the result of proximity calculation. See Proximity_2D_result.
+ */
+ public abstract Proximity2DResult getNearestCoordinate(Geometry geom,
+ Point inputPoint, boolean bTestPolygonInterior);
- /**
- * Returns the nearest vertex of the Geometry to the given input point.
- */
- public abstract Proximity2DResult getNearestVertex(Geometry geom,
- Point inputPoint);
+ /**
+ * Returns the nearest vertex of the Geometry to the given input point.
+ */
+ public abstract Proximity2DResult getNearestVertex(Geometry geom,
+ Point inputPoint);
- /**
- * Returns vertices of the Geometry that are closer to the given point than
- * the given radius.
- *
- * @param geom The input Geometry.
- * @param inputPoint The query point.
- * @param searchRadius The maximum distance to the query point of the vertices.
- * @param maxVertexCountToReturn The maximum vertex count to return. The function returns no
- * more than this number of vertices.
- * @return The array of vertices that are in the given search radius to the
- * point. The array is sorted by distance to the queryPoint with the
- * closest point first. When there are more than the
- * maxVertexCountToReturn vertices to return, it returns the closest
- * vertices. The array will be empty when geom is empty.
- */
- public abstract Proximity2DResult[] getNearestVertices(Geometry geom,
- Point inputPoint, double searchRadius, int maxVertexCountToReturn);
+ /**
+ * Returns vertices of the Geometry that are closer to the given point than
+ * the given radius.
+ *
+ * @param geom The input Geometry.
+ * @param inputPoint The query point.
+ * @param searchRadius The maximum distance to the query point of the vertices.
+ * @param maxVertexCountToReturn The maximum vertex count to return. The function returns no
+ * more than this number of vertices.
+ * @return The array of vertices that are in the given search radius to the
+ * point. The array is sorted by distance to the queryPoint with the
+ * closest point first. When there are more than the
+ * maxVertexCountToReturn vertices to return, it returns the closest
+ * vertices. The array will be empty when geom is empty.
+ */
+ public abstract Proximity2DResult[] getNearestVertices(Geometry geom,
+ Point inputPoint, double searchRadius, int maxVertexCountToReturn);
- public static OperatorProximity2D local() {
- return (OperatorProximity2D) OperatorFactoryLocal.getInstance()
- .getOperator(Type.Proximity2D);
- }
+ public static OperatorProximity2D local() {
+ return (OperatorProximity2D) OperatorFactoryLocal.getInstance()
+ .getOperator(Type.Proximity2D);
+ }
- interface ProxResultInfo {
- static final int rightSide = 0x1;
- }
+ interface ProxResultInfo {
+ static final int rightSide = 0x1;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorProximity2DLocal.java b/src/main/java/com/esri/core/geometry/OperatorProximity2DLocal.java
index 7b6969d7..832ad712 100644
--- a/src/main/java/com/esri/core/geometry/OperatorProximity2DLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorProximity2DLocal.java
@@ -31,511 +31,511 @@
class OperatorProximity2DLocal extends OperatorProximity2D {
- class Side_helper {
- int m_i1;
- int m_i2;
- boolean m_bRight1;
- boolean m_bRight2;
-
- void reset() {
- m_i1 = -1;
- m_i2 = -1;
- m_bRight1 = false;
- m_bRight2 = false;
- }
-
- int find_non_degenerate(SegmentIterator segIter, int vertexIndex,
- int pathIndex) {
- segIter.resetToVertex(vertexIndex, pathIndex);
-
- while (segIter.hasNextSegment()) {
- Segment segment = segIter.nextSegment();
- double length = segment.calculateLength2D();
-
- if (length != 0.0)
- return segIter.getStartPointIndex();
- }
-
- segIter.resetToVertex(vertexIndex, pathIndex);
-
- while (segIter.hasPreviousSegment()) {
- Segment segment = segIter.previousSegment();
- double length = segment.calculateLength2D();
-
- if (length != 0)
- return segIter.getStartPointIndex();
- }
-
- return -1;
- }
-
- int find_prev_non_degenerate(SegmentIterator segIter, int index) {
- segIter.resetToVertex(index, -1);
-
- while (segIter.hasPreviousSegment()) {
- Segment segment = segIter.previousSegment();
- double length = segment.calculateLength2D();
-
- if (length != 0)
- return segIter.getStartPointIndex();
- }
-
- return -1;
- }
-
- int find_next_non_degenerate(SegmentIterator segIter, int index) {
- segIter.resetToVertex(index, -1);
- segIter.nextSegment();
-
- while (segIter.hasNextSegment()) {
- Segment segment = segIter.nextSegment();
- double length = segment.calculateLength2D();
-
- if (length != 0)
- return segIter.getStartPointIndex();
- }
-
- return -1;
- }
-
- void find_analysis_pair_from_index(Point2D inputPoint,
- SegmentIterator segIter, int vertexIndex, int pathIndex) {
- m_i1 = find_non_degenerate(segIter, vertexIndex, pathIndex);
-
- if (m_i1 != -1) {
- segIter.resetToVertex(m_i1, -1);
- Segment segment1 = segIter.nextSegment();
- double t1 = segment1.getClosestCoordinate(inputPoint, false);
- Point2D p1 = segment1.getCoord2D(t1);
- double d1 = Point2D.sqrDistance(p1, inputPoint);
- Point2D pq = new Point2D();
- pq.setCoords(p1);
- pq.sub(segment1.getStartXY());
- Point2D pr = new Point2D();
- pr.setCoords(inputPoint);
- pr.sub(segment1.getStartXY());
- m_bRight1 = (pq.crossProduct(pr) < 0);
-
- m_i2 = find_next_non_degenerate(segIter, m_i1);
- if (m_i2 != -1) {
- segIter.resetToVertex(m_i2, -1);
- Segment segment2 = segIter.nextSegment();
- double t2 = segment2
- .getClosestCoordinate(inputPoint, false);
- Point2D p2 = segment2.getCoord2D(t2);
- double d2 = Point2D.sqrDistance(p2, inputPoint);
-
- if (d2 > d1) {
- m_i2 = -1;
- } else {
- pq.setCoords(p2);
- pq.sub(segment2.getStartXY());
- pr.setCoords(inputPoint);
- pr.sub(segment2.getStartXY());
- m_bRight2 = (pq.crossProduct(pr) < 0);
- }
- }
-
- if (m_i2 == -1) {
- m_i2 = find_prev_non_degenerate(segIter, m_i1);
- if (m_i2 != -1) {
- segIter.resetToVertex(m_i2, -1);
- Segment segment2 = segIter.nextSegment();
- double t2 = segment2.getClosestCoordinate(inputPoint,
- false);
- Point2D p2 = segment2.getCoord2D(t2);
- double d2 = Point2D.sqrDistance(p2, inputPoint);
-
- if (d2 > d1)
- m_i2 = -1;
- else {
- pq.setCoords(p2);
- pq.sub(segment2.getStartXY());
- pr.setCoords(inputPoint);
- pr.sub(segment2.getStartXY());
- m_bRight2 = (pq.crossProduct(pr) < 0);
-
- int itemp = m_i1;
- m_i1 = m_i2;
- m_i2 = itemp;
-
- boolean btemp = m_bRight1;
- m_bRight1 = m_bRight2;
- m_bRight2 = btemp;
- }
- }
- }
- }
- }
-
- // Try to find two segements that are not degenerate
- boolean calc_side(Point2D inputPoint, boolean bRight,
- MultiPath multipath, int vertexIndex, int pathIndex) {
- SegmentIterator segIter = multipath.querySegmentIterator();
-
- find_analysis_pair_from_index(inputPoint, segIter, vertexIndex,
- pathIndex);
-
- if (m_i1 != -1 && m_i2 == -1) {// could not find a pair of segments
- return m_bRight1;
- }
-
- if (m_i1 != -1 && m_i2 != -1) {
- if (m_bRight1 == m_bRight2)
- return m_bRight1;// no conflicting result for the side
- else {
- // the conflicting result, that we are trying to resolve,
- // happens in the obtuse (outer) side of the turn only.
- segIter.resetToVertex(m_i1, -1);
- Segment segment1 = segIter.nextSegment();
- Point2D tang1 = segment1._getTangent(1.0);
-
- segIter.resetToVertex(m_i2, -1);
- Segment segment2 = segIter.nextSegment();
- Point2D tang2 = segment2._getTangent(0.0);
-
- double cross = tang1.crossProduct(tang2);
-
- if (cross >= 0) // the obtuse angle is on the right side
- {
- return true;
- } else // the obtuse angle is on the right side
- {
- return false;
- }
- }
- } else {
- assert (m_i1 == -1 && m_i2 == -1);
- return bRight;// could not resolve the side. So just return the
- // old value.
- }
- }
- }
-
- @Override
- public Proximity2DResult getNearestCoordinate(Geometry geom,
- Point inputPoint, boolean bTestPolygonInterior) {
-
- return getNearestCoordinate(geom, inputPoint, bTestPolygonInterior,
- false);
- }
-
- @Override
- public Proximity2DResult getNearestCoordinate(Geometry geom,
- Point inputPoint, boolean bTestPolygonInterior,
- boolean bCalculateLeftRightSide) {
- if (geom.isEmpty())
- return new Proximity2DResult();
-
- Point2D inputPoint2D = inputPoint.getXY();
-
- Geometry proxmityTestGeom = geom;
- int gt = geom.getType().value();
-
- if (gt == Geometry.GeometryType.Envelope) {
- Polygon polygon = new Polygon();
- polygon.addEnvelope((Envelope) geom, false);
- proxmityTestGeom = polygon;
- gt = Geometry.GeometryType.Polygon;
- }
- switch (gt) {
- case Geometry.GeometryType.Point:
- return pointGetNearestVertex((Point) proxmityTestGeom, inputPoint2D);
- case Geometry.GeometryType.MultiPoint:
- return multiVertexGetNearestVertex(
- (MultiVertexGeometry) proxmityTestGeom, inputPoint2D);
- case Geometry.GeometryType.Polyline:
- case Geometry.GeometryType.Polygon:
- return multiPathGetNearestCoordinate((MultiPath) proxmityTestGeom,
- inputPoint2D, bTestPolygonInterior, bCalculateLeftRightSide);
- default: {
- throw new GeometryException("not implemented");
- }
- }
- }
-
- @Override
- public Proximity2DResult getNearestVertex(Geometry geom, Point inputPoint) {
- if (geom.isEmpty())
- return new Proximity2DResult();
-
- Point2D inputPoint2D = inputPoint.getXY();
-
- Geometry proxmityTestGeom = geom;
- int gt = geom.getType().value();
-
- if (gt == Geometry.GeometryType.Envelope) {
- Polygon polygon = new Polygon();
- polygon.addEnvelope((Envelope) geom, false);
- proxmityTestGeom = polygon;
- gt = Geometry.GeometryType.Polygon;
- }
- switch (gt) {
- case Geometry.GeometryType.Point:
- return pointGetNearestVertex((Point) proxmityTestGeom, inputPoint2D);
- case Geometry.GeometryType.MultiPoint:
- case Geometry.GeometryType.Polyline:
- case Geometry.GeometryType.Polygon:
- return multiVertexGetNearestVertex(
- (MultiVertexGeometry) proxmityTestGeom, inputPoint2D);
- default: {
- throw new GeometryException("not implemented");
- }
- }
- }
-
- @Override
- public Proximity2DResult[] getNearestVertices(Geometry geom,
- Point inputPoint, double searchRadius, int maxVertexCountToReturn) {
- if (maxVertexCountToReturn < 0)
- throw new IllegalArgumentException();
-
- if (geom.isEmpty())
- return new Proximity2DResult[]{};
-
- Point2D inputPoint2D = inputPoint.getXY();
-
- Geometry proxmityTestGeom = geom;
- int gt = geom.getType().value();
-
- if (gt == Geometry.GeometryType.Envelope) {
- Polygon polygon = new Polygon();
- polygon.addEnvelope((Envelope) geom, false);
- proxmityTestGeom = polygon;
- gt = Geometry.GeometryType.Polygon;
- }
- switch (gt) {
- case Geometry.GeometryType.Point:
- return pointGetNearestVertices((Point) proxmityTestGeom,
- inputPoint2D, searchRadius, maxVertexCountToReturn);
- case Geometry.GeometryType.MultiPoint:
- case Geometry.GeometryType.Polyline:
- case Geometry.GeometryType.Polygon:
- return multiVertexGetNearestVertices(
- (MultiVertexGeometry) proxmityTestGeom, inputPoint2D,
- searchRadius, maxVertexCountToReturn);
- default: {
- throw new GeometryException("not implemented");
- }
- }
- }
-
- Proximity2DResult multiPathGetNearestCoordinate(MultiPath geom,
- Point2D inputPoint, boolean bTestPolygonInterior,
- boolean bCalculateLeftRightSide) {
- if (geom.getType() == Geometry.Type.Polygon && bTestPolygonInterior) {
- Envelope2D env = new Envelope2D();
- geom.queryEnvelope2D(env);
- double tolerance = InternalUtils.calculateToleranceFromGeometry(
- null, env, false);
-
- PolygonUtils.PiPResult pipResult;
-
- if (bCalculateLeftRightSide)
- pipResult = PolygonUtils.isPointInPolygon2D((Polygon) geom,
- inputPoint, 0.0);
- else
- pipResult = PolygonUtils.isPointInPolygon2D((Polygon) geom,
- inputPoint, tolerance);
-
- if (pipResult != PolygonUtils.PiPResult.PiPOutside) {
- Proximity2DResult result = new Proximity2DResult(inputPoint, 0,
- 0.0);
-
- if (bCalculateLeftRightSide)
- result.setRightSide(true);
-
- return result;
- }
- }
-
- SegmentIterator segIter = geom.querySegmentIterator();
-
- Point2D closest = new Point2D();
- int closestVertexIndex = -1;
- int closestPathIndex = -1;
- double closestDistanceSq = NumberUtils.doubleMax();
- boolean bRight = false;
- int num_candidates = 0;
-
- while (segIter.nextPath()) {
- while (segIter.hasNextSegment()) {
- Segment segment = segIter.nextSegment();
- double t = segment.getClosestCoordinate(inputPoint, false);
-
- Point2D point = segment.getCoord2D(t);
-
- double distanceSq = Point2D.sqrDistance(point, inputPoint);
- if (distanceSq < closestDistanceSq) {
- num_candidates = 1;
- closest = point;
- closestVertexIndex = segIter.getStartPointIndex();
- closestPathIndex = segIter.getPathIndex();
- closestDistanceSq = distanceSq;
- } else if (distanceSq == closestDistanceSq) {
- num_candidates++;
- }
- }
- }
-
- Proximity2DResult result = new Proximity2DResult(closest,
- closestVertexIndex, Math.sqrt(closestDistanceSq));
-
- if (bCalculateLeftRightSide) {
- segIter.resetToVertex(closestVertexIndex, closestPathIndex);
- Segment segment = segIter.nextSegment();
- bRight = (Point2D.orientationRobust(inputPoint,
- segment.getStartXY(), segment.getEndXY()) < 0);
-
- if (num_candidates > 1) {
- Side_helper sideHelper = new Side_helper();
- sideHelper.reset();
- bRight = sideHelper.calc_side(inputPoint, bRight, geom,
- closestVertexIndex, closestPathIndex);
- }
-
- result.setRightSide(bRight);
- }
-
- return result;
- }
-
- Proximity2DResult pointGetNearestVertex(Point geom, Point2D input_point) {
- Point2D pt = geom.getXY();
- double distance = Point2D.distance(pt, input_point);
- return new Proximity2DResult(pt, 0, distance);
- }
-
- Proximity2DResult multiVertexGetNearestVertex(MultiVertexGeometry geom,
- Point2D inputPoint) {
- MultiVertexGeometryImpl mpImpl = (MultiVertexGeometryImpl) geom
- ._getImpl();
- AttributeStreamOfDbl position = (AttributeStreamOfDbl) mpImpl
- .getAttributeStreamRef((Semantics.POSITION));
- int pointCount = geom.getPointCount();
-
- int closestIndex = 0;
- double closestx = 0.0;
- double closesty = 0.0;
- double closestDistanceSq = NumberUtils.doubleMax();
- for (int i = 0; i < pointCount; i++) {
- Point2D pt = new Point2D();
- position.read(2 * i, pt);
-
- double distanceSq = Point2D.sqrDistance(pt, inputPoint);
- if (distanceSq < closestDistanceSq) {
- closestx = pt.x;
- closesty = pt.y;
- closestIndex = i;
- closestDistanceSq = distanceSq;
- }
- }
-
- Proximity2DResult result = new Proximity2DResult();
- result._setParams(closestx, closesty, closestIndex,
- Math.sqrt(closestDistanceSq));
-
- return result;
- }
-
- Proximity2DResult[] pointGetNearestVertices(Point geom, Point2D inputPoint,
- double searchRadius, int maxVertexCountToReturn) {
- Proximity2DResult[] resultArray;
-
- if (maxVertexCountToReturn == 0) {
- resultArray = new Proximity2DResult[]{};
- return resultArray;
- }
-
- double searchRadiusSq = searchRadius * searchRadius;
- Point2D pt = geom.getXY();
-
- double distanceSq = Point2D.sqrDistance(pt, inputPoint);
- if (distanceSq <= searchRadiusSq) {
- resultArray = new Proximity2DResult[1];
-
- Proximity2DResult result = new Proximity2DResult();
- result._setParams(pt.x, pt.y, 0, Math.sqrt(distanceSq));
- resultArray[0] = result;
- } else {
- resultArray = new Proximity2DResult[0];
- }
-
- return resultArray;
- }
-
- Proximity2DResult[] multiVertexGetNearestVertices(MultiVertexGeometry geom,
- Point2D inputPoint, double searchRadius, int maxVertexCountToReturn) {
- Proximity2DResult[] resultArray;
-
- if (maxVertexCountToReturn == 0) {
- resultArray = new Proximity2DResult[0];
- return resultArray;
- }
-
- MultiVertexGeometryImpl mpImpl = (MultiVertexGeometryImpl) geom
- ._getImpl();
- AttributeStreamOfDbl position = (AttributeStreamOfDbl) mpImpl
- .getAttributeStreamRef((Semantics.POSITION));
- int pointCount = geom.getPointCount();
-
- ArrayList
- * The operation always starts from the lowest point on the segment, thus guaranteeing that topologically equal segments are always densified exactly the same.
- */
- public abstract GeometryCursor execute(GeometryCursor geoms, SpatialReference sr, double maxLengthMeters, double maxDeviationMeters, double reserved, ProgressTracker progressTracker);
+ /**
+ * Performs the Shape Preserving Densify operation on the geometry set. Attributes are interpolated along the scalar t-values of the input segments obtained from the length ratios along the
+ * densified segments.
+ *
+ * @param geoms The geometries to be densified.
+ * @param sr The spatial reference of the geometries.
+ * @param maxLengthMeters The maximum segment length allowed. Must be a positive value to be used. Pass zero or NaN to disable densification by length.
+ * @param maxDeviationMeters The maximum deviation. Must be a positive value to be used. Pass zero or NaN to disable densification by deviation.
+ * @param reserved Must be 0 or NaN. Reserved for future use. Throws and exception if not NaN or 0.
+ * @return Returns the densified geometries (It does nothing to geometries with dim less than 1, but simply passes them along).
+ *
+ * The operation always starts from the lowest point on the segment, thus guaranteeing that topologically equal segments are always densified exactly the same.
+ */
+ public abstract GeometryCursor execute(GeometryCursor geoms, SpatialReference sr, double maxLengthMeters, double maxDeviationMeters, double reserved, ProgressTracker progressTracker);
- /**
- * Performs the Shape Preserving Densify operation on the geometry. Attributes are interpolated along the scalar t-values of the input segments obtained from the length ratios along the densified
- * segments.
- *
- * @param geom The geometry to be densified.
- * @param sr The spatial reference of the geometry.
- * @param maxLengthMeters The maximum segment length allowed. Must be a positive value to be used. Pass zero or NaN to disable densification by length.
- * @param maxDeviationMeters The maximum deviation. Must be a positive value to be used. Pass zero or NaN to disable densification by deviation.
- * @param reserved Must be 0 or NaN. Reserved for future use. Throws and exception if not NaN or 0.
- * @return Returns the densified geometries (It does nothing to geometries with dim less than 1, but simply passes them along).
- *
- * The operation always starts from the lowest point on the segment, thus guaranteeing that topologically equal segments are always densified exactly the same.
- */
- public abstract Geometry execute(Geometry geom, SpatialReference sr, double maxLengthMeters, double maxDeviationMeters, double reserved, ProgressTracker progressTracker);
+ /**
+ * Performs the Shape Preserving Densify operation on the geometry. Attributes are interpolated along the scalar t-values of the input segments obtained from the length ratios along the densified
+ * segments.
+ *
+ * @param geom The geometry to be densified.
+ * @param sr The spatial reference of the geometry.
+ * @param maxLengthMeters The maximum segment length allowed. Must be a positive value to be used. Pass zero or NaN to disable densification by length.
+ * @param maxDeviationMeters The maximum deviation. Must be a positive value to be used. Pass zero or NaN to disable densification by deviation.
+ * @param reserved Must be 0 or NaN. Reserved for future use. Throws and exception if not NaN or 0.
+ * @return Returns the densified geometries (It does nothing to geometries with dim less than 1, but simply passes them along).
+ *
+ * The operation always starts from the lowest point on the segment, thus guaranteeing that topologically equal segments are always densified exactly the same.
+ */
+ public abstract Geometry execute(Geometry geom, SpatialReference sr, double maxLengthMeters, double maxDeviationMeters, double reserved, ProgressTracker progressTracker);
- public static OperatorShapePreservingDensify local() {
- return (OperatorShapePreservingDensify) OperatorFactoryLocal.getInstance()
- .getOperator(Type.ShapePreservingDensify);
- }
+ public static OperatorShapePreservingDensify local() {
+ return (OperatorShapePreservingDensify) OperatorFactoryLocal.getInstance()
+ .getOperator(Type.ShapePreservingDensify);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorShapePreservingDensifyLocal.java b/src/main/java/com/esri/core/geometry/OperatorShapePreservingDensifyLocal.java
index 2a7d4128..50a9874b 100644
--- a/src/main/java/com/esri/core/geometry/OperatorShapePreservingDensifyLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorShapePreservingDensifyLocal.java
@@ -26,19 +26,19 @@
//This is a stub
class OperatorShapePreservingDensifyLocal extends
- OperatorShapePreservingDensify {
-
- @Override
- public GeometryCursor execute(GeometryCursor geoms, SpatialReference sr,
- double maxLengthMeters, double maxDeviationMeters, double reserved,
- ProgressTracker progressTracker) {
- throw new GeometryException("not implemented");
- }
-
- @Override
- public Geometry execute(Geometry geom, SpatialReference sr,
- double maxLengthMeters, double maxDeviationMeters, double reserved,
- ProgressTracker progressTracker) {
- throw new GeometryException("not implemented");
- }
+ OperatorShapePreservingDensify {
+
+ @Override
+ public GeometryCursor execute(GeometryCursor geoms, SpatialReference sr,
+ double maxLengthMeters, double maxDeviationMeters, double reserved,
+ ProgressTracker progressTracker) {
+ throw new GeometryException("not implemented");
+ }
+
+ @Override
+ public Geometry execute(Geometry geom, SpatialReference sr,
+ double maxLengthMeters, double maxDeviationMeters, double reserved,
+ ProgressTracker progressTracker) {
+ throw new GeometryException("not implemented");
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorSimpleRelation.java b/src/main/java/com/esri/core/geometry/OperatorSimpleRelation.java
index feb6a6b1..ff24f76d 100644
--- a/src/main/java/com/esri/core/geometry/OperatorSimpleRelation.java
+++ b/src/main/java/com/esri/core/geometry/OperatorSimpleRelation.java
@@ -33,42 +33,42 @@
*/
public abstract class OperatorSimpleRelation extends Operator {
- /**
- * Performs the given relation operation between two geometries.
- *
- * @return Returns True if the relation holds, False otherwise.
- */
- public abstract boolean execute(Geometry inputGeom1,
- Geometry inputGeom2,
- SpatialReference sr,
- ProgressTracker progressTracker);
+ /**
+ * Performs the given relation operation between two geometries.
+ *
+ * @return Returns True if the relation holds, False otherwise.
+ */
+ public abstract boolean execute(Geometry inputGeom1,
+ Geometry inputGeom2,
+ SpatialReference sr,
+ ProgressTracker progressTracker);
- public HashMap
- * The isSimpleAsFeature returns true after this method.
- */
- public abstract GeometryCursor execute(GeometryCursor geoms,
- SpatialReference sr, boolean bForceSimplify,
- ProgressTracker progressTracker);
+ /**
+ * Performs the Simplify operation on the geometry cursor.
+ *
+ * @param geoms Geometries to simplify.
+ * @param sr Spatial reference from which the tolerance is obtained. When null, the tolerance
+ * will be derived individually for each geometry from its bounds.
+ * @param bForceSimplify When True, the Geometry will be simplified regardless of the internal IsKnownSimple flag.
+ * @param progressTracker Allows cancellation of a long operation. Can be null.
+ * @return Returns a GeometryCursor of simplified geometries.
+ *
+ * The isSimpleAsFeature returns true after this method.
+ */
+ public abstract GeometryCursor execute(GeometryCursor geoms,
+ SpatialReference sr, boolean bForceSimplify,
+ ProgressTracker progressTracker);
- /**
- * Performs the Simplify operation on the geometry.
- *
- * @param geom Geometry to simplify.
- * @param sr Spatial reference from which the tolerance is obtained. When null, the tolerance
- * will be derived individually for each geometry from its bounds.
- * @param bForceSimplify When True, the Geometry will be simplified regardless of the internal IsKnownSimple flag.
- * @param progressTracker Allows cancellation of a long operation. Can be null.
- * @return Returns a simple geometry.
- *
- * The isSimpleAsFeature returns true after this method.
- */
- public abstract Geometry execute(Geometry geom, SpatialReference sr,
- boolean bForceSimplify, ProgressTracker progressTracker);
+ /**
+ * Performs the Simplify operation on the geometry.
+ *
+ * @param geom Geometry to simplify.
+ * @param sr Spatial reference from which the tolerance is obtained. When null, the tolerance
+ * will be derived individually for each geometry from its bounds.
+ * @param bForceSimplify When True, the Geometry will be simplified regardless of the internal IsKnownSimple flag.
+ * @param progressTracker Allows cancellation of a long operation. Can be null.
+ * @return Returns a simple geometry.
+ *
+ * The isSimpleAsFeature returns true after this method.
+ */
+ public abstract Geometry execute(Geometry geom, SpatialReference sr,
+ boolean bForceSimplify, ProgressTracker progressTracker);
- public static OperatorSimplify local() {
- return (OperatorSimplify) OperatorFactoryLocal.getInstance()
- .getOperator(Type.Simplify);
- }
+ public static OperatorSimplify local() {
+ return (OperatorSimplify) OperatorFactoryLocal.getInstance()
+ .getOperator(Type.Simplify);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorSimplifyCursor.java b/src/main/java/com/esri/core/geometry/OperatorSimplifyCursor.java
index 362154a5..a2cb146d 100644
--- a/src/main/java/com/esri/core/geometry/OperatorSimplifyCursor.java
+++ b/src/main/java/com/esri/core/geometry/OperatorSimplifyCursor.java
@@ -24,42 +24,42 @@
package com.esri.core.geometry;
class OperatorSimplifyCursor extends GeometryCursor {
- SpatialReference m_spatialReference;
- ProgressTracker m_progressTracker;
- boolean m_bForceSimplify;
+ SpatialReference m_spatialReference;
+ ProgressTracker m_progressTracker;
+ boolean m_bForceSimplify;
- // Reviewed vs. Feb 8 2011
- OperatorSimplifyCursor(GeometryCursor geoms, SpatialReference spatialRef,
- boolean bForceSimplify, ProgressTracker progressTracker) {
- if (geoms == null)
- throw new IllegalArgumentException();
+ // Reviewed vs. Feb 8 2011
+ OperatorSimplifyCursor(GeometryCursor geoms, SpatialReference spatialRef,
+ boolean bForceSimplify, ProgressTracker progressTracker) {
+ if (geoms == null)
+ throw new IllegalArgumentException();
- m_progressTracker = progressTracker;
- m_bForceSimplify = bForceSimplify;
- m_inputGeoms = geoms;
+ m_progressTracker = progressTracker;
+ m_bForceSimplify = bForceSimplify;
+ m_inputGeoms = geoms;
- m_spatialReference = spatialRef;
- }
+ m_spatialReference = spatialRef;
+ }
- // Reviewed vs. Feb 8 2011
- @Override
- public Geometry next() {
- if (hasNext()) {
- if ((m_progressTracker != null) && !(m_progressTracker.progress(-1, -1)))
- throw new RuntimeException("user_canceled");
- return simplify(m_inputGeoms.next());
- }
- return null;
- }
+ // Reviewed vs. Feb 8 2011
+ @Override
+ public Geometry next() {
+ if (hasNext()) {
+ if ((m_progressTracker != null) && !(m_progressTracker.progress(-1, -1)))
+ throw new RuntimeException("user_canceled");
+ return simplify(m_inputGeoms.next());
+ }
+ return null;
+ }
- // Reviewed vs. Feb 8 2011
- Geometry simplify(Geometry geometry) {
- if (geometry == null)
- throw new IllegalArgumentException();
+ // Reviewed vs. Feb 8 2011
+ Geometry simplify(Geometry geometry) {
+ if (geometry == null)
+ throw new IllegalArgumentException();
- // Geometry.Type type = geometry.getType();
+ // Geometry.Type type = geometry.getType();
- return OperatorSimplifyLocalHelper.simplifyAsFeature(geometry,
- m_spatialReference, m_bForceSimplify, m_progressTracker);
- }
+ return OperatorSimplifyLocalHelper.simplifyAsFeature(geometry,
+ m_spatialReference, m_bForceSimplify, m_progressTracker);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorSimplifyCursorOGC.java b/src/main/java/com/esri/core/geometry/OperatorSimplifyCursorOGC.java
index e1d5e0af..55690dc6 100644
--- a/src/main/java/com/esri/core/geometry/OperatorSimplifyCursorOGC.java
+++ b/src/main/java/com/esri/core/geometry/OperatorSimplifyCursorOGC.java
@@ -24,39 +24,39 @@
package com.esri.core.geometry;
class OperatorSimplifyCursorOGC extends GeometryCursor {
- SpatialReference m_spatialReference;
- ProgressTracker m_progressTracker;
- boolean m_bForceSimplify;
-
- OperatorSimplifyCursorOGC(GeometryCursor geoms,
- SpatialReference spatialRef, boolean bForceSimplify,
- ProgressTracker progressTracker) {
- if (geoms == null)
- throw new IllegalArgumentException();
-
- m_progressTracker = progressTracker;
- m_bForceSimplify = bForceSimplify;
-
- m_inputGeoms = geoms;
-
- m_spatialReference = spatialRef;
- }
-
- @Override
- public Geometry next() {
- if (hasNext()) {
- if ((m_progressTracker != null) && !(m_progressTracker.progress(-1, -1)))
- throw new RuntimeException("user_canceled");
- return simplify(m_inputGeoms.next());
- }
- return null;
- }
-
- Geometry simplify(Geometry geometry) {
- if (geometry == null)
- throw new IllegalArgumentException();
-
- return OperatorSimplifyLocalHelper.simplifyOGC(geometry,
- m_spatialReference, m_bForceSimplify, m_progressTracker);
- }
+ SpatialReference m_spatialReference;
+ ProgressTracker m_progressTracker;
+ boolean m_bForceSimplify;
+
+ OperatorSimplifyCursorOGC(GeometryCursor geoms,
+ SpatialReference spatialRef, boolean bForceSimplify,
+ ProgressTracker progressTracker) {
+ if (geoms == null)
+ throw new IllegalArgumentException();
+
+ m_progressTracker = progressTracker;
+ m_bForceSimplify = bForceSimplify;
+
+ m_inputGeoms = geoms;
+
+ m_spatialReference = spatialRef;
+ }
+
+ @Override
+ public Geometry next() {
+ if (hasNext()) {
+ if ((m_progressTracker != null) && !(m_progressTracker.progress(-1, -1)))
+ throw new RuntimeException("user_canceled");
+ return simplify(m_inputGeoms.next());
+ }
+ return null;
+ }
+
+ Geometry simplify(Geometry geometry) {
+ if (geometry == null)
+ throw new IllegalArgumentException();
+
+ return OperatorSimplifyLocalHelper.simplifyOGC(geometry,
+ m_spatialReference, m_bForceSimplify, m_progressTracker);
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorSimplifyLocal.java b/src/main/java/com/esri/core/geometry/OperatorSimplifyLocal.java
index a1eea89c..c18690ad 100644
--- a/src/main/java/com/esri/core/geometry/OperatorSimplifyLocal.java
+++ b/src/main/java/com/esri/core/geometry/OperatorSimplifyLocal.java
@@ -25,35 +25,35 @@
class OperatorSimplifyLocal extends OperatorSimplify {
- // Reviewed vs. Feb 8 2011
- @Override
- public GeometryCursor execute(GeometryCursor geoms,
- SpatialReference spatialRef,
- boolean bForceSimplify,
- ProgressTracker progressTracker) {
- return new OperatorSimplifyCursor(geoms, spatialRef, bForceSimplify,progressTracker);
- }
-
- // Reviewed vs. Feb 8 2011
- @Override
- public boolean isSimpleAsFeature(Geometry geom,
- SpatialReference spatialRef,
- boolean bForceTest,
- NonSimpleResult result,
- ProgressTracker progressTracker) {
- int res = OperatorSimplifyLocalHelper.isSimpleAsFeature(geom, spatialRef, bForceTest, result, progressTracker);
- return res > 0;
- }
-
- // Reviewed vs. Feb 8 2011
- @Override
- public Geometry execute(Geometry geom,
- SpatialReference spatialRef,
- boolean bForceSimplify,
- ProgressTracker progressTracker) {
- SimpleGeometryCursor inputCursor = new SimpleGeometryCursor(geom);
- GeometryCursor outputCursor = execute(inputCursor, spatialRef,bForceSimplify, progressTracker);
-
- return outputCursor.next();
- }
+ // Reviewed vs. Feb 8 2011
+ @Override
+ public GeometryCursor execute(GeometryCursor geoms,
+ SpatialReference spatialRef,
+ boolean bForceSimplify,
+ ProgressTracker progressTracker) {
+ return new OperatorSimplifyCursor(geoms, spatialRef, bForceSimplify, progressTracker);
+ }
+
+ // Reviewed vs. Feb 8 2011
+ @Override
+ public boolean isSimpleAsFeature(Geometry geom,
+ SpatialReference spatialRef,
+ boolean bForceTest,
+ NonSimpleResult result,
+ ProgressTracker progressTracker) {
+ int res = OperatorSimplifyLocalHelper.isSimpleAsFeature(geom, spatialRef, bForceTest, result, progressTracker);
+ return res > 0;
+ }
+
+ // Reviewed vs. Feb 8 2011
+ @Override
+ public Geometry execute(Geometry geom,
+ SpatialReference spatialRef,
+ boolean bForceSimplify,
+ ProgressTracker progressTracker) {
+ SimpleGeometryCursor inputCursor = new SimpleGeometryCursor(geom);
+ GeometryCursor outputCursor = execute(inputCursor, spatialRef, bForceSimplify, progressTracker);
+
+ return outputCursor.next();
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OperatorSimplifyLocalHelper.java b/src/main/java/com/esri/core/geometry/OperatorSimplifyLocalHelper.java
index b6707af3..2513693e 100644
--- a/src/main/java/com/esri/core/geometry/OperatorSimplifyLocalHelper.java
+++ b/src/main/java/com/esri/core/geometry/OperatorSimplifyLocalHelper.java
@@ -31,2204 +31,2180 @@
import com.esri.core.geometry.MultiVertexGeometryImpl.GeometryXSimple;
class OperatorSimplifyLocalHelper {
- private static final class Edge {
- Edge() {
- m_flags = 0;
- // m_segment.createInstance();
- }
-
- Segment m_segment;
- int m_vertexIndex;
- int m_pathIndex;
- int m_flags;
-
- void setReversed(boolean bYesNo) {
- m_flags &= (~1);
- m_flags = m_flags | (bYesNo ? 1 : 0);
- }
-
- // The value returned by GetReversed is interpreted differently in
- // checkSelfIntersections_ and checkValidRingOrientation_
- boolean getReversed() /* const */ {
- return (m_flags & 1) != 0;
- }
-
- int getRightSide() /* const */ {
- return getReversed() ? 0 : 1; // 0 means there should be an
- // emptiness on the right side of
- // the edge, 1 means there is
- // interior
- }
- }
-
- private final VertexDescription m_description;
- private Geometry m_geometry;
- private SpatialReferenceImpl m_sr;
- private int m_dbgCounter; // debugging counter(for breakpoints)
- private double m_toleranceIsSimple;
- private double m_toleranceSimplify;
- // private double m_toleranceCluster; //cluster tolerance needs to be
- // sqrt(2) times larger than the tolerance of the other simplify processes.
- private int m_knownSimpleResult;
- private int m_attributeCount;
-
- private ArrayList
- * The method throws if the pointSrc is not of the Point type.
- * The attributes, that are present in the pointSrc and missing
- * in this Geometry, will be added to the Geometry.
- * The vertex attributes missing in the pointSrc but present in
- * the Geometry will be set to the default values (see
- * VertexDescription::GetDefaultValue).
- */
- public abstract void setPoint(int index, Point pointSrc);// Java only
-
- /**
- * Returns XY coordinates of the given vertex of the Geometry.
- */
- public abstract Point2D getXY(int index);
-
- public abstract void getXY(int index, Point2D pt);
-
- /**
- * Sets XY coordinates of the given vertex of the Geometry. All other
- * attributes are unchanged.
- */
- public abstract void setXY(int index, Point2D pt);
-
- /**
- * Returns XYZ coordinates of the given vertex of the Geometry. If the
- * Geometry has no Z's, the default value for Z is returned (0).
- */
- abstract Point3D getXYZ(int index);
-
- /**
- * Sets XYZ coordinates of the given vertex of the Geometry. If Z attribute
- * is not present in this Geometry, it is added. All other attributes are
- * unchanged.
- */
- abstract void setXYZ(int index, Point3D pt);
-
- /**
- * Returns XY coordinates as an array.
- */
- public Point2D[] getCoordinates2D() {
- Point2D[] arr = new Point2D[getPointCount()];
- queryCoordinates(arr);
- return arr;
- }
-
- /**
- * Returns XYZ coordinates as an array.
- */
- Point3D[] getCoordinates3D() {
- Point3D[] arr = new Point3D[getPointCount()];
- queryCoordinates(arr);
- return arr;
- }
-
- public abstract void queryCoordinates(Point[] dst);
-
- /**
- * Queries XY coordinates as an array. The array must be larg enough (See
- * GetPointCount()).
- */
- public abstract void queryCoordinates(Point2D[] dst);
-
- /**
- * Queries XYZ coordinates as an array. The array must be larg enough (See
- * GetPointCount()).
- */
- abstract void queryCoordinates(Point3D[] dst);
-
- /**
- * Returns value of the given vertex attribute as double.
- *
- * @param semantics The atribute semantics.
- * @param index is the vertex index in the Geometry.
- * @param ordinate is the ordinate of a vertex attribute (for example, y has
- * ordinate of 1, because it is second ordinate of POSITION)
- *
- * The method throws if the pointSrc is not of the Point type.
- * The attributes, that are present in the pointSrc and missing
- * in this Geometry, will be added to the Geometry.
- * The vertex attributes missing in the pointSrc but present in
- * the Geometry will be set to the default values (see
- * VertexDescription::GetDefaultValue).
- */
- public abstract void setPointByVal(int index, Point pointSrc);
+ Serializable {
+
+ @Override
+ protected void _assignVertexDescriptionImpl(VertexDescription newDescription) {
+ throw new GeometryException("invalid call");
+ }
+
+ /**
+ * Returns the total vertex count in this Geometry.
+ */
+ public abstract int getPointCount();
+
+ /**
+ * Returns given vertex of the Geometry.
+ */
+ public abstract Point getPoint(int index);// Java only
+
+ /**
+ * Returns given vertex of the Geometry by value.
+ */
+ public void getPoint(int index, Point ptOut) {
+ getPointByVal(index, ptOut);
+ }
+
+ /**
+ * Sets the vertex at given index of the Geometry.
+ *
+ * @param index The index of the vertex being changed.
+ * @param pointSrc The Point instance to set given vertex attributes from. The
+ * pointSrc can not be empty.
+ * The method throws if the pointSrc is not of the Point type.
+ * The attributes, that are present in the pointSrc and missing
+ * in this Geometry, will be added to the Geometry.
+ * The vertex attributes missing in the pointSrc but present in
+ * the Geometry will be set to the default values (see
+ * VertexDescription::GetDefaultValue).
+ */
+ public abstract void setPoint(int index, Point pointSrc);// Java only
+
+ /**
+ * Returns XY coordinates of the given vertex of the Geometry.
+ */
+ public abstract Point2D getXY(int index);
+
+ public abstract void getXY(int index, Point2D pt);
+
+ /**
+ * Sets XY coordinates of the given vertex of the Geometry. All other
+ * attributes are unchanged.
+ */
+ public abstract void setXY(int index, Point2D pt);
+
+ /**
+ * Returns XYZ coordinates of the given vertex of the Geometry. If the
+ * Geometry has no Z's, the default value for Z is returned (0).
+ */
+ abstract Point3D getXYZ(int index);
+
+ /**
+ * Sets XYZ coordinates of the given vertex of the Geometry. If Z attribute
+ * is not present in this Geometry, it is added. All other attributes are
+ * unchanged.
+ */
+ abstract void setXYZ(int index, Point3D pt);
+
+ /**
+ * Returns XY coordinates as an array.
+ */
+ public Point2D[] getCoordinates2D() {
+ Point2D[] arr = new Point2D[getPointCount()];
+ queryCoordinates(arr);
+ return arr;
+ }
+
+ /**
+ * Returns XYZ coordinates as an array.
+ */
+ Point3D[] getCoordinates3D() {
+ Point3D[] arr = new Point3D[getPointCount()];
+ queryCoordinates(arr);
+ return arr;
+ }
+
+ public abstract void queryCoordinates(Point[] dst);
+
+ /**
+ * Queries XY coordinates as an array. The array must be larg enough (See
+ * GetPointCount()).
+ */
+ public abstract void queryCoordinates(Point2D[] dst);
+
+ /**
+ * Queries XYZ coordinates as an array. The array must be larg enough (See
+ * GetPointCount()).
+ */
+ abstract void queryCoordinates(Point3D[] dst);
+
+ /**
+ * Returns value of the given vertex attribute as double.
+ *
+ * @param semantics The atribute semantics.
+ * @param index is the vertex index in the Geometry.
+ * @param ordinate is the ordinate of a vertex attribute (for example, y has
+ * ordinate of 1, because it is second ordinate of POSITION)
+ *
+ * The method throws if the pointSrc is not of the Point type.
+ * The attributes, that are present in the pointSrc and missing
+ * in this Geometry, will be added to the Geometry.
+ * The vertex attributes missing in the pointSrc but present in
+ * the Geometry will be set to the default values (see
+ * VertexDescription::GetDefaultValue).
+ */
+ public abstract void setPointByVal(int index, Point pointSrc);
}
diff --git a/src/main/java/com/esri/core/geometry/MultiVertexGeometryImpl.java b/src/main/java/com/esri/core/geometry/MultiVertexGeometryImpl.java
index 8907df37..e045aa2a 100644
--- a/src/main/java/com/esri/core/geometry/MultiVertexGeometryImpl.java
+++ b/src/main/java/com/esri/core/geometry/MultiVertexGeometryImpl.java
@@ -30,1087 +30,1055 @@
/**
* This class is a base for geometries with many vertices.
- *
- * If the attribute is missing, it will be added.
- * Note, that this method does not change the vertex count in the Geometry.
- * The stream can have more elements, than the Geometry point count, but
- * only necessary part will be saved when exporting to a ESRI shape or other
- * format. @param semantics Semantics of the attribute to assign the stream
- * to. @param stream The input AttributeStream that will be assigned by
- * reference. If one changes the stream later through the reference, one has
- * to call NotifyStreamChanged. \exception Throws invalid_argument exception
- * if the input stream type does not match that of the semantics
- * persistence.
- */
- public void setAttributeStreamRef(int semantics, AttributeStreamBase stream) {
- // int test1 = VertexDescription.getPersistence(semantics);
- // int test2 = stream.getPersistence();
-
- if ((stream != null)
- && VertexDescription.getPersistence(semantics) != stream
- .getPersistence())// input stream has wrong persistence
- throw new IllegalArgumentException();
-
- // Do not check for the stream size here to allow several streams to be
- // attached before the point count is changed.
- addAttribute(semantics);
- int attributeIndex = m_description.getAttributeIndex(semantics);
- if (m_vertexAttributes == null)
- m_vertexAttributes = new AttributeStreamBase[m_description
- .getAttributeCount()];
-
- m_vertexAttributes[attributeIndex] = stream;
- notifyModified(DirtyFlags.DirtyAll);
- }
-
- @Override
- protected void _assignVertexDescriptionImpl(VertexDescription newDescription) {
- AttributeStreamBase[] newAttributes = null;
-
- if (m_vertexAttributes != null) {
- int[] mapping = VertexDescriptionDesignerImpl.mapAttributes(
- newDescription, m_description);
-
- newAttributes = new AttributeStreamBase[newDescription
- .getAttributeCount()];
-
- for (int i = 0, n = newDescription.getAttributeCount(); i < n; i++) {
- if (mapping[i] != -1) {
- int m = mapping[i];
- newAttributes[i] = m_vertexAttributes[m];
- }
-
- }
- } else {
- //if there are no streams we do not create them
- }
-
- m_description = newDescription;
- m_vertexAttributes = newAttributes; // late assignment to try to stay
- m_reservedPointCount = -1;// we need to recreate the new attribute then
- notifyModified(DirtyFlags.DirtyAll);
- }
-
- // Checked vs. Jan 11, 2011
- protected void _updateEnvelope(Envelope2D env) {
- _updateAllDirtyIntervals(true);
- m_envelope.queryEnvelope2D(env);
- } // note: overload for polylines/polygons with curves
-
- // Checked vs. Jan 11, 2011
- protected void _updateEnvelope(Envelope3D env) {
- _updateAllDirtyIntervals(true);
- m_envelope.queryEnvelope3D(env);
- } // note: overload for polylines/polygons with curves
-
- // Checked vs. Jan 11, 2011
- protected void _updateLooseEnvelope(Envelope2D env) {
- // TODO ROHIT has this set to true?
- _updateAllDirtyIntervals(false);
- m_envelope.queryEnvelope2D(env);
- } // note: overload for polylines/polygons with curves
-
- // Checked vs. Jan 11, 2011
-
- /**
- * \internal Calculates loose envelope. Returns True if the calculation
- * renders exact envelope.
- */
- protected void _updateLooseEnvelope(Envelope3D env) {
- // TODO ROHIT has this set to true?
- _updateAllDirtyIntervals(false);
- m_envelope.queryEnvelope3D(env);
- } // note: overload for polylines/polygons with curves
-
- // Checked vs. Jan 11, 2011
- @Override
- public void queryEnvelope(Envelope env) {
- _updateAllDirtyIntervals(true);
- m_envelope.copyTo(env);
- }
-
- // TODO rename to remove 2D
- // Checked vs. Jan 11, 2011
- @Override
- public void queryEnvelope2D(Envelope2D env) {
- _updateEnvelope(env);
- }
-
- // Checked vs. Jan 11, 2011
- // TODO rename to remove 3D
- @Override
- public void queryEnvelope3D(Envelope3D env) {
- _updateEnvelope(env);
- }
-
- // Checked vs. Jan 11, 2011
- // TODO rename to remove 2D
- @Override
- public void queryLooseEnvelope2D(Envelope2D env) {
- _updateLooseEnvelope(env);
- }
-
- // Checked vs. Jan 11, 2011
- // TODO rename to remove 3D
- @Override
- public void queryLooseEnvelope3D(Envelope3D env) {
- _updateLooseEnvelope(env);
- }
-
- // Checked vs. Jan 11, 2011
- @Override
- public Envelope1D queryInterval(int semantics, int ordinate) {
- Envelope1D env = new Envelope1D();
- if (isEmptyImpl()) {
- env.setEmpty();
- return env;
- }
-
- _updateAllDirtyIntervals(true);
- return m_envelope.queryInterval(semantics, ordinate);
- }
-
- // Checked vs. Jan 11, 2011
- // TODO Rename to getHashCode
- @Override
- public int hashCode() {
- int hashCode = m_description.hashCode();
-
- if (!isEmptyImpl()) {
- int pointCount = getPointCount();
- for (int i = 0, n = m_description.getAttributeCount(); i < n; i++) {
- int components = VertexDescription
- .getComponentCount(m_description._getSemanticsImpl(i));
- AttributeStreamBase stream = m_vertexAttributes[i];
- hashCode = stream.calculateHashImpl(hashCode, 0, pointCount
- * components);
- }
- }
-
- return hashCode;
- }
-
- // Checked vs. Jan 11, 2011
- @Override
- public boolean equals(Object other) {
- // Java checks
- if (other == this)
- return true;
-
- if (!(other instanceof MultiVertexGeometryImpl))
- return false;
-
- MultiVertexGeometryImpl otherMulti = (MultiVertexGeometryImpl) other;
-
- if (!(m_description.equals(otherMulti.m_description)))
- return false;
-
- if (isEmptyImpl() != otherMulti.isEmptyImpl())
- return false;
-
- if (isEmptyImpl())
- return true; // both geometries are empty
-
- int pointCount = getPointCount();
- int pointCountOther = otherMulti.getPointCount();
-
- if (pointCount != pointCountOther)
- return false;
-
- for (int i = 0; i < m_description.getAttributeCount(); i++) {
- int semantics = m_description.getSemantics(i);
-
- AttributeStreamBase stream = getAttributeStreamRef(semantics);
- AttributeStreamBase streamOther = otherMulti
- .getAttributeStreamRef(semantics);
-
- int components = VertexDescription.getComponentCount(semantics);
-
- if (!stream.equals(streamOther, 0, pointCount * components))
- return false;
- }
-
- return true;
- }
-
- // Checked vs. Jan 11, 2011
-
- /**
- * Sets the envelope of the Geometry. The Envelope description must match
- * that of the Geometry.
- */
- public void setEnvelope(Envelope env) {
- if (!m_description.equals(env.getDescription()))
- throw new IllegalArgumentException();
-
- // m_envelope = (Envelope) env.clone();
- m_envelope = (Envelope) env.createInstance();
- env.copyTo(m_envelope);
- _setDirtyFlag(DirtyFlags.DirtyIntervals, false);
- }
-
- @Override
- public void copyTo(Geometry dstGeom) {
- MultiVertexGeometryImpl dst = (MultiVertexGeometryImpl) dstGeom;
- if (dst.getType() != getType())
- throw new IllegalArgumentException();
-
- _copyToUnsafe(dst);
- }
-
- //Does not check geometry type. Used to copy Polygon to Polyline
- void _copyToUnsafe(MultiVertexGeometryImpl dst) {
- _verifyAllStreams();
- dst.m_description = m_description;
- dst.m_vertexAttributes = null;
- int nattrib = m_description.getAttributeCount();
- AttributeStreamBase[] cloneAttributes = null;
- if (m_vertexAttributes != null) {
- cloneAttributes = new AttributeStreamBase[nattrib];
- for (int i = 0; i < nattrib; i++) {
- if (m_vertexAttributes[i] != null) {
- int ncomps = VertexDescription.getComponentCount(m_description._getSemanticsImpl(i));
- cloneAttributes[i] = m_vertexAttributes[i].restrictedClone(getPointCount() * ncomps);
- }
- }
- }
-
- if (m_envelope != null) {
- dst.m_envelope = (Envelope) m_envelope.createInstance();
- m_envelope.copyTo(dst.m_envelope);
- // dst.m_envelope = (Envelope) m_envelope.clone();
- } else
- dst.m_envelope = null;
-
- dst.m_pointCount = m_pointCount;
- dst.m_flagsMask = m_flagsMask;
- dst.m_vertexAttributes = cloneAttributes;
-
- try {
- _copyToImpl(dst); // copy child props
- } catch (Exception ex) {
- dst.setEmpty();
- throw new RuntimeException(ex);
- }
- }
-
- // Checked vs. Jan 11, 2011
- public boolean _attributeStreamIsAllocated(int semantics) {
- throwIfEmpty();
-
- int attributeIndex = m_description.getAttributeIndex(semantics);
-
- if (attributeIndex >= 0 && m_vertexAttributes[attributeIndex] != null)
- return true;
-
- return false;
- }
-
- // Checked vs. Jan 11, 2011
- void _setEmptyImpl() {
- m_pointCount = 0;
- m_reservedPointCount = -1;
- m_vertexAttributes = null;// release it all streams.
- notifyModified(DirtyFlags.DirtyAll);
- }
-
- // Checked vs. Jan 11, 2011
-
- /**
- * Notifies the Geometry of changes made to the vertices so that it could
- * reset cached structures.
- */
- public void notifyModified(int flags) {
- if (flags == DirtyFlags.DirtyAll) {
- m_reservedPointCount = -1;// forget the reserved point number
- _notifyModifiedAllImpl();
- }
- m_flagsMask |= flags;
-
- _clearAccelerators();
- _touch();
- }
-
- // Checked vs. Jan 11, 2011
-
- /**
- * @param bExact True, when the exact envelope need to be calculated and false
- * for the loose one.
- */
- protected void _updateAllDirtyIntervals(boolean bExact) {
- _verifyAllStreams();
- if (_hasDirtyFlag(DirtyFlags.DirtyIntervals)) {
- if (null == m_envelope)
- m_envelope = new Envelope(m_description);
- else
- m_envelope.assignVertexDescription(m_description);
-
- if (isEmpty()) {
- m_envelope.setEmpty();
- return;
- }
-
- _updateXYImpl(bExact);// efficient method for xy's
- // now go through other attribues.
- for (int attributeIndex = 1; attributeIndex < m_description
- .getAttributeCount(); attributeIndex++) {
- int semantics = m_description._getSemanticsImpl(attributeIndex);
- int ncomps = VertexDescription.getComponentCount(semantics);
- AttributeStreamBase stream = m_vertexAttributes[attributeIndex];
- for (int iord = 0; iord < ncomps; iord++) {
- Envelope1D interval = new Envelope1D();
- interval.setEmpty();
- for (int i = 0; i < m_pointCount; i++) {
- double value = stream.readAsDbl(i * ncomps + iord);// some
- // optimization
- // is
- // possible
- // if
- // non-virtual
- // method
- // is
- // used
- interval.merge(value);
- }
- m_envelope.setInterval(semantics, iord, interval);
- }
- }
- if (bExact)
- _setDirtyFlag(DirtyFlags.DirtyIntervals, false);
- }
- }
-
- // Checked vs. Jan 11, 2011
-
- /**
- * \internal Updates x, y intervals.
- */
- public void _updateXYImpl(boolean bExact) {
- m_envelope.setEmpty();
- AttributeStreamOfDbl stream = (AttributeStreamOfDbl) m_vertexAttributes[0];
- Point2D pt = new Point2D();
- for (int i = 0; i < m_pointCount; i++) {
- stream.read(2 * i, pt);
- m_envelope.merge(pt);
- }
- }
-
- void calculateEnvelope2D(Envelope2D env, boolean bExact) {
- env.setEmpty();
- AttributeStreamOfDbl stream = (AttributeStreamOfDbl) m_vertexAttributes[0];
- Point2D pt = new Point2D();
- for (int i = 0; i < m_pointCount; i++) {
- stream.read(2 * i, pt);
- env.merge(pt);
- }
- }
-
- // Checked vs. Jan 11, 2011 lots of changes
-
- /**
- * \internal Verifies all streams (calls _VerifyStream for every attribute).
- */
- protected void _verifyAllStreamsImpl() {
- // This method checks that the streams are of correct size.
- // It resizes the streams to ensure they are not shorter than
- // m_PointCount
- // _ASSERT(_HasDirtyFlag(enum_value1(DirtyFlags,
- // DirtyVerifiedStreams)));
- if (m_reservedPointCount < m_pointCount) // an optimization to skip this
- // expensive loop when
- // adding point by point
- {
- if (m_vertexAttributes == null)
- m_vertexAttributes = new AttributeStreamBase[m_description
- .getAttributeCount()];
-
- m_reservedPointCount = NumberUtils.intMax();
- for (int attributeIndex = 0; attributeIndex < m_description
- .getAttributeCount(); attributeIndex++) {
- int semantics = m_description._getSemanticsImpl(attributeIndex);
- if (m_vertexAttributes[attributeIndex] != null) {
- int ncomp = VertexDescription.getComponentCount(semantics);
- int size = m_vertexAttributes[attributeIndex].virtualSize()
- / ncomp;
- if (size < m_pointCount) {
- size = (m_reservedPointCount > m_pointCount + 5) ? (m_pointCount * 5 + 3) / 4
- : m_pointCount;// reserve 25% more than user
- // asks
- m_vertexAttributes[attributeIndex].resize(size * ncomp,
- VertexDescription.getDefaultValue(semantics));
- }
-
- if (size < m_reservedPointCount)
- m_reservedPointCount = size;
- } else {
- m_vertexAttributes[attributeIndex] = AttributeStreamBase
- .createAttributeStreamWithSemantics(semantics,
- m_pointCount);
- m_reservedPointCount = m_pointCount;
- }
- }
- }
- _verifyStreamsImpl();
-
- _setDirtyFlag(DirtyFlags.DirtyVerifiedStreams, false);
- }
-
- // Checked vs. Jan 11, 2011
- void _resizeImpl(int pointCount) {
- if (pointCount < 0)
- throw new IllegalArgumentException();
-
- if (pointCount == m_pointCount)
- return;
-
- m_pointCount = pointCount;
- notifyModified(DirtyFlags.DirtyAllInternal);
- }
-
- // Checked vs. Jan 11, 2011
- int queryCoordinates(Point2D[] dst, int dstSize, int beginIndex,
- int endIndex) {
- int endIndexC = endIndex < 0 ? m_pointCount : endIndex;
- endIndexC = Math.min(endIndexC, beginIndex + dstSize);
-
- if (beginIndex < 0 || beginIndex >= m_pointCount
- || endIndexC < beginIndex)
- throw new IllegalArgumentException();
-
- AttributeStreamOfDbl xy = (AttributeStreamOfDbl) getAttributeStreamRef(VertexDescription.Semantics.POSITION);
- int j = 0;
- double[] dstArray = new double[dst.length * 2];
- xy.readRange(2 * beginIndex, (endIndexC - beginIndex) * 2, dstArray, j, true);
-
- for (int i = 0; i < dst.length; i++) {
- dst[i] = new Point2D(dstArray[i * 2], dstArray[i * 2 + 1]);
- }
-
- // for (int i = beginIndex; i < endIndexC; i++, j++)
- // {
- // xy.read(2 * i, dst[j]);
- // }
-
- return endIndexC;
- }
-
- // Checked vs. Jan 11, 2011
- int QueryCoordinates(Point3D[] dst, int dstSize, int beginIndex,
- int endIndex) {
- int endIndexC = endIndex < 0 ? m_pointCount : endIndex;
- endIndexC = Math.min(endIndexC, beginIndex + dstSize);
-
- if (beginIndex < 0 || beginIndex >= m_pointCount
- || endIndexC < beginIndex)
- // TODO replace geometry exc
- throw new IllegalArgumentException();
-
- AttributeStreamOfDbl xy = (AttributeStreamOfDbl) getAttributeStreamRef(VertexDescription.Semantics.POSITION);
- AttributeStreamOfDbl z = null;
- double v = VertexDescription
- .getDefaultValue(VertexDescription.Semantics.Z);
- boolean bHasZ = hasAttribute(VertexDescription.Semantics.Z);
- if (bHasZ)
- z = (AttributeStreamOfDbl) getAttributeStreamRef(VertexDescription.Semantics.Z);
- int j = 0;
- for (int i = beginIndex; i < endIndexC; i++, j++) {
- dst[j].x = xy.read(2 * i);
- dst[j].y = xy.read(2 * i + 1);
- dst[j].z = bHasZ ? z.read(i) : v;
-
- dst[j] = getXYZ(i);
- }
-
- return endIndexC;
- }
-
- // Checked vs. Jan 11, 2011
- // -1 : DirtySimple is true (whether or not the MultiPath is Simple is
- // unknown)
- // 0 : DirtySimple is false and the MultiPath is not Weak Simple
- // 1 : DirtySimple is false and the MultiPath is Weak Simple but not ring
- // ordering may be invalid
- // 2 : DirtySimple is false and the MultiPath is Strong Simple (Weak Simple
- // and valid ring ordering)
- public int getIsSimple(double tolerance) {
- if (!_hasDirtyFlag(DirtyFlags.DirtyIsKnownSimple)) {
- if (!_hasDirtyFlag(DirtyFlags.IsWeakSimple)) {
- return 0;
- }
- if (m_simpleTolerance >= tolerance) {
- if (!_hasDirtyFlag(DirtyFlags.DirtyOGCFlags))
- return 2;
-
- return 1;
- }
-
- return -1;
- }
- return -1;
- }
-
- void setIsSimple(int isSimpleRes, double tolerance, boolean ogc_known) {
- m_simpleTolerance = tolerance;
- if (isSimpleRes == GeometryXSimple.Unknown) {
- _setDirtyFlag(DirtyFlags.DirtyIsKnownSimple, true);
- _setDirtyFlag(DirtyFlags.DirtyOGCFlags, true);
- return;
- }
- _setDirtyFlag(DirtyFlags.DirtyIsKnownSimple, false);
-
- if (!ogc_known)
- _setDirtyFlag(DirtyFlags.DirtyOGCFlags, true);
-
- if (isSimpleRes == GeometryXSimple.Not) {
- _setDirtyFlag(DirtyFlags.IsWeakSimple, false);
- _setDirtyFlag(DirtyFlags.IsStrongSimple, false);
- } else if (isSimpleRes == GeometryXSimple.Weak) {
- _setDirtyFlag(DirtyFlags.IsWeakSimple, true);
- _setDirtyFlag(DirtyFlags.IsStrongSimple, false);
- } else if (isSimpleRes == GeometryXSimple.Strong) {
- _setDirtyFlag(DirtyFlags.IsWeakSimple, true);
- _setDirtyFlag(DirtyFlags.IsStrongSimple, true);
- } else
- throw GeometryException.GeometryInternalError();// what?
- }
-
- double _getSimpleTolerance() {
- return m_simpleTolerance;
- }
-
- public GeometryAccelerators _getAccelerators() {
- return m_accelerators;
- }
-
- void _clearAccelerators() {
- if (m_accelerators != null)
- m_accelerators = null;
- }
-
- void _interpolateTwoVertices(int vertex1, int vertex2, double f,
- Point outPoint) {
- if (vertex1 < 0 || vertex1 >= m_pointCount)
- throw new GeometryException("index out of bounds.");
- if (vertex2 < 0 || vertex2 >= m_pointCount)
- throw new GeometryException("index out of bounds.");
-
- // _ASSERT(!IsEmpty());
- // _ASSERT(m_vertexAttributes != NULLPTR);
-
- _verifyAllStreams();
-
- outPoint.assignVertexDescription(m_description);
- if (outPoint.isEmpty())
- outPoint._setToDefault();
-
- for (int attributeIndex = 0; attributeIndex < m_description
- .getAttributeCount(); attributeIndex++) {
- int semantics = m_description._getSemanticsImpl(attributeIndex);
- for (int icomp = 0, ncomp = VertexDescription
- .getComponentCount(semantics); icomp < ncomp; icomp++) {
- double v1 = m_vertexAttributes[attributeIndex].readAsDbl(ncomp
- * vertex1 + icomp);
- double v2 = m_vertexAttributes[attributeIndex].readAsDbl(ncomp
- * vertex2 + icomp);
- outPoint.setAttribute(semantics, icomp, MathUtils.lerp(v1, v2, f));
- }
- }
- }
-
- double _getShortestDistance(int vertex1, int vertex2) {
- Point2D pt = getXY(vertex1);
- pt.sub(getXY(vertex2));
- return pt.length();
- }
-
- // ////////////////// METHODS To REMOVE ///////////////////////
- @Override
- public Point getPoint(int index) {
- if (index < 0 || index >= m_pointCount)
- throw new IndexOutOfBoundsException();
-
- _verifyAllStreams();
-
- Point outPoint = new Point();
- outPoint.assignVertexDescription(m_description);
- if (outPoint.isEmpty())
- outPoint._setToDefault();
-
- for (int attributeIndex = 0; attributeIndex < m_description
- .getAttributeCount(); attributeIndex++) {
- int semantics = m_description.getSemantics(attributeIndex);
- for (int icomp = 0, ncomp = VertexDescription
- .getComponentCount(semantics); icomp < ncomp; icomp++) {
- double v = m_vertexAttributes[attributeIndex].readAsDbl(ncomp
- * index + icomp);
- outPoint.setAttribute(semantics, icomp, v);
- }
- }
- return outPoint;
- }
-
- @Override
- public void setPoint(int index, Point src) {
- if (index < 0 || index >= m_pointCount)
- throw new IndexOutOfBoundsException();
-
- Point point = src;
-
- if (src.isEmpty())// can not assign an empty point to a multipoint
- // vertex
- throw new IllegalArgumentException();
-
- _verifyAllStreams();// verify all allocated streams are of necessary
- // size.
- VertexDescription vdin = point.getDescription();
- for (int attributeIndex = 0; attributeIndex < vdin.getAttributeCount(); attributeIndex++) {
- int semantics = vdin.getSemantics(attributeIndex);
- int ncomp = VertexDescription.getComponentCount(semantics);
- for (int icomp = 0; icomp < ncomp; icomp++) {
- double v = point.getAttributeAsDbl(semantics, icomp);
- setAttribute(semantics, index, icomp, v);
- }
- }
- }
-
- @Override
- public void queryCoordinates(Point[] dst) {
- int sz = m_pointCount;
- if (dst.length < sz)
- throw new IllegalArgumentException();
-
- // TODO: refactor to a better AttributeAray call (ReadRange?)
- for (int i = 0; i < sz; i++) {
- dst[i] = getPoint(i);
- }
- }
-
- @Override
- public void queryCoordinates(Point2D[] dst) {
- int sz = m_pointCount;
- if (dst.length < sz)
- throw new IllegalArgumentException();
-
- // TODO: refactor to a better AttributeAray call (ReadRange?)
- for (int i = 0; i < sz; i++) {
- dst[i] = getXY(i);
- }
- }
-
- @Override
- public void queryCoordinates(Point3D[] dst) {
- int sz = m_pointCount;
- if (dst.length < sz)
- throw new IllegalArgumentException();
-
- // TODO: refactor to a better AttributeAray call (ReadRange?)
- for (int i = 0; i < sz; i++) {
- dst[i] = getXYZ(i);
- }
- }
-
+ // HEADER DEFINED
+ public interface GeometryXSimple {
+ final int Unknown = -1; // not know if simple or not
+ final int Not = 0; // not simple
+ final int Weak = 1; // weak simple (no self intersections, ring
+ // orientation is correct, but ring order is not)
+ final int Strong = 2; // same as weak simple + OGC ring order.
+ }
+
+ // TODO Remove?
+ /**
+ * \internal CHildren implement this method to copy additional information
+ */
+ abstract void _copyToImpl(MultiVertexGeometryImpl mvg);
+
+ protected abstract void _notifyModifiedAllImpl();
+
+ /**
+ * \internal Called inside of the VerifyAllStreams to get a child class a
+ * chance to do additional verify.
+ */
+ protected abstract void _verifyStreamsImpl();
+
+ public interface DirtyFlags {
+ /**0 when IsWeakSimple flag is valid*/
+ int DirtyIsKnownSimple = 1;
+ /**when DirtyIsKnownSimple is 0, this flag indicates whether the geometry is weak simple or not*/
+ int IsWeakSimple = 2;
+ int IsStrongSimple = 4;
+ /**OGCFlags are set by Simplify or WKB/WKT import.*/
+ int DirtyOGCFlags = 8;
+ /** At least one stream is unverified*/
+ int DirtyVerifiedStreams = 32;
+ /** exact envelope is dirty*/
+ int DirtyExactIntervals = 64;
+ /** loose envelope is dirty*/
+ int DirtyLooseIntervals = 128;
+ /** loose and dirty envelopes are dirty */
+ int DirtyIntervals = DirtyExactIntervals
+ | DirtyLooseIntervals;
+ /**the geometry is not known to be an envelope*/
+ int DirtyIsEnvelope = 256;
+ /** The geometry length needs update*/
+ int DirtyLength2D = 512;
+ /** m_cachedRingAreas2D need update*/
+ int DirtyRingAreas2D = 1024;
+ int DirtyCoordinates = DirtyIsKnownSimple
+ | DirtyIntervals | DirtyIsEnvelope | DirtyLength2D
+ | DirtyRingAreas2D | DirtyOGCFlags;
+ int DirtyAllInternal = 0xFFFF;
+ /** There has been a change to one of attribute streams from the outside.*/
+ int DirtyAll = 0xFFFFFF;
+ }
+
+ /**
+ * Returns the total vertex count in this Geometry.
+ *
+ * @return total vertex count in this Geometry.
+ */
+ @Override
+ public int getPointCount() {
+ return m_pointCount;
+ }
+
+ @Override
+ public boolean isEmpty() {
+ return isEmptyImpl();
+ }
+
+ public VertexDescription getDescriptionImpl() {
+ return m_description;
+ }
+
+ boolean isEmptyImpl() {
+ return m_pointCount == 0;
+ }
+
+ protected boolean _hasDirtyFlag(int flag) {
+ return (m_flagsMask & flag) != 0;
+ }
+
+ protected void _setDirtyFlag(int flag, boolean bYesNo) {
+ if (bYesNo)
+ m_flagsMask |= flag;
+ else
+ m_flagsMask &= ~flag;
+ }
+
+ protected void _verifyAllStreams() {
+ if (_hasDirtyFlag(DirtyFlags.DirtyVerifiedStreams))
+ _verifyAllStreamsImpl();
+ }
+
+ protected void throwIfEmpty() {
+ if (isEmptyImpl())
+ // TODO fix exceptions
+ throw new GeometryException(
+ "This operation was performed on an Empty Geometry.");
+ }
+
+ private static final long serialVersionUID = 1L;
+
+ AttributeStreamBase[] m_vertexAttributes;
+ // TODO implement accelerators
+ GeometryAccelerators m_accelerators;
+ Envelope m_envelope; // the BBOX for all attributes
+ protected int m_pointCount;
+ protected int m_reservedPointCount;// the number of vertices reserved and
+ // initialized to default value.
+ protected int m_flagsMask;
+ protected double m_simpleTolerance;
+
+ public MultiVertexGeometryImpl() {
+ m_flagsMask = DirtyFlags.DirtyAllInternal;
+ m_pointCount = 0;
+ m_reservedPointCount = -1;
+ m_accelerators = null;
+ }
+
+ @Override
+ public void getPointByVal(int index, Point dst) {
+ if (index < 0 || index >= m_pointCount)
+ // TODO
+ throw new GeometryException("index out of bounds");
+
+ _verifyAllStreams();
+
+ Point outPoint = dst;
+ outPoint.assignVertexDescription(m_description);
+
+ for (int attributeIndex = 0; attributeIndex < m_description
+ .getAttributeCount(); attributeIndex++) {
+ // fix semantics
+ int semantics = m_description._getSemanticsImpl(attributeIndex);
+
+ // VertexDescription.getComponentCount(semantics);
+ for (int icomp = 0, ncomp = VertexDescription
+ .getComponentCount(semantics); icomp < ncomp; icomp++) {
+ double v = m_vertexAttributes[attributeIndex].readAsDbl(ncomp
+ * index + icomp);
+ outPoint.setAttribute(semantics, icomp, v);
+ }
+ }
+ }
+
+ @Override
+ public void setPointByVal(int index, Point src) {
+ if (index < 0 || index >= m_pointCount)
+ throw new GeometryException("index out of bounds");
+
+ Point point = src;
+
+ if (src.isEmpty())// can not assign an empty point to a multipoint
+ // vertex
+ throw new IllegalArgumentException();
+
+ _verifyAllStreams();// verify all allocated streams are of necessary
+ // size.
+ VertexDescription vdin = point.getDescription();
+ for (int attributeIndex = 0; attributeIndex < vdin.getAttributeCount(); attributeIndex++) {
+ int semantics = vdin._getSemanticsImpl(attributeIndex);
+ int ncomp = VertexDescription.getComponentCount(semantics);
+ for (int icomp = 0; icomp < ncomp; icomp++) {
+ double v = point.getAttributeAsDbl(semantics, icomp);
+ setAttribute(semantics, index, icomp, v);
+ }
+ }
+ }
+
+ // Checked vs. Jan 11, 2011
+ @Override
+ public Point2D getXY(int index) {
+ Point2D pt = new Point2D();
+ getXY(index, pt);
+ return pt;
+ }
+
+ @Override
+ public void getXY(int index, Point2D pt) {
+ if (index < 0 || index >= getPointCount())
+ throw new IndexOutOfBoundsException();
+
+ _verifyAllStreams();
+ // AttributeStreamOfDbl v = (AttributeStreamOfDbl)
+ // m_vertexAttributes[0];
+ AttributeStreamOfDbl v = (AttributeStreamOfDbl) m_vertexAttributes[0];
+ v.read(index * 2, pt);
+ }
+
+ // Checked vs. Jan 11, 2011
+ @Override
+ public void setXY(int index, Point2D pt) {
+ if (index < 0 || index >= m_pointCount)
+ // TODO exception
+ throw new IndexOutOfBoundsException();
+
+ _verifyAllStreams();
+ // AttributeStreamOfDbl v = (AttributeStreamOfDbl)
+ // m_vertexAttributes[0];
+ AttributeStreamOfDbl v = (AttributeStreamOfDbl) m_vertexAttributes[0];
+ v.write(index * 2, pt);
+ notifyModified(DirtyFlags.DirtyCoordinates);
+ }
+
+ // Checked vs. Jan 11, 2011
+ public void setXY(int index, double x, double y) {
+ if (index < 0 || index >= m_pointCount)
+ // TODO exc
+ throw new IndexOutOfBoundsException();
+
+ _verifyAllStreams();
+ // AttributeStreamOfDbl v = (AttributeStreamOfDbl)
+ // m_vertexAttributes[0];
+ // TODO ask sergey about casts
+ AttributeStreamOfDbl v = (AttributeStreamOfDbl) m_vertexAttributes[0];
+ v.write(index * 2, x);
+ v.write(index * 2 + 1, y);
+ notifyModified(DirtyFlags.DirtyCoordinates);
+ }
+
+ // Checked vs. Jan 11, 2011
+ @Override
+ public Point3D getXYZ(int index) {
+ if (index < 0 || index >= getPointCount())
+ throw new IndexOutOfBoundsException();
+
+ _verifyAllStreams();
+ AttributeStreamOfDbl v = (AttributeStreamOfDbl) m_vertexAttributes[0];
+ Point3D pt = new Point3D();
+ pt.x = v.read(index * 2);
+ pt.y = v.read(index * 2 + 1);
+
+ // TODO check excluded if statement componenet
+ if (hasAttribute(Semantics.Z))// && (m_vertexAttributes[1] != null))
+ pt.z = m_vertexAttributes[1].readAsDbl(index);
+ else
+ pt.z = VertexDescription.getDefaultValue(Semantics.Z);
+
+ return pt;
+ }
+
+ // Checked vs. Jan 11, 2011
+ @Override
+ public void setXYZ(int index, Point3D pt) {
+ if (index < 0 || index >= getPointCount())
+ throw new IndexOutOfBoundsException();
+
+ addAttribute(Semantics.Z);
+
+ _verifyAllStreams();
+ notifyModified(DirtyFlags.DirtyCoordinates);
+ AttributeStreamOfDbl v = (AttributeStreamOfDbl) m_vertexAttributes[0];
+ v.write(index * 2, pt.x);
+ v.write(index * 2 + 1, pt.y);
+ m_vertexAttributes[1].writeAsDbl(index, pt.z);
+ }
+
+ // Checked vs. Jan 11, 2011
+ @Override
+ public double getAttributeAsDbl(int semantics, int offset, int ordinate) {
+ if (offset < 0 || offset >= m_pointCount)
+ throw new IndexOutOfBoundsException();
+
+ int ncomps = VertexDescription.getComponentCount(semantics);
+ if (ordinate >= ncomps)
+ throw new IndexOutOfBoundsException();
+
+ _verifyAllStreams();
+ int attributeIndex = m_description.getAttributeIndex(semantics);
+ // TODO check if statement
+ if (attributeIndex >= 0)// && m_vertexAttributes[attributeIndex] !=
+ // null) {
+ {
+ return m_vertexAttributes[attributeIndex].readAsDbl(offset * ncomps
+ + ordinate);
+ }
+ return VertexDescription.getDefaultValue(semantics);
+ }
+
+ // Checked vs. Jan 11, 2011
+ @Override
+ public int getAttributeAsInt(int semantics, int offset, int ordinate) {
+ return (int) getAttributeAsDbl(semantics, offset, ordinate);
+ }
+
+ // Checked vs. Jan 11, 2011
+ @Override
+ public void setAttribute(int semantics, int offset, int ordinate,
+ double value) {
+ if (offset < 0 || offset >= m_pointCount)
+ throw new IndexOutOfBoundsException();
+
+ int ncomps = VertexDescription.getComponentCount(semantics);
+ if (ordinate >= ncomps)
+ throw new IndexOutOfBoundsException();
+
+ addAttribute(semantics);
+ _verifyAllStreams();
+ int attributeIndex = m_description.getAttributeIndex(semantics);
+ notifyModified(DirtyFlags.DirtyCoordinates);
+ m_vertexAttributes[attributeIndex].writeAsDbl(offset * ncomps
+ + ordinate, value);
+ }
+
+ // Checked vs. Jan 11, 2011
+ @Override
+ public void setAttribute(int semantics, int offset, int ordinate, int value) {
+ setAttribute(semantics, offset, ordinate, (double) value);
+ }
+
+ public AttributeStreamBase getAttributeStreamRef(int semantics) {
+ throwIfEmpty();
+
+ addAttribute(semantics);
+ _verifyAllStreams();
+
+ int attributeIndex = m_description.getAttributeIndex(semantics);
+ return m_vertexAttributes[attributeIndex];
+ }
+
+ /**
+ * Sets a reference to the given AttributeStream of the Geometry. Once the
+ * buffer has been obtained, the vertices of the Geometry can be manipulated
+ * directly. The AttributeStream parameters are not checked for the size.
+ * If the attribute is missing, it will be added.
+ * Note, that this method does not change the vertex count in the Geometry.
+ * The stream can have more elements, than the Geometry point count, but
+ * only necessary part will be saved when exporting to a ESRI shape or other
+ * format. @param semantics Semantics of the attribute to assign the stream
+ * to. @param stream The input AttributeStream that will be assigned by
+ * reference. If one changes the stream later through the reference, one has
+ * to call NotifyStreamChanged. \exception Throws invalid_argument exception
+ * if the input stream type does not match that of the semantics
+ * persistence.
+ */
+ public void setAttributeStreamRef(int semantics, AttributeStreamBase stream) {
+ // int test1 = VertexDescription.getPersistence(semantics);
+ // int test2 = stream.getPersistence();
+
+ if ((stream != null)
+ && VertexDescription.getPersistence(semantics) != stream
+ .getPersistence())// input stream has wrong persistence
+ throw new IllegalArgumentException();
+
+ // Do not check for the stream size here to allow several streams to be
+ // attached before the point count is changed.
+ addAttribute(semantics);
+ int attributeIndex = m_description.getAttributeIndex(semantics);
+ if (m_vertexAttributes == null)
+ m_vertexAttributes = new AttributeStreamBase[m_description
+ .getAttributeCount()];
+
+ m_vertexAttributes[attributeIndex] = stream;
+ notifyModified(DirtyFlags.DirtyAll);
+ }
+
+ @Override
+ protected void _assignVertexDescriptionImpl(VertexDescription newDescription) {
+ AttributeStreamBase[] newAttributes = null;
+
+ if (m_vertexAttributes != null) {
+ int[] mapping = VertexDescriptionDesignerImpl.mapAttributes(
+ newDescription, m_description);
+
+ newAttributes = new AttributeStreamBase[newDescription
+ .getAttributeCount()];
+
+ for (int i = 0, n = newDescription.getAttributeCount(); i < n; i++) {
+ if (mapping[i] != -1) {
+ int m = mapping[i];
+ newAttributes[i] = m_vertexAttributes[m];
+ }
+
+ }
+ }
+ else {
+ //if there are no streams we do not create them
+ }
+
+ m_description = newDescription;
+ m_vertexAttributes = newAttributes; // late assignment to try to stay
+ m_reservedPointCount = -1;// we need to recreate the new attribute then
+ notifyModified(DirtyFlags.DirtyAll);
+ }
+
+ // Checked vs. Jan 11, 2011
+ protected void _updateEnvelope(Envelope2D env) {
+ _updateAllDirtyIntervals(true);
+ m_envelope.queryEnvelope2D(env);
+ } // note: overload for polylines/polygons with curves
+
+ // Checked vs. Jan 11, 2011
+ protected void _updateEnvelope(Envelope3D env) {
+ _updateAllDirtyIntervals(true);
+ m_envelope.queryEnvelope3D(env);
+ } // note: overload for polylines/polygons with curves
+
+ // Checked vs. Jan 11, 2011
+ protected void _updateLooseEnvelope(Envelope2D env) {
+ // TODO ROHIT has this set to true?
+ _updateAllDirtyIntervals(false);
+ m_envelope.queryEnvelope2D(env);
+ } // note: overload for polylines/polygons with curves
+
+ // Checked vs. Jan 11, 2011
+ /**
+ * \internal Calculates loose envelope. Returns True if the calculation
+ * renders exact envelope.
+ */
+ protected void _updateLooseEnvelope(Envelope3D env) {
+ // TODO ROHIT has this set to true?
+ _updateAllDirtyIntervals(false);
+ m_envelope.queryEnvelope3D(env);
+ } // note: overload for polylines/polygons with curves
+
+ // Checked vs. Jan 11, 2011
+ @Override
+ public void queryEnvelope(Envelope env) {
+ _updateAllDirtyIntervals(true);
+ m_envelope.copyTo(env);
+ }
+
+ // TODO rename to remove 2D
+ // Checked vs. Jan 11, 2011
+ @Override
+ public void queryEnvelope2D(Envelope2D env) {
+ _updateEnvelope(env);
+ }
+
+ // Checked vs. Jan 11, 2011
+ // TODO rename to remove 3D
+ @Override
+ public void queryEnvelope3D(Envelope3D env) {
+ _updateEnvelope(env);
+ }
+
+ // Checked vs. Jan 11, 2011
+ // TODO rename to remove 2D
+ @Override
+ public void queryLooseEnvelope2D(Envelope2D env) {
+ _updateLooseEnvelope(env);
+ }
+
+ // Checked vs. Jan 11, 2011
+ // TODO rename to remove 3D
+ @Override
+ public void queryLooseEnvelope3D(Envelope3D env) {
+ _updateLooseEnvelope(env);
+ }
+
+ // Checked vs. Jan 11, 2011
+ @Override
+ public Envelope1D queryInterval(int semantics, int ordinate) {
+ Envelope1D env = new Envelope1D();
+ if (isEmptyImpl()) {
+ env.setEmpty();
+ return env;
+ }
+
+ _updateAllDirtyIntervals(true);
+ return m_envelope.queryInterval(semantics, ordinate);
+ }
+
+ // Checked vs. Jan 11, 2011
+ // TODO Rename to getHashCode
+ @Override
+ public int hashCode() {
+ int hashCode = m_description.hashCode();
+
+ if (!isEmptyImpl()) {
+ int pointCount = getPointCount();
+ for (int i = 0, n = m_description.getAttributeCount(); i < n; i++) {
+ int components = VertexDescription
+ .getComponentCount(m_description._getSemanticsImpl(i));
+ AttributeStreamBase stream = m_vertexAttributes[i];
+ hashCode = stream.calculateHashImpl(hashCode, 0, pointCount
+ * components);
+ }
+ }
+
+ return hashCode;
+ }
+
+ // Checked vs. Jan 11, 2011
+ @Override
+ public boolean equals(Object other) {
+ // Java checks
+ if (other == this)
+ return true;
+
+ if (!(other instanceof MultiVertexGeometryImpl))
+ return false;
+
+ MultiVertexGeometryImpl otherMulti = (MultiVertexGeometryImpl) other;
+
+ if (!(m_description.equals(otherMulti.m_description)))
+ return false;
+
+ if (isEmptyImpl() != otherMulti.isEmptyImpl())
+ return false;
+
+ if (isEmptyImpl())
+ return true; // both geometries are empty
+
+ int pointCount = getPointCount();
+ int pointCountOther = otherMulti.getPointCount();
+
+ if (pointCount != pointCountOther)
+ return false;
+
+ for (int i = 0; i < m_description.getAttributeCount(); i++) {
+ int semantics = m_description.getSemantics(i);
+
+ AttributeStreamBase stream = getAttributeStreamRef(semantics);
+ AttributeStreamBase streamOther = otherMulti
+ .getAttributeStreamRef(semantics);
+
+ int components = VertexDescription.getComponentCount(semantics);
+
+ if (!stream.equals(streamOther, 0, pointCount * components))
+ return false;
+ }
+
+ return true;
+ }
+
+ // Checked vs. Jan 11, 2011
+ /**
+ * Sets the envelope of the Geometry. The Envelope description must match
+ * that of the Geometry.
+ */
+ public void setEnvelope(Envelope env) {
+ if (!m_description.equals(env.getDescription()))
+ throw new IllegalArgumentException();
+
+ // m_envelope = (Envelope) env.clone();
+ m_envelope = (Envelope) env.createInstance();
+ env.copyTo(m_envelope);
+ _setDirtyFlag(DirtyFlags.DirtyIntervals, false);
+ }
+
+ @Override
+ public void copyTo(Geometry dstGeom) {
+ MultiVertexGeometryImpl dst = (MultiVertexGeometryImpl) dstGeom;
+ if (dst.getType() != getType())
+ throw new IllegalArgumentException();
+
+ _copyToUnsafe(dst);
+ }
+
+ //Does not check geometry type. Used to copy Polygon to Polyline
+ void _copyToUnsafe(MultiVertexGeometryImpl dst) {
+ _verifyAllStreams();
+ dst.m_description = m_description;
+ dst.m_vertexAttributes = null;
+ int nattrib = m_description.getAttributeCount();
+ AttributeStreamBase[] cloneAttributes = null;
+ if (m_vertexAttributes != null) {
+ cloneAttributes = new AttributeStreamBase[nattrib];
+ for (int i = 0; i < nattrib; i++) {
+ if (m_vertexAttributes[i] != null) {
+ int ncomps = VertexDescription
+ .getComponentCount(m_description
+ ._getSemanticsImpl(i));
+ cloneAttributes[i] = m_vertexAttributes[i]
+ .restrictedClone(getPointCount() * ncomps);
+ }
+ }
+ }
+
+ if (m_envelope != null) {
+ dst.m_envelope = (Envelope) m_envelope.createInstance();
+ m_envelope.copyTo(dst.m_envelope);
+ // dst.m_envelope = (Envelope) m_envelope.clone();
+ } else
+ dst.m_envelope = null;
+
+ dst.m_pointCount = m_pointCount;
+ dst.m_flagsMask = m_flagsMask;
+ dst.m_vertexAttributes = cloneAttributes;
+
+ try {
+ _copyToImpl(dst); // copy child props
+ } catch (Exception ex) {
+ dst.setEmpty();
+ throw new RuntimeException(ex);
+ }
+ }
+
+ // Checked vs. Jan 11, 2011
+ public boolean _attributeStreamIsAllocated(int semantics) {
+ throwIfEmpty();
+
+ int attributeIndex = m_description.getAttributeIndex(semantics);
+
+ if (attributeIndex >= 0 && m_vertexAttributes[attributeIndex] != null)
+ return true;
+
+ return false;
+ }
+
+ // Checked vs. Jan 11, 2011
+ void _setEmptyImpl() {
+ m_pointCount = 0;
+ m_reservedPointCount = -1;
+ m_vertexAttributes = null;// release it all streams.
+ notifyModified(DirtyFlags.DirtyAll);
+ }
+
+ // Checked vs. Jan 11, 2011
+ /**
+ * Notifies the Geometry of changes made to the vertices so that it could
+ * reset cached structures.
+ */
+ public void notifyModified(int flags) {
+ if (flags == DirtyFlags.DirtyAll) {
+ m_reservedPointCount = -1;// forget the reserved point number
+ _notifyModifiedAllImpl();
+ }
+ m_flagsMask |= flags;
+
+ _clearAccelerators();
+ _touch();
+ }
+
+ // Checked vs. Jan 11, 2011
+ /**
+ * @param bExact
+ * True, when the exact envelope need to be calculated and false
+ * for the loose one.
+ */
+ protected void _updateAllDirtyIntervals(boolean bExact) {
+ _verifyAllStreams();
+ if (_hasDirtyFlag(DirtyFlags.DirtyIntervals)) {
+ if (null == m_envelope)
+ m_envelope = new Envelope(m_description);
+ else
+ m_envelope.assignVertexDescription(m_description);
+
+ if (isEmpty()) {
+ m_envelope.setEmpty();
+ return;
+ }
+
+ _updateXYImpl(bExact);// efficient method for xy's
+ // now go through other attribues.
+ for (int attributeIndex = 1; attributeIndex < m_description
+ .getAttributeCount(); attributeIndex++) {
+ int semantics = m_description._getSemanticsImpl(attributeIndex);
+ int ncomps = VertexDescription.getComponentCount(semantics);
+ AttributeStreamBase stream = m_vertexAttributes[attributeIndex];
+ for (int iord = 0; iord < ncomps; iord++) {
+ Envelope1D interval = new Envelope1D();
+ interval.setEmpty();
+ for (int i = 0; i < m_pointCount; i++) {
+ double value = stream.readAsDbl(i * ncomps + iord);// some
+ // optimization
+ // is
+ // possible
+ // if
+ // non-virtual
+ // method
+ // is
+ // used
+ interval.merge(value);
+ }
+ m_envelope.setInterval(semantics, iord, interval);
+ }
+ }
+ if (bExact)
+ _setDirtyFlag(DirtyFlags.DirtyIntervals, false);
+ }
+ }
+
+ // Checked vs. Jan 11, 2011
+ /**
+ * \internal Updates x, y intervals.
+ */
+ public void _updateXYImpl(boolean bExact) {
+ m_envelope.setEmpty();
+ AttributeStreamOfDbl stream = (AttributeStreamOfDbl) m_vertexAttributes[0];
+ Point2D pt = new Point2D();
+ for (int i = 0; i < m_pointCount; i++) {
+ stream.read(2 * i, pt);
+ m_envelope.merge(pt);
+ }
+ }
+
+ void calculateEnvelope2D(Envelope2D env, boolean bExact) {
+ env.setEmpty();
+ AttributeStreamOfDbl stream = (AttributeStreamOfDbl) m_vertexAttributes[0];
+ Point2D pt = new Point2D();
+ for (int i = 0; i < m_pointCount; i++) {
+ stream.read(2 * i, pt);
+ env.merge(pt);
+ }
+ }
+
+ // Checked vs. Jan 11, 2011 lots of changes
+ /**
+ * \internal Verifies all streams (calls _VerifyStream for every attribute).
+ */
+ protected void _verifyAllStreamsImpl() {
+ // This method checks that the streams are of correct size.
+ // It resizes the streams to ensure they are not shorter than
+ // m_PointCount
+ // _ASSERT(_HasDirtyFlag(enum_value1(DirtyFlags,
+ // DirtyVerifiedStreams)));
+ if (m_reservedPointCount < m_pointCount) // an optimization to skip this
+ // expensive loop when
+ // adding point by point
+ {
+ if (m_vertexAttributes == null)
+ m_vertexAttributes = new AttributeStreamBase[m_description
+ .getAttributeCount()];
+
+ m_reservedPointCount = NumberUtils.intMax();
+ for (int attributeIndex = 0; attributeIndex < m_description
+ .getAttributeCount(); attributeIndex++) {
+ int semantics = m_description._getSemanticsImpl(attributeIndex);
+ if (m_vertexAttributes[attributeIndex] != null) {
+ int ncomp = VertexDescription.getComponentCount(semantics);
+ int size = m_vertexAttributes[attributeIndex].virtualSize()
+ / ncomp;
+ if (size < m_pointCount) {
+ size = (m_reservedPointCount > m_pointCount + 5) ? (m_pointCount * 5 + 3) / 4
+ : m_pointCount;// reserve 25% more than user
+ // asks
+ m_vertexAttributes[attributeIndex].resize(size * ncomp,
+ VertexDescription.getDefaultValue(semantics));
+ }
+
+ if (size < m_reservedPointCount)
+ m_reservedPointCount = size;
+ } else {
+ m_vertexAttributes[attributeIndex] = AttributeStreamBase
+ .createAttributeStreamWithSemantics(semantics,
+ m_pointCount);
+ m_reservedPointCount = m_pointCount;
+ }
+ }
+ }
+ _verifyStreamsImpl();
+
+ _setDirtyFlag(DirtyFlags.DirtyVerifiedStreams, false);
+ }
+
+ // Checked vs. Jan 11, 2011
+ void _resizeImpl(int pointCount) {
+ if (pointCount < 0)
+ throw new IllegalArgumentException();
+
+ if (pointCount == m_pointCount)
+ return;
+
+ m_pointCount = pointCount;
+ notifyModified(DirtyFlags.DirtyAllInternal);
+ }
+
+ // Checked vs. Jan 11, 2011
+ int queryCoordinates(Point2D[] dst, int dstSize, int beginIndex,
+ int endIndex) {
+ int endIndexC = endIndex < 0 ? m_pointCount : endIndex;
+ endIndexC = Math.min(endIndexC, beginIndex + dstSize);
+
+ if (beginIndex < 0 || beginIndex >= m_pointCount
+ || endIndexC < beginIndex)
+ throw new IllegalArgumentException();
+
+ AttributeStreamOfDbl xy = (AttributeStreamOfDbl) getAttributeStreamRef(VertexDescription.Semantics.POSITION);
+ int j = 0;
+ double[] dstArray = new double[dst.length * 2];
+ xy.readRange(2 * beginIndex, (endIndexC - beginIndex) * 2, dstArray, j, true);
+
+ for (int i = 0; i < dst.length; i++) {
+ dst[i] = new Point2D(dstArray[i * 2], dstArray[i * 2 + 1]);
+ }
+
+ // for (int i = beginIndex; i < endIndexC; i++, j++)
+ // {
+ // xy.read(2 * i, dst[j]);
+ // }
+
+ return endIndexC;
+ }
+
+ // Checked vs. Jan 11, 2011
+ int QueryCoordinates(Point3D[] dst, int dstSize, int beginIndex,
+ int endIndex) {
+ int endIndexC = endIndex < 0 ? m_pointCount : endIndex;
+ endIndexC = Math.min(endIndexC, beginIndex + dstSize);
+
+ if (beginIndex < 0 || beginIndex >= m_pointCount
+ || endIndexC < beginIndex)
+ // TODO replace geometry exc
+ throw new IllegalArgumentException();
+
+ AttributeStreamOfDbl xy = (AttributeStreamOfDbl) getAttributeStreamRef(VertexDescription.Semantics.POSITION);
+ AttributeStreamOfDbl z = null;
+ double v = VertexDescription
+ .getDefaultValue(VertexDescription.Semantics.Z);
+ boolean bHasZ = hasAttribute(VertexDescription.Semantics.Z);
+ if (bHasZ)
+ z = (AttributeStreamOfDbl) getAttributeStreamRef(VertexDescription.Semantics.Z);
+ int j = 0;
+ for (int i = beginIndex; i < endIndexC; i++, j++) {
+ dst[j].x = xy.read(2 * i);
+ dst[j].y = xy.read(2 * i + 1);
+ dst[j].z = bHasZ ? z.read(i) : v;
+
+ dst[j] = getXYZ(i);
+ }
+
+ return endIndexC;
+ }
+
+ // Checked vs. Jan 11, 2011
+ // -1 : DirtySimple is true (whether or not the MultiPath is Simple is
+ // unknown)
+ // 0 : DirtySimple is false and the MultiPath is not Weak Simple
+ // 1 : DirtySimple is false and the MultiPath is Weak Simple but not ring
+ // ordering may be invalid
+ // 2 : DirtySimple is false and the MultiPath is Strong Simple (Weak Simple
+ // and valid ring ordering)
+ public int getIsSimple(double tolerance) {
+ if (!_hasDirtyFlag(DirtyFlags.DirtyIsKnownSimple)) {
+ if (!_hasDirtyFlag(DirtyFlags.IsWeakSimple)) {
+ return 0;
+ }
+ if (m_simpleTolerance >= tolerance) {
+ if (!_hasDirtyFlag(DirtyFlags.DirtyOGCFlags))
+ return 2;
+
+ return 1;
+ }
+
+ return -1;
+ }
+ return -1;
+ }
+
+ void setIsSimple(int isSimpleRes, double tolerance, boolean ogc_known) {
+ m_simpleTolerance = tolerance;
+ if (isSimpleRes == GeometryXSimple.Unknown) {
+ _setDirtyFlag(DirtyFlags.DirtyIsKnownSimple, true);
+ _setDirtyFlag(DirtyFlags.DirtyOGCFlags, true);
+ return;
+ }
+ _setDirtyFlag(DirtyFlags.DirtyIsKnownSimple, false);
+
+ if (!ogc_known)
+ _setDirtyFlag(DirtyFlags.DirtyOGCFlags, true);
+
+ if (isSimpleRes == GeometryXSimple.Not) {
+ _setDirtyFlag(DirtyFlags.IsWeakSimple, false);
+ _setDirtyFlag(DirtyFlags.IsStrongSimple, false);
+ } else if (isSimpleRes == GeometryXSimple.Weak) {
+ _setDirtyFlag(DirtyFlags.IsWeakSimple, true);
+ _setDirtyFlag(DirtyFlags.IsStrongSimple, false);
+ } else if (isSimpleRes == GeometryXSimple.Strong) {
+ _setDirtyFlag(DirtyFlags.IsWeakSimple, true);
+ _setDirtyFlag(DirtyFlags.IsStrongSimple, true);
+ } else
+ throw GeometryException.GeometryInternalError();// what?
+ }
+
+ double _getSimpleTolerance() {
+ return m_simpleTolerance;
+ }
+
+ public GeometryAccelerators _getAccelerators() {
+ return m_accelerators;
+ }
+
+ void _clearAccelerators() {
+ if (m_accelerators != null)
+ m_accelerators = null;
+ }
+
+ void _interpolateTwoVertices(int vertex1, int vertex2, double f,
+ Point outPoint) {
+ if (vertex1 < 0 || vertex1 >= m_pointCount)
+ throw new GeometryException("index out of bounds.");
+ if (vertex2 < 0 || vertex2 >= m_pointCount)
+ throw new GeometryException("index out of bounds.");
+
+ // _ASSERT(!IsEmpty());
+ // _ASSERT(m_vertexAttributes != NULLPTR);
+
+ _verifyAllStreams();
+
+ outPoint.assignVertexDescription(m_description);
+ for (int attributeIndex = 0; attributeIndex < m_description
+ .getAttributeCount(); attributeIndex++) {
+ int semantics = m_description._getSemanticsImpl(attributeIndex);
+ for (int icomp = 0, ncomp = VertexDescription
+ .getComponentCount(semantics); icomp < ncomp; icomp++) {
+ double v1 = m_vertexAttributes[attributeIndex].readAsDbl(ncomp
+ * vertex1 + icomp);
+ double v2 = m_vertexAttributes[attributeIndex].readAsDbl(ncomp
+ * vertex2 + icomp);
+ outPoint.setAttribute(semantics, icomp, MathUtils.lerp(v1, v2, f));
+ }
+ }
+ }
+
+ double _getShortestDistance(int vertex1, int vertex2) {
+ Point2D pt = getXY(vertex1);
+ pt.sub(getXY(vertex2));
+ return pt.length();
+ }
+
+ // ////////////////// METHODS To REMOVE ///////////////////////
+ @Override
+ public Point getPoint(int index) {
+ if (index < 0 || index >= m_pointCount)
+ throw new IndexOutOfBoundsException();
+
+ _verifyAllStreams();
+
+ Point outPoint = new Point();
+ outPoint.assignVertexDescription(m_description);
+
+ for (int attributeIndex = 0; attributeIndex < m_description
+ .getAttributeCount(); attributeIndex++) {
+ int semantics = m_description.getSemantics(attributeIndex);
+ for (int icomp = 0, ncomp = VertexDescription
+ .getComponentCount(semantics); icomp < ncomp; icomp++) {
+ double v = m_vertexAttributes[attributeIndex].readAsDbl(ncomp
+ * index + icomp);
+ outPoint.setAttribute(semantics, icomp, v);
+ }
+ }
+ return outPoint;
+ }
+
+ @Override
+ public void setPoint(int index, Point src) {
+ if (index < 0 || index >= m_pointCount)
+ throw new IndexOutOfBoundsException();
+
+ Point point = src;
+
+ if (src.isEmpty())// can not assign an empty point to a multipoint
+ // vertex
+ throw new IllegalArgumentException();
+
+ _verifyAllStreams();// verify all allocated streams are of necessary
+ // size.
+ VertexDescription vdin = point.getDescription();
+ for (int attributeIndex = 0; attributeIndex < vdin.getAttributeCount(); attributeIndex++) {
+ int semantics = vdin.getSemantics(attributeIndex);
+ int ncomp = VertexDescription.getComponentCount(semantics);
+ for (int icomp = 0; icomp < ncomp; icomp++) {
+ double v = point.getAttributeAsDbl(semantics, icomp);
+ setAttribute(semantics, index, icomp, v);
+ }
+ }
+ }
+
+ @Override
+ public void queryCoordinates(Point[] dst) {
+ int sz = m_pointCount;
+ if (dst.length < sz)
+ throw new IllegalArgumentException();
+
+ // TODO: refactor to a better AttributeAray call (ReadRange?)
+ for (int i = 0; i < sz; i++) {
+ dst[i] = getPoint(i);
+ }
+ }
+
+ @Override
+ public void queryCoordinates(Point2D[] dst) {
+ int sz = m_pointCount;
+ if (dst.length < sz)
+ throw new IllegalArgumentException();
+
+ // TODO: refactor to a better AttributeAray call (ReadRange?)
+ for (int i = 0; i < sz; i++) {
+ dst[i] = getXY(i);
+ }
+ }
+
+ @Override
+ public void queryCoordinates(Point3D[] dst) {
+ int sz = m_pointCount;
+ if (dst.length < sz)
+ throw new IllegalArgumentException();
+
+ // TODO: refactor to a better AttributeAray call (ReadRange?)
+ for (int i = 0; i < sz; i++) {
+ dst[i] = getXYZ(i);
+ }
+ }
+
@Override
public void replaceNaNs(int semantics, double value) {
- addAttribute(semantics);
- if (isEmpty())
- return;
-
- boolean modified = false;
- int ncomps = VertexDescription.getComponentCount(semantics);
- for (int i = 0; i < ncomps; i++) {
- AttributeStreamBase streamBase = getAttributeStreamRef(semantics);
- if (streamBase instanceof AttributeStreamOfDbl) {
- AttributeStreamOfDbl dblStream = (AttributeStreamOfDbl) streamBase;
- for (int ivert = 0, n = m_pointCount * ncomps; ivert < n; ivert++) {
- double v = dblStream.read(ivert);
- if (Double.isNaN(v)) {
- dblStream.write(ivert, value);
- modified = true;
- }
- }
- } else {
- for (int ivert = 0, n = m_pointCount * ncomps; ivert < n; ivert++) {
- double v = streamBase.readAsDbl(ivert);
- if (Double.isNaN(v)) {
- streamBase.writeAsDbl(ivert, value);
- modified = true;
- }
- }
- }
- }
-
- if (modified) {
- notifyModified(DirtyFlags.DirtyCoordinates);
- }
+ addAttribute(semantics);
+ if (isEmpty())
+ return;
+
+ boolean modified = false;
+ int ncomps = VertexDescription.getComponentCount(semantics);
+ for (int i = 0; i < ncomps; i++) {
+ AttributeStreamBase streamBase = getAttributeStreamRef(semantics);
+ if (streamBase instanceof AttributeStreamOfDbl) {
+ AttributeStreamOfDbl dblStream = (AttributeStreamOfDbl)streamBase;
+ for (int ivert = 0, n = m_pointCount * ncomps; ivert < n; ivert++) {
+ double v = dblStream.read(ivert);
+ if (Double.isNaN(v)) {
+ dblStream.write(ivert, value);
+ modified = true;
+ }
+ }
+ }
+ else {
+ for (int ivert = 0, n = m_pointCount * ncomps; ivert < n; ivert++) {
+ double v = streamBase.readAsDbl(ivert);
+ if (Double.isNaN(v)) {
+ streamBase.writeAsDbl(ivert, value);
+ modified = true;
+ }
+ }
+ }
+ }
+
+ if (modified) {
+ notifyModified(DirtyFlags.DirtyCoordinates);
+ }
}
- public abstract boolean _buildRasterizedGeometryAccelerator(
- double toleranceXY, GeometryAccelerationDegree accelDegree);
+ public abstract boolean _buildRasterizedGeometryAccelerator(
+ double toleranceXY, GeometryAccelerationDegree accelDegree);
- public abstract boolean _buildQuadTreeAccelerator(
- GeometryAccelerationDegree d);
+ public abstract boolean _buildQuadTreeAccelerator(
+ GeometryAccelerationDegree d);
- @Override
- public String toString() {
- return "MultiVertexGeometryImpl";
- }
+ @Override
+ public String toString() {
+ return "MultiVertexGeometryImpl";
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/NonSimpleResult.java b/src/main/java/com/esri/core/geometry/NonSimpleResult.java
index 47fa6a59..517a19e7 100644
--- a/src/main/java/com/esri/core/geometry/NonSimpleResult.java
+++ b/src/main/java/com/esri/core/geometry/NonSimpleResult.java
@@ -27,80 +27,80 @@
* The result of the IsSimpleXXX.
*/
public class NonSimpleResult {
- public enum Reason {
- /**
- * This value is returned if the geometry "knows" through an internal state that it is non-simple.
- * To make it determine the reason, use
- * bForceTest == True.
- */
- NotDetermined,
- /**
- * non-simple, because the structure is bad (0 size path, for example).
- */
- Structure,
- /**
- * Non-simple, because there are degenerate segments.
- */
- DegenerateSegments,
- /**
- * Non-simple, because not clustered properly, that is there are non-coincident vertices closer than tolerance.
- */
- Clustering,
- /**
- * Non-simple, because not cracked properly (intersecting segments, overlaping segments)
- */
- Cracking,
- /**
- * Non-simple, because there are crossovers (self intersections that are not cracking case).
- */
- CrossOver,
- /**
- * Non-simple, because holes or exteriors have wrong orientation.
- */
- RingOrientation,
- /**
- * The geometry is simple, but not strong-simple, because exteriors
- * and holes are not in the correct order, and separation into sub polygons is not possible.
- * Geometry needs to be resimplified with the bForceTest = true to fix this.
- */
- RingOrder,
- /**
- * There is a self tangency or cross-over situation (strong simple, but not OGC simple)
- * Only OperatorSimplifyOGC returns this.
- */
- OGCPolylineSelfTangency,
- /**
- * There is a self tangency situation (strong simple, but not OGC simple)
- * Only OperatorSimplifyOGC returns this.
- */
- OGCPolygonSelfTangency,
- /**
- * Touching interioir rings make a disconnected point set from polygon interior
- * (strong simple, but not OGC simple).
- * Only OperatorSimplifyOGC returns this.
- */
- OGCDisconnectedInterior
- }
+ public enum Reason {
+ /**
+ * This value is returned if the geometry "knows" through an internal state that it is non-simple.
+ * To make it determine the reason, use
+ * bForceTest == True.
+ */
+ NotDetermined,
+ /**
+ * non-simple, because the structure is bad (0 size path, for example).
+ */
+ Structure,
+ /**
+ * Non-simple, because there are degenerate segments.
+ */
+ DegenerateSegments,
+ /**
+ * Non-simple, because not clustered properly, that is there are non-coincident vertices closer than tolerance.
+ */
+ Clustering,
+ /**
+ * Non-simple, because not cracked properly (intersecting segments, overlaping segments)
+ */
+ Cracking,
+ /**
+ * Non-simple, because there are crossovers (self intersections that are not cracking case).
+ */
+ CrossOver,
+ /**
+ * Non-simple, because holes or exteriors have wrong orientation.
+ */
+ RingOrientation,
+ /**
+ * The geometry is simple, but not strong-simple, because exteriors
+ * and holes are not in the correct order, and separation into sub polygons is not possible.
+ * Geometry needs to be resimplified with the bForceTest = true to fix this.
+ */
+ RingOrder,
+ /**
+ * There is a self tangency or cross-over situation (strong simple, but not OGC simple)
+ * Only OperatorSimplifyOGC returns this.
+ */
+ OGCPolylineSelfTangency,
+ /**
+ * There is a self tangency situation (strong simple, but not OGC simple)
+ * Only OperatorSimplifyOGC returns this.
+ */
+ OGCPolygonSelfTangency,
+ /**
+ * Touching interioir rings make a disconnected point set from polygon interior
+ * (strong simple, but not OGC simple).
+ * Only OperatorSimplifyOGC returns this.
+ */
+ OGCDisconnectedInterior
+ }
- public Reason m_reason;
- public int m_vertexIndex1;
- public int m_vertexIndex2;
+ public Reason m_reason;
+ public int m_vertexIndex1;
+ public int m_vertexIndex2;
- public NonSimpleResult() {
- m_reason = Reason.NotDetermined;
- m_vertexIndex1 = -1;
- m_vertexIndex2 = -1;
- }
+ public NonSimpleResult() {
+ m_reason = Reason.NotDetermined;
+ m_vertexIndex1 = -1;
+ m_vertexIndex2 = -1;
+ }
- void Assign(NonSimpleResult src) {
- m_reason = src.m_reason;
- m_vertexIndex1 = src.m_vertexIndex1;
- m_vertexIndex2 = src.m_vertexIndex2;
- }
+ void Assign(NonSimpleResult src) {
+ m_reason = src.m_reason;
+ m_vertexIndex1 = src.m_vertexIndex1;
+ m_vertexIndex2 = src.m_vertexIndex2;
+ }
- NonSimpleResult(Reason reason, int index1, int index2) {
- m_reason = reason;
- m_vertexIndex1 = index1;
- m_vertexIndex2 = index2;
- }
+ NonSimpleResult(Reason reason, int index1, int index2) {
+ m_reason = reason;
+ m_vertexIndex1 = index1;
+ m_vertexIndex2 = index2;
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/NumberUtils.java b/src/main/java/com/esri/core/geometry/NumberUtils.java
index 0fc74aa5..01b6fd92 100644
--- a/src/main/java/com/esri/core/geometry/NumberUtils.java
+++ b/src/main/java/com/esri/core/geometry/NumberUtils.java
@@ -26,115 +26,128 @@
public class NumberUtils {
- public static int snap(int v, int minv, int maxv) {
- return v < minv ? minv : v > maxv ? maxv : v;
- }
-
- public static long snap(long v, long minv, long maxv) {
- return v < minv ? minv : v > maxv ? maxv : v;
- }
-
- public static double snap(double v, double minv, double maxv) {
- return v < minv ? minv : v > maxv ? maxv : v;
- }
-
- static int sizeOf(double v) {
- return 8;
- }
-
- static int sizeOfDouble() {
- return 8;
- }
-
- static int sizeOf(int v) {
- return 4;
- }
-
- static int sizeOf(long v) {
- return 8;
- }
-
- static int sizeOf(byte v) {
- return 1;
- }
-
- static boolean isNaN(double d) {
- return Double.isNaN(d);
- }
-
- final static double TheNaN = Double.NaN;
-
- static double NaN() {
- return Double.NaN;
- }
-
- //combines two hash values
- public static int hashCombine(int hash1, int hash2) {
- return (hash1 * 31 + hash2) & 0x7FFFFFFF;
- }
-
- //makes a hash out of an int
- static int hash(int n) {
- int hash = 5381;
- hash = ((hash << 5) + hash) + (n & 0xFF); /* hash * 33 + c */
- hash = ((hash << 5) + hash) + ((n >> 8) & 0xFF);
- hash = ((hash << 5) + hash) + ((n >> 16) & 0xFF);
- hash = ((hash << 5) + hash) + ((n >> 24) & 0xFF);
- hash &= 0x7FFFFFFF;
- return hash;
- }
-
- // //makes a hash out of an double
- static int hash(double d) {
- long bits = Double.doubleToLongBits(d);
- int hc = (int) (bits ^ (bits >>> 32));
- return hash(hc);
- }
-
- //adds an int to a hash value
- static int hash(int hashIn, int n) {
- int hash = ((hashIn << 5) + hashIn) + (n & 0xFF); /* hash * 33 + c */
- hash = ((hash << 5) + hash) + ((n >> 8) & 0xFF);
- hash = ((hash << 5) + hash) + ((n >> 16) & 0xFF);
- hash = ((hash << 5) + hash) + ((n >> 24) & 0xFF);
- hash &= 0x7FFFFFFF;
- return hash;
- }
-
- //adds a double to a hash value
- static int hash(int hash, double d) {
- long bits = Double.doubleToLongBits(d);
- int hc = (int) (bits ^ (bits >>> 32));
- return hash(hash, hc);
- }
-
- static long doubleToInt64Bits(double d) {
- return Double.doubleToLongBits(d);
- }
-
- static double negativeInf() {
- return Double.NEGATIVE_INFINITY;
- }
-
- static double positiveInf() {
- return Double.POSITIVE_INFINITY;
- }
-
- static int intMax() {
- return Integer.MAX_VALUE;
- }
-
- static double doubleEps() {
- return 2.2204460492503131e-016;
- }
-
- static double doubleMax() {
- return Double.MAX_VALUE;
- }
-
- static int nextRand(int prevRand) {
- return (1103515245 * prevRand + 12345) & intMax(); // according to Wiki,
- // this is gcc's
- }
-
+ public static int snap(int v, int minv, int maxv) {
+ return v < minv ? minv : v > maxv ? maxv : v;
+ }
+
+ public static long snap(long v, long minv, long maxv) {
+ return v < minv ? minv : v > maxv ? maxv : v;
+ }
+
+ public static double snap(double v, double minv, double maxv) {
+ return v < minv ? minv : v > maxv ? maxv : v;
+ }
+
+ static int sizeOf(double v) {
+ return 8;
+ }
+
+ static int sizeOfDouble() {
+ return 8;
+ }
+
+ static int sizeOf(int v) {
+ return 4;
+ }
+
+ static int sizeOf(long v) {
+ return 8;
+ }
+
+ static int sizeOf(byte v) {
+ return 1;
+ }
+
+ static boolean isNaN(double d) {
+ return Double.isNaN(d);
+ }
+
+ final static double TheNaN = Double.NaN;
+
+ static double NaN() {
+ return Double.NaN;
+ }
+
+ //combines two hash values
+ public static int hashCombine(int hash1, int hash2) {
+ return (hash1 * 31 + hash2) & 0x7FFFFFFF;
+ }
+
+ //makes a hash out of an int
+ static int hash(int n) {
+ int hash = 5381;
+ hash = ((hash << 5) + hash) + (n & 0xFF); /* hash * 33 + c */
+ hash = ((hash << 5) + hash) + ((n >> 8) & 0xFF);
+ hash = ((hash << 5) + hash) + ((n >> 16) & 0xFF);
+ hash = ((hash << 5) + hash) + ((n >> 24) & 0xFF);
+ hash &= 0x7FFFFFFF;
+ return hash;
+ }
+
+ // //makes a hash out of an double
+ static int hash(double d) {
+ long bits = Double.doubleToLongBits(d);
+ int hc = (int) (bits ^ (bits >>> 32));
+ return hash(hc);
+ }
+
+ //adds an int to a hash value
+ static int hash(int hashIn, int n) {
+ int hash = ((hashIn << 5) + hashIn) + (n & 0xFF); /* hash * 33 + c */
+ hash = ((hash << 5) + hash) + ((n >> 8) & 0xFF);
+ hash = ((hash << 5) + hash) + ((n >> 16) & 0xFF);
+ hash = ((hash << 5) + hash) + ((n >> 24) & 0xFF);
+ hash &= 0x7FFFFFFF;
+ return hash;
+ }
+
+ //adds a double to a hash value
+ static int hash(int hash, double d) {
+ long bits = Double.doubleToLongBits(d);
+ int hc = (int) (bits ^ (bits >>> 32));
+ return hash(hash, hc);
+ }
+
+ static long doubleToInt64Bits(double d) {
+ return Double.doubleToLongBits(d);
+ }
+
+ static double negativeInf() {
+ return Double.NEGATIVE_INFINITY;
+ }
+
+ static double positiveInf() {
+ return Double.POSITIVE_INFINITY;
+ }
+
+ static int intMax() {
+ return Integer.MAX_VALUE;
+ }
+
+ static double doubleEps() {
+ return 2.2204460492503131e-016;
+ }
+
+ static double doubleMax() {
+ return Double.MAX_VALUE;
+ }
+
+ static int nextRand(int prevRand) {
+ return (1103515245 * prevRand + 12345) & intMax(); // according to Wiki,
+ // this is gcc's
+ }
+
+ /**
+ * Returns true if two values are equal (also can compare inf and nan).
+ */
+ static boolean isEqualNonIEEE(double a, double b) {
+ return a == b || (Double.isNaN(a) && Double.isNaN(b));
+ }
+
+ /**
+ * Returns true if two values are equal (also can compare inf and nan).
+ */
+ static boolean isEqualNonIEEE(double a, double b, double tolerance) {
+ return a == b || Math.abs(a - b) <= tolerance || (Double.isNaN(a) && Double.isNaN(b));
+ }
}
diff --git a/src/main/java/com/esri/core/geometry/OGCStructure.java b/src/main/java/com/esri/core/geometry/OGCStructure.java
index b5002dde..9f0875b9 100644
--- a/src/main/java/com/esri/core/geometry/OGCStructure.java
+++ b/src/main/java/com/esri/core/geometry/OGCStructure.java
@@ -26,7 +26,7 @@
import java.util.List;
public class OGCStructure {
- public int m_type;
- public List