Ejemplo n.º 1
0
 /// <summary>Adds a new segment to this multipath.</summary>
 /// <param name="segment">The segment to be added to this mulitpath.</param>
 /// <param name="bStartNewPath">TRUE if a new path will be added.</param>
 public virtual void AddSegment(com.epl.geometry.Segment segment, bool bStartNewPath)
 {
     m_impl.AddSegment(segment, bStartNewPath);
 }
Ejemplo n.º 2
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;
		}