public void FillEnvelope(com.epl.geometry.Envelope2D envIn)
        {
            com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D(0, 0, width_, height_);
            if (!env.Intersect(envIn))
            {
                return;
            }
            int x0 = (int)env.xmin;
            int x  = (int)env.xmax;
            int xn = com.epl.geometry.NumberUtils.Snap(x0, 0, width_);
            int xm = com.epl.geometry.NumberUtils.Snap(x, 0, width_);

            if (x0 < width_ && xn < xm)
            {
                int y0 = (int)env.ymin;
                int y1 = (int)env.ymax;
                y0 = com.epl.geometry.NumberUtils.Snap(y0, 0, height_);
                y1 = com.epl.geometry.NumberUtils.Snap(y1, 0, height_);
                if (y0 < height_)
                {
                    for (int y = y0; y < y1; y++)
                    {
                        scanBuffer_[scanPtr_++] = xn;
                        scanBuffer_[scanPtr_++] = xm;
                        scanBuffer_[scanPtr_++] = y;
                        if (scanPtr_ == scanBuffer_.Length)
                        {
                            callback_.DrawScan(scanBuffer_, scanPtr_);
                            scanPtr_ = 0;
                        }
                    }
                }
            }
        }
Example #2
0
		internal virtual com.epl.geometry.GeometryCursor IntersectEx(com.epl.geometry.Geometry input_geom)
		{
			System.Diagnostics.Debug.Assert((m_dimensionMask != -1));
			com.epl.geometry.Geometry dst_geom = TryNativeImplementation_(input_geom);
			if (dst_geom != null)
			{
				com.epl.geometry.Geometry[] res_vec = new com.epl.geometry.Geometry[3];
				res_vec[dst_geom.GetDimension()] = dst_geom;
				return PrepareVector_(input_geom.GetDescription(), m_dimensionMask, res_vec);
			}
			com.epl.geometry.Envelope2D commonExtent = com.epl.geometry.InternalUtils.GetMergedExtent(m_geomIntersector, input_geom);
			double t = com.epl.geometry.InternalUtils.CalculateToleranceFromGeometry(m_spatial_reference, commonExtent, true);
			// Preprocess geometries to be clipped to the extent of intersection to
			// get rid of extra segments.
			com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D();
			m_geomIntersector.QueryEnvelope2D(env);
			env.Inflate(2 * t, 2 * t);
			com.epl.geometry.Envelope2D env1 = new com.epl.geometry.Envelope2D();
			input_geom.QueryEnvelope2D(env1);
			env.Intersect(env1);
			System.Diagnostics.Debug.Assert((!env.IsEmpty()));
			env.Inflate(100 * t, 100 * t);
			double tol = 0;
			com.epl.geometry.Geometry clippedIntersector = com.epl.geometry.Clipper.Clip(m_geomIntersector, env, tol, 0.0);
			com.epl.geometry.Geometry clippedInputGeom = com.epl.geometry.Clipper.Clip(input_geom, env, tol, 0.0);
			// perform the clip
			com.epl.geometry.Geometry[] res_vec_1;
			res_vec_1 = com.epl.geometry.TopologicalOperations.IntersectionEx(clippedInputGeom, clippedIntersector, m_spatial_reference, m_progress_tracker);
			return PrepareVector_(input_geom.GetDescription(), m_dimensionMask, res_vec_1);
		}
Example #3
0
		internal virtual com.epl.geometry.Geometry Intersect(com.epl.geometry.Geometry input_geom)
		{
			com.epl.geometry.Geometry dst_geom = TryNativeImplementation_(input_geom);
			if (dst_geom != null)
			{
				return dst_geom;
			}
			com.epl.geometry.Envelope2D commonExtent = com.epl.geometry.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 = com.epl.geometry.InternalUtils.CalculateToleranceFromGeometry(m_spatial_reference, commonExtent, true);
			com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D();
			m_geomIntersector.QueryEnvelope2D(env);
			com.epl.geometry.Envelope2D env1 = new com.epl.geometry.Envelope2D();
			input_geom.QueryEnvelope2D(env1);
			env.Inflate(2.0 * t, 2.0 * t);
			env.Intersect(env1);
			System.Diagnostics.Debug.Assert((!env.IsEmpty()));
			env.Inflate(100 * t, 100 * t);
			double tol = 0;
			com.epl.geometry.Geometry clippedIntersector = com.epl.geometry.Clipper.Clip(m_geomIntersector, env, tol, 0.0);
			com.epl.geometry.Geometry clippedInputGeom = com.epl.geometry.Clipper.Clip(input_geom, env, tol, 0.0);
			// perform the clip
			return com.epl.geometry.TopologicalOperations.Intersection(clippedInputGeom, clippedIntersector, m_spatial_reference, m_progress_tracker);
		}
