예제 #1
0
 public override void QueryEnvelope(com.epl.geometry.Envelope env)
 {
     env.SetEmpty();
     env.AssignVertexDescription(m_description);
     com.epl.geometry.Envelope2D env2D = new com.epl.geometry.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 = com.epl.geometry.VertexDescription.GetComponentCount(semantics); i < nord; i++)
         {
             com.epl.geometry.Envelope1D interval = QueryInterval(semantics, iord);
             env.SetInterval(semantics, iord, interval);
         }
     }
 }
예제 #2
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;
		}