Example #4
0
 /// <summary>
 /// Changes this envelope to be the intersection of itself with the other
 /// envelope.
 /// </summary>
 /// <param name="other">The envelope to intersect.</param>
 /// <returns>Returns true if the result is not empty.</returns>
 public virtual bool Intersect(com.epl.geometry.Envelope other)
 {
     _touch();
     com.epl.geometry.Envelope2D e2d = new com.epl.geometry.Envelope2D();
     other.QueryEnvelope2D(e2d);
     return(m_envelope.Intersect(e2d));
 }
        internal static com.epl.geometry.Envelope2DIntersectorImpl GetEnvelope2DIntersectorForParts(com.epl.geometry.MultiPathImpl multipathImplA, com.epl.geometry.MultiPathImpl multipathImplB, double tolerance, bool bExteriorOnlyA, bool bExteriorOnlyB)
        {
            int type_a = multipathImplA.GetType().Value();
            int type_b = multipathImplB.GetType().Value();

            com.epl.geometry.Envelope2D env_a = new com.epl.geometry.Envelope2D();
            com.epl.geometry.Envelope2D env_b = new com.epl.geometry.Envelope2D();
            multipathImplA.QueryLooseEnvelope2D(env_a);
            multipathImplB.QueryLooseEnvelope2D(env_b);
            env_a.Inflate(tolerance, tolerance);
            env_b.Inflate(tolerance, tolerance);
            com.epl.geometry.Envelope2D envInter = new com.epl.geometry.Envelope2D();
            envInter.SetCoords(env_a);
            envInter.Intersect(env_b);
            com.epl.geometry.Envelope2DIntersectorImpl intersector = new com.epl.geometry.Envelope2DIntersectorImpl();
            intersector.SetTolerance(tolerance);
            bool b_found_red = false;

            intersector.StartRedConstruction();
            for (int ipath_a = 0, npaths = multipathImplA.GetPathCount(); ipath_a < npaths; ipath_a++)
            {
                if (bExteriorOnlyA && type_a == com.epl.geometry.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);
            }
            bool b_found_blue = false;

            intersector.StartBlueConstruction();
            for (int ipath_b = 0, npaths = multipathImplB.GetPathCount(); ipath_b < npaths; ipath_b++)
            {
                if (bExteriorOnlyB && type_b == com.epl.geometry.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);
        }
        internal static com.epl.geometry.Envelope2DIntersectorImpl GetEnvelope2DIntersector(com.epl.geometry.MultiPathImpl multipathImplA, com.epl.geometry.MultiPathImpl multipathImplB, double tolerance)
        {
            com.epl.geometry.Envelope2D env_a = new com.epl.geometry.Envelope2D();
            com.epl.geometry.Envelope2D env_b = new com.epl.geometry.Envelope2D();
            multipathImplA.QueryLooseEnvelope2D(env_a);
            multipathImplB.QueryLooseEnvelope2D(env_b);
            env_a.Inflate(tolerance, tolerance);
            env_b.Inflate(tolerance, tolerance);
            com.epl.geometry.Envelope2D envInter = new com.epl.geometry.Envelope2D();
            envInter.SetCoords(env_a);
            envInter.Intersect(env_b);
            com.epl.geometry.SegmentIteratorImpl       segIterA    = multipathImplA.QuerySegmentIterator();
            com.epl.geometry.SegmentIteratorImpl       segIterB    = multipathImplB.QuerySegmentIterator();
            com.epl.geometry.Envelope2DIntersectorImpl intersector = new com.epl.geometry.Envelope2DIntersectorImpl();
            intersector.SetTolerance(tolerance);
            bool b_found_red = false;

            intersector.StartRedConstruction();
            while (segIterA.NextPath())
            {
                while (segIterA.HasNextSegment())
                {
                    com.epl.geometry.Segment segmentA = segIterA.NextSegment();
                    segmentA.QueryEnvelope2D(env_a);
                    if (!env_a.IsIntersecting(envInter))
                    {
                        continue;
                    }
                    b_found_red = true;
                    com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D();
                    env.SetCoords(env_a);
                    intersector.AddRedEnvelope(segIterA.GetStartPointIndex(), env);
                }
            }
            intersector.EndRedConstruction();
            if (!b_found_red)
            {
                return(null);
            }
            bool b_found_blue = false;

            intersector.StartBlueConstruction();
            while (segIterB.NextPath())
            {
                while (segIterB.HasNextSegment())
                {
                    com.epl.geometry.Segment segmentB = segIterB.NextSegment();
                    segmentB.QueryEnvelope2D(env_b);
                    if (!env_b.IsIntersecting(envInter))
                    {
                        continue;
                    }
                    b_found_blue = true;
                    com.epl.geometry.Envelope2D env = new com.epl.geometry.Envelope2D();
                    env.SetCoords(env_b);
                    intersector.AddBlueEnvelope(segIterB.GetStartPointIndex(), env);
                }
            }
            intersector.EndBlueConstruction();
            if (!b_found_blue)
            {
                return(null);
            }
            return(intersector);
        }
        public override com.epl.geometry.RasterizedGeometry2D.HitType QueryEnvelopeInGeometry(com.epl.geometry.Envelope2D env)
        {
            if (!env.Intersect(m_geomEnv))
            {
                return(com.epl.geometry.RasterizedGeometry2D.HitType.Outside);
            }
            int ixmin = WorldToPixX(env.xmin);
            int ixmax = WorldToPixX(env.xmax);
            int iymin = WorldToPixY(env.ymin);
            int iymax = WorldToPixY(env.ymax);

            if (ixmin < 0)
            {
                ixmin = 0;
            }
            if (iymin < 0)
            {
                iymin = 0;
            }
            if (ixmax >= m_width)
            {
                ixmax = m_width - 1;
            }
            if (iymax >= m_width)
            {
                iymax = m_width - 1;
            }
            if (ixmin > ixmax || iymin > iymax)
            {
                return(com.epl.geometry.RasterizedGeometry2D.HitType.Outside);
            }
            int area         = System.Math.Max(ixmax - ixmin, 1) * System.Math.Max(iymax - iymin, 1);
            int iStart       = 0;
            int scanLineSize = m_scanLineSize;
            int width        = m_width;
            int res          = 0;

            while (true)
            {
                if (area < 32 || width < 16)
                {
                    for (int iy = iymin; iy <= iymax; iy++)
                    {
                        for (int ix = ixmin; ix <= ixmax; ix++)
                        {
                            int divix = ix >> 4;
                            int modix = (ix & 15) * 2;
                            res = (m_bitmap[iStart + scanLineSize * iy + divix] >> modix) & 3;
                            // read
                            // two
                            // bit
                            // color.
                            if (res > 1)
                            {
                                return(com.epl.geometry.RasterizedGeometry2D.HitType.Border);
                            }
                        }
                    }
                    if (res == 0)
                    {
                        return(com.epl.geometry.RasterizedGeometry2D.HitType.Outside);
                    }
                    else
                    {
                        if (res == 1)
                        {
                            return(com.epl.geometry.RasterizedGeometry2D.HitType.Inside);
                        }
                    }
                }
                iStart      += scanLineSize * width;
                width       /= 2;
                scanLineSize = (width * 2 + 31) / 32;
                ixmin       /= 2;
                iymin       /= 2;
                ixmax       /= 2;
                iymax       /= 2;
                area         = System.Math.Max(ixmax - ixmin, 1) * System.Math.Max(iymax - iymin, 1);
            }
        }
Example #8
0
		internal virtual com.epl.geometry.Geometry TryFastIntersectPolylinePolygon_(com.epl.geometry.Polyline polyline, com.epl.geometry.Polygon polygon)
		{
			com.epl.geometry.MultiPathImpl polylineImpl = (com.epl.geometry.MultiPathImpl)polyline._getImpl();
			com.epl.geometry.MultiPathImpl polygonImpl = (com.epl.geometry.MultiPathImpl)polygon._getImpl();
			double tolerance = com.epl.geometry.InternalUtils.CalculateToleranceFromGeometry(m_spatial_reference, polygon, false);
			com.epl.geometry.Envelope2D clipEnvelope = new com.epl.geometry.Envelope2D();
			{
				polygonImpl.QueryEnvelope2D(clipEnvelope);
				com.epl.geometry.Envelope2D env1 = new com.epl.geometry.Envelope2D();
				polylineImpl.QueryEnvelope2D(env1);
				env1.Inflate(2.0 * tolerance, 2.0 * tolerance);
				clipEnvelope.Intersect(env1);
				System.Diagnostics.Debug.Assert((!clipEnvelope.IsEmpty()));
			}
			clipEnvelope.Inflate(10 * tolerance, 10 * tolerance);
			if (true)
			{
				double tol = 0;
				com.epl.geometry.Geometry clippedPolyline = com.epl.geometry.Clipper.Clip(polyline, clipEnvelope, tol, 0.0);
				polyline = (com.epl.geometry.Polyline)clippedPolyline;
				polylineImpl = (com.epl.geometry.MultiPathImpl)polyline._getImpl();
			}
			com.epl.geometry.AttributeStreamOfInt32 clipResult = new com.epl.geometry.AttributeStreamOfInt32(0);
			int unresolvedSegments = -1;
			com.epl.geometry.GeometryAccelerators accel = polygonImpl._getAccelerators();
			if (accel != null)
			{
				com.epl.geometry.RasterizedGeometry2D rgeom = accel.GetRasterizedGeometry();
				if (rgeom != null)
				{
					unresolvedSegments = 0;
					clipResult.Reserve(polylineImpl.GetPointCount() + polylineImpl.GetPathCount());
					com.epl.geometry.Envelope2D seg_env = new com.epl.geometry.Envelope2D();
					com.epl.geometry.SegmentIteratorImpl iter = polylineImpl.QuerySegmentIterator();
					while (iter.NextPath())
					{
						while (iter.HasNextSegment())
						{
							com.epl.geometry.Segment seg = iter.NextSegment();
							seg.QueryEnvelope2D(seg_env);
							com.epl.geometry.RasterizedGeometry2D.HitType hit = rgeom.QueryEnvelopeInGeometry(seg_env);
							if (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Inside)
							{
								clipResult.Add(1);
							}
							else
							{
								if (hit == com.epl.geometry.RasterizedGeometry2D.HitType.Outside)
								{
									clipResult.Add(0);
								}
								else
								{
									clipResult.Add(-1);
									unresolvedSegments++;
								}
							}
						}
					}
				}
			}
			if (polygon.GetPointCount() > 5)
			{
				double tol = 0;
				com.epl.geometry.Geometry clippedPolygon = com.epl.geometry.Clipper.Clip(polygon, clipEnvelope, tol, 0.0);
				polygon = (com.epl.geometry.Polygon)clippedPolygon;
				polygonImpl = (com.epl.geometry.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 = System.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
			com.epl.geometry.QuadTreeImpl polygonQuadTree = null;
			com.epl.geometry.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 = com.epl.geometry.InternalUtils.BuildQuadTree(polygonImpl);
			}
			com.epl.geometry.Polyline result_polyline = (com.epl.geometry.Polyline)polyline.CreateInstance();
			com.epl.geometry.MultiPathImpl resultPolylineImpl = (com.epl.geometry.MultiPathImpl)result_polyline._getImpl();
			com.epl.geometry.QuadTreeImpl.QuadTreeIteratorImpl qIter = null;
			com.epl.geometry.SegmentIteratorImpl polylineIter = polylineImpl.QuerySegmentIterator();
			double[] @params = new double[9];
			com.epl.geometry.AttributeStreamOfDbl intersections = new com.epl.geometry.AttributeStreamOfDbl(0);
			com.epl.geometry.SegmentBuffer segmentBuffer = new com.epl.geometry.SegmentBuffer();
			int start_index = -1;
			int inCount = 0;
			int segIndex = 0;
			bool 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++;
					com.epl.geometry.Segment polylineSeg = polylineIter.NextSegment();
					if (clipStatus < 0)
					{
						System.Diagnostics.Debug.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();
								com.epl.geometry.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())
								{
									com.epl.geometry.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;
								}
								bool bWholeSegment = false;
								com.epl.geometry.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
													{
														System.Diagnostics.Debug.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)
							{
								System.Diagnostics.Debug.Assert((clipStatus >= 0));
								return null;
							}
							// something goes wrong, resort to
							// planesweep
							System.Diagnostics.Debug.Assert((AnalyseClipSegment_(polygon, polylineSeg.GetEndXY(), tolerance) == clipStatus));
							if (clipStatus == 1)
							{
								// the whole segment inside
								if (state < stateManySegments)
								{
									System.Diagnostics.Debug.Assert((inCount == 0));
									start_index = polylineIter.GetStartPointIndex() - polylineImpl.GetPathStart(polylinePathIndex);
									if (state == stateNewPath)
									{
										state = stateManySegmentsNewPath;
									}
									else
									{
										System.Diagnostics.Debug.Assert((state == stateAddSegment));
										state = stateManySegmentsContinuePath;
									}
								}
								inCount++;
							}
							else
							{
								System.Diagnostics.Debug.Assert((state < stateManySegments));
								start_index = -1;
								inCount = 0;
							}
						}
						intersections.Clear(false);
					}
					else
					{
						// clip status is determined by other means
						if (clipStatus == 0)
						{
							// outside
							System.Diagnostics.Debug.Assert((AnalyseClipSegment_(polygon, polylineSeg, tolerance) == 0));
							System.Diagnostics.Debug.Assert((start_index < 0));
							System.Diagnostics.Debug.Assert((inCount == 0));
							continue;
						}
						if (clipStatus == 1)
						{
							System.Diagnostics.Debug.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
								{
									System.Diagnostics.Debug.Assert((state >= stateManySegments));
								}
							}
							inCount++;
							continue;
						}
					}
				}
				if (state >= stateManySegments)
				{
					resultPolylineImpl.AddSegmentsFromPath(polylineImpl, polylinePathIndex, start_index, inCount, state == stateManySegmentsNewPath);
					start_index = -1;
				}
			}
			return result_polyline;
		}
Example #9
0
		internal virtual com.epl.geometry.Geometry TryNativeImplementation_(com.epl.geometry.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.
			com.epl.geometry.Envelope2D mergedExtent = com.epl.geometry.InternalUtils.GetMergedExtent(input_geom, m_geomIntersector);
			double tolerance = com.epl.geometry.InternalUtils.CalculateToleranceFromGeometry(m_spatial_reference, mergedExtent, false);
			int gtInput = input_geom.GetType().Value();
			bool bInputEmpty = input_geom.IsEmpty();
			bool bGeomIntersectorEmpty = m_geomIntersector.IsEmpty();
			bool bResultIsEmpty = bInputEmpty || bGeomIntersectorEmpty;
			if (!bResultIsEmpty)
			{
				// test envelopes
				com.epl.geometry.Envelope2D env2D1 = new com.epl.geometry.Envelope2D();
				input_geom.QueryEnvelope2D(env2D1);
				com.epl.geometry.Envelope2D env2D2 = new com.epl.geometry.Envelope2D();
				m_geomIntersector.QueryEnvelope2D(env2D2);
				env2D2.Inflate(2.0 * tolerance, 2.0 * tolerance);
				bResultIsEmpty = !env2D1.IsIntersecting(env2D2);
			}
			if (!bResultIsEmpty)
			{
				// try accelerated test
				int res = com.epl.geometry.OperatorInternalRelationUtils.QuickTest2D_Accelerated_DisjointOrContains(m_geomIntersector, input_geom, tolerance);
				if (res == com.epl.geometry.OperatorInternalRelationUtils.Relation.Disjoint)
				{
					// disjoint
					bResultIsEmpty = true;
				}
				else
				{
					if ((res & com.epl.geometry.OperatorInternalRelationUtils.Relation.Within) != 0)
					{
						// intersector
						// is
						// within
						// the
						// input_geom
						// TODO:
						// assign
						// input_geom
						// attributes
						// first
						return m_geomIntersector;
					}
					else
					{
						if ((res & com.epl.geometry.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 = com.epl.geometry.Geometry.GetDimensionFromType(gtInput);
				int dim2 = com.epl.geometry.Geometry.GetDimensionFromType(m_geomIntersectorType);
				if (dim1 < dim2)
				{
					return ReturnEmpty_(input_geom, bInputEmpty);
				}
				else
				{
					if (dim1 > dim2)
					{
						return ReturnEmptyIntersector_();
					}
					else
					{
						if (dim1 == 0)
						{
							if (gtInput == com.epl.geometry.Geometry.GeometryType.MultiPoint && m_geomIntersectorType == com.epl.geometry.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 == com.epl.geometry.Geometry.GeometryType.Envelope && m_geomIntersectorType == com.epl.geometry.Geometry.GeometryType.Envelope)
			{
				com.epl.geometry.Envelope env1 = (com.epl.geometry.Envelope)input_geom;
				com.epl.geometry.Envelope env2 = (com.epl.geometry.Envelope)m_geomIntersector;
				com.epl.geometry.Envelope2D env2D_1 = new com.epl.geometry.Envelope2D();
				env1.QueryEnvelope2D(env2D_1);
				com.epl.geometry.Envelope2D env2D_2 = new com.epl.geometry.Envelope2D();
				env2.QueryEnvelope2D(env2D_2);
				env2D_1.Intersect(env2D_2);
				com.epl.geometry.Envelope result_env = new com.epl.geometry.Envelope();
				env1.CopyTo(result_env);
				result_env.SetEnvelope2D(env2D_1);
				return result_env;
			}
			// Use clip for Point and Multi_point with Envelope
			if ((gtInput == com.epl.geometry.Geometry.GeometryType.Envelope && com.epl.geometry.Geometry.GetDimensionFromType(m_geomIntersectorType) == 0) || (m_geomIntersectorType == com.epl.geometry.Geometry.GeometryType.Envelope && com.epl.geometry.Geometry.GetDimensionFromType(gtInput
				) == 0))
			{
				com.epl.geometry.Envelope env = gtInput == com.epl.geometry.Geometry.GeometryType.Envelope ? (com.epl.geometry.Envelope)input_geom : (com.epl.geometry.Envelope)m_geomIntersector;
				com.epl.geometry.Geometry other = gtInput == com.epl.geometry.Geometry.GeometryType.Envelope ? m_geomIntersector : input_geom;
				com.epl.geometry.Envelope2D env_2D = new com.epl.geometry.Envelope2D();
				env.QueryEnvelope2D(env_2D);
				return com.epl.geometry.Clipper.Clip(other, env_2D, tolerance, 0);
			}
			if ((com.epl.geometry.Geometry.GetDimensionFromType(gtInput) == 0 && com.epl.geometry.Geometry.GetDimensionFromType(m_geomIntersectorType) > 0) || (com.epl.geometry.Geometry.GetDimensionFromType(gtInput) > 0 && com.epl.geometry.Geometry.GetDimensionFromType(m_geomIntersectorType
				) == 0))
			{
				// multipoint
				// intersection
				double tolerance1 = com.epl.geometry.InternalUtils.CalculateToleranceFromGeometry(m_spatial_reference, input_geom, false);
				if (gtInput == com.epl.geometry.Geometry.GeometryType.MultiPoint)
				{
					return com.epl.geometry.TopologicalOperations.Intersection((com.epl.geometry.MultiPoint)input_geom, m_geomIntersector, tolerance1);
				}
				if (gtInput == com.epl.geometry.Geometry.GeometryType.Point)
				{
					return com.epl.geometry.TopologicalOperations.Intersection((com.epl.geometry.Point)input_geom, m_geomIntersector, tolerance1);
				}
				if (m_geomIntersectorType == com.epl.geometry.Geometry.GeometryType.MultiPoint)
				{
					return com.epl.geometry.TopologicalOperations.Intersection((com.epl.geometry.MultiPoint)m_geomIntersector, input_geom, tolerance1);
				}
				if (m_geomIntersectorType == com.epl.geometry.Geometry.GeometryType.Point)
				{
					return com.epl.geometry.TopologicalOperations.Intersection((com.epl.geometry.Point)m_geomIntersector, input_geom, tolerance1);
				}
				throw com.epl.geometry.GeometryException.GeometryInternalError();
			}
			// Try Polyline vs Polygon
			if ((m_dimensionMask == -1 || m_dimensionMask == (1 << 1)) && (gtInput == com.epl.geometry.Geometry.GeometryType.Polyline) && (m_geomIntersectorType == com.epl.geometry.Geometry.GeometryType.Polygon))
			{
				return TryFastIntersectPolylinePolygon_((com.epl.geometry.Polyline)(input_geom), (com.epl.geometry.Polygon)(m_geomIntersector));
			}
			// Try Polygon vs Polyline
			if ((m_dimensionMask == -1 || m_dimensionMask == (1 << 1)) && (gtInput == com.epl.geometry.Geometry.GeometryType.Polygon) && (m_geomIntersectorType == com.epl.geometry.Geometry.GeometryType.Polyline))
			{
				return TryFastIntersectPolylinePolygon_((com.epl.geometry.Polyline)(m_geomIntersector), (com.epl.geometry.Polygon)(input_geom));
			}
			return null;
		}
Example #10
0
 public static void Test_perf_quad_tree()
 {
     com.epl.geometry.Envelope extent1 = new com.epl.geometry.Envelope();
     extent1.SetCoords(-1000, -1000, 1000, 1000);
     com.epl.geometry.RandomCoordinateGenerator generator1 = new com.epl.geometry.RandomCoordinateGenerator(1000, extent1, 0.001);
     //HiResTimer timer;
     for (int N = 16; N <= 1024; N *= 2)
     {
         //timer.StartMeasurement();
         com.epl.geometry.Envelope2D extent = new com.epl.geometry.Envelope2D();
         extent.SetCoords(-1000, -1000, 1000, 1000);
         System.Collections.Generic.Dictionary <int, com.epl.geometry.Envelope2D> data = new System.Collections.Generic.Dictionary <int, com.epl.geometry.Envelope2D>(0);
         com.epl.geometry.QuadTree qt = new com.epl.geometry.QuadTree(extent, 10);
         for (int i = 0; i < N; i++)
         {
             com.epl.geometry.Envelope2D env    = new com.epl.geometry.Envelope2D();
             com.epl.geometry.Point2D    center = generator1.GetRandomCoord().GetXY();
             double w = 10;
             env.SetCoords(center, w, w);
             env.Intersect(extent);
             if (env.IsEmpty())
             {
                 continue;
             }
             int h = qt.Insert(i, env);
             data[h] = env;
         }
         int ecount = 0;
         com.epl.geometry.AttributeStreamOfInt32    handles = new com.epl.geometry.AttributeStreamOfInt32(0);
         com.epl.geometry.QuadTree.QuadTreeIterator iter    = qt.GetIterator();
         System.Collections.Generic.IEnumerator <System.Collections.Generic.KeyValuePair <int, com.epl.geometry.Envelope2D> > pairs = data.GetEnumerator();
         while (pairs.MoveNext())
         {
             System.Collections.Generic.KeyValuePair <int, com.epl.geometry.Envelope2D> entry = pairs.Current;
             iter.ResetIterator((com.epl.geometry.Envelope2D)entry.Value, 0.001);
             bool remove_self = false;
             for (int h = iter.Next(); h != -1; h = iter.Next())
             {
                 if (h != entry.Key)
                 {
                     handles.Add(h);
                 }
                 else
                 {
                     remove_self = true;
                 }
                 ecount++;
             }
             for (int i_1 = 0; i_1 < handles.Size(); i_1++)
             {
                 qt.RemoveElement(handles.Get(i_1));
             }
             //remove elements that were selected.
             if (remove_self)
             {
                 qt.RemoveElement(entry.Key);
             }
             handles.Resize(0);
         }
     }
 }