/// <summary>
        /// Constructor used to combine a series of <c>IntersectResult</c> objects. This
        /// implementation is used to obtain a results object for a new topological line
        /// that has just been intersected against the map.
        /// </summary>
        /// <param name="xsect">The result of intersecting a line with the map</param>
        internal IntersectionResult(IntersectionFinder xsect)
        {
            m_IntersectedObject = xsect.Intersector;
            m_Geom = m_IntersectedObject.LineGeometry;
            m_Data = null;

            // Get the total number of intersections that were found (there's one
            // InteresectionResult for each intersected line)
            IList<IntersectionResult> results = xsect.Intersections;
            int nData = 0;
            foreach (IntersectionResult r in results)
                nData += r.m_Data.Count;

            // Return if no intersections.
            if (nData==0)
                return;

            // Copy over the info
            m_Data = new List<IntersectionData>(nData);
            foreach (IntersectionResult r in results)
            {
                List<IntersectionData> data = r.Intersections;
                foreach (IntersectionData d in data)
                    m_Data.Add(d);
            }

            // Reverse all context codes.
            foreach (IntersectionData d in m_Data)
                d.ReverseContext();
        }
        /// <summary>
        /// Creates a new <c>DividerObject</c> that wraps the supplied divider.
        /// </summary>
        /// <param name="d">The divider to wrap</param>
        internal DividerObject(IDivider d)
        {
            if (d==null)
                throw new ArgumentNullException();

            m_Divider = d;
            m_Geom = m_Divider.LineGeometry;
        }
        /// <summary>
        /// Creates a new <c>FindPointsOnLineQuery</c> (and executes it). The result of the query
        /// can then be obtained through the <c>Result</c> property.
        /// </summary>
        /// <param name="index">The spatial index to search</param>
        /// <param name="line">The line of interest.</param>
        /// <param name="wantEnds">Specify true if you want points coincident with the line ends.</param>
        /// <param name="tol">The search tolerance (expected to be greater than zero).</param>
        internal FindPointsOnLineQuery(ISpatialIndex index, LineGeometry line, bool wantEnds, ILength tol)
        {
            m_Line = line;
            m_Tolerance = tol.Meters;
            m_Result = new List<PointFeature>();

            IWindow w = m_Line.Extent;
            index.QueryWindow(w, SpatialType.Point, OnQueryHit);
        }
        /// <summary>
        /// Obtains line geometry that isn't an instance of <see cref="SectionGeometry"/>
        /// </summary>
        /// <param name="geom">The geometry that could be a section</param>
        /// <returns>Concrete (unsectioned) geometry that corresponds to <paramref name="geom"/></returns>
        private UnsectionedLineGeometry GetUnsectionedLineGeometry(LineGeometry geom)
        {
            if (geom is UnsectionedLineGeometry)
                return (geom as UnsectionedLineGeometry);

            if (geom is SectionGeometry)
                return (geom as SectionGeometry).Make();

            throw new NotImplementedException("Unexpected line geometry: "+geom.GetType().Name);
        }
        /// <summary>
        /// Creates a new <c>FindIntersectionsQuery</c> (and executes it). The result of the query
        /// can then be obtained through the <c>Result</c> property.
        /// <para/>
        /// Use this constructor when intersecting with geometry that has been created ad-hoc.
        /// Note that if you are looking to intersect a line feature (already part of
        /// the spatial index), you should use the constructor that accepts the <c>LineFeature</c>.
        /// </summary>
        /// <param name="index">The spatial index to search</param>
        /// <param name="geom">The geometry to intersect.</param>
        /// <param name="wantEndEnd">Specify true if you want end-to-end intersections in the results.</param>
        internal FindIntersectionsQuery(ISpatialIndex index, LineGeometry geom, bool wantEndEnd)
        {
            m_Feature = null;
            m_Geom = GetUnsectionedLineGeometry(geom);
            m_WantEndEnd = wantEndEnd;
            m_Result = new List<IntersectionResult>(100);

            FindIntersections(index);
        }
 /// <summary>
 /// Creates a new <c>IntersectionFinder</c> for the specified geometry.
 /// Use this constructor when intersecting geometry that has been created ad-hoc.
 /// </summary>
 /// <param name="geom">The geometry to intersect.</param>
 /// <param name="wantEndEnd">Specify true if you want end-to-end intersections in the results.</param>
 internal IntersectionFinder(LineGeometry geom, bool wantEndEnd)
 {
     m_Line = geom;
     ISpatialIndex index = CadastralMapModel.Current.Index;
     m_Intersects = new FindIntersectionsQuery(index, geom, wantEndEnd).Result;
 }
 /// <summary>
 /// Creates a new <c>IntersectionResult</c> for the specified line. This
 /// implementation is used when intersecting ad-hoc geometry, as well as
 /// representing the results of intersecting a line feature with previously
 /// existing topology.
 /// </summary>
 /// <param name="intersectedObject"></param>
 internal IntersectionResult(IIntersectable intersectedObject)
 {
     m_IntersectedObject = intersectedObject;
     m_Geom = intersectedObject.LineGeometry;
     m_Data = new List<IntersectionData>();
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="LineFeature"/> class, and records it
        /// as part of the map model.
        /// </summary>
        /// <param name="iid">The internal ID for the feature.</param>
        /// <param name="fid">The (optional) user-perceived ID for the feature. If not null,
        /// this will be modified by cross-referencing it to the newly created feature.</param>
        /// <param name="ent">The entity type for the feature (not null)</param>
        /// <param name="creator">The operation creating the feature (not null). Expected to
        /// refer to an editing session that is consistent with the session ID that is part
        /// of the feature's internal ID.</param>
        /// <param name="start">The point at the start of the line (not null)</param>
        /// <param name="end">The point at the end of the line (not null)</param>
        /// <param name="g">The geometry for the line (could be null, although this is only really
        /// expected during deserialization)</param>
        /// <param name="isTopological">Does the line form part of a polygon boundary?</param>
        /// <exception cref="ArgumentNullException">If either <paramref name="ent"/> or
        /// <paramref name="creator"/> or <paramref name="start"/> or <paramref name="end"/> is null.
        /// </exception>
        protected LineFeature(IFeature f, PointFeature start, PointFeature end, LineGeometry g, bool isTopological)
            : base(f)
        {
            if (start == null || end == null)
                throw new ArgumentNullException();

            m_From = start;
            m_To = end;
            m_Geom = g;
            m_Topology = null;

            // Don't cross-reference if we're dealing with a temporary feature
            if (!f.InternalId.IsEmpty)
                AddReferences();

            if (isTopological)
                SetTopology(true);
        }
        /// <summary>
        /// Creates a new <c>LineFeature</c>
        /// </summary>
        /// <param name="creator">The operation that created the feature (not null)</param>
        /// <param name="id">The internal ID of this feature within the
        /// project that created it.</param>
        /// <param name="e">The entity type for the feature (not null)</param>
        /// <param name="g">The geometry defining the shape of the line (not null)</param>
        /// <note>To ensure that the start and end of all lines are instances of <see cref="PointFeature"/>,
        /// this constructor should always remain private.</note>
        protected LineFeature(Operation creator, InternalIdValue id, IEntity e, PointFeature start, PointFeature end, LineGeometry g)
            : base(creator, id, e, null)
        {
            if (g==null)
                throw new ArgumentNullException();

            m_From = start;
            m_To = end;
            m_Geom = g;
            m_Topology = null;
            AddReferences();

            // If the entity type denotes a topological boundary, initialize the topology.
            if (e.IsPolygonBoundaryValid)
                SetTopology(true);
        }
        /// <summary>
        /// Reads data that was previously written using <see cref="WriteData"/>
        /// </summary>
        /// <param name="editDeserializer">The mechanism for reading back content.</param>
        /// <param name="from">The point at the start of the line</param>
        /// <param name="to">The point at the end of the line</param>
        /// <param name="isTopological">Does the line act as a polygon boundary </param>
        /// <param name="geom">The geometry for the line.</param>
        static void ReadData(EditDeserializer editDeserializer, out PointFeature from, out PointFeature to, out bool isTopological,
            out LineGeometry geom)
        {
            from = editDeserializer.ReadFeatureRef<PointFeature>(DataField.From);
            to = editDeserializer.ReadFeatureRef<PointFeature>(DataField.To);
            isTopological = editDeserializer.ReadBool(DataField.Topological);

            if (editDeserializer.IsNextField(DataField.Type))
            {
                geom = editDeserializer.ReadPersistent<LineGeometry>(DataField.Type);

                // Ensure terminals have been defined (since there was no easy way to pass them
                // through to the LineGeometry constructor).
                geom.StartTerminal = from;
                geom.EndTerminal = to;

                // If we're dealing with a circular arc, and the bc/ec points have defined
                // positions (e.g. coming from an import), we can calculate the radius now.
                // Otherwise we'll need to wait until geometry has been calculated.

                // The radius is defined here only because it's consistent with older code.
                // It may well be better to leave the definition of circle radius till later
                // (i.e. do all circles after geometry has been calculated).

                ArcGeometry arc = (geom as ArcGeometry);
                if (arc != null)
                {
                    Circle c = (Circle)arc.Circle;
                    PointFeature center = c.CenterPoint;

                    if (center.PointGeometry != null && from.PointGeometry != null)
                        c.Radius = Geom.Distance(center.PointGeometry, from.PointGeometry);
                }

            }
            else
            {
                geom = new SegmentGeometry(from, to);
            }
        }
 // Should try to get rid of this...
 protected void ChangeGeometry(ArcGeometry arc)
 {
     m_Geom = arc;
 }
        /// <summary>
        /// Checks whether this closed shape overlaps a line
        /// </summary>
        /// <param name="shape">Positions defining a closed outline (the last position
        /// must coincide with the first position). At least 3 positions.</param>
        /// <param name="shapeWindow">The extent of <paramref name="shape"/></param>
        /// <param name="line">The line to compare with the shape</param>
        /// <returns>True if the shape overlaps the line</returns>
        internal bool IsOverlap(LineGeometry line)
        {
            // Get the window of the line
            IWindow lwin = line.Extent;

            // The two windows have to overlap.
            if (!m_Extent.IsOverlap(lwin))
                return false;

            // If either end of the line falls inside this shape, we've got overlap.
            IPointGeometry p = line.Start;
            if (m_Extent.IsOverlap(p) && Geom.IsPointInClosedShape(this.Data, p))
                return true;

            p = line.End;
            if (m_Extent.IsOverlap(p) && Geom.IsPointInClosedShape(this.Data, p))
                return true;

            // The only thing left is a possible interesection between
            // the shape and the line.
            return IsIntersect(line);
        }
        /// <summary>
        /// Checks whether this closed shape intersects (overlaps) a line.
        /// This assumes that a window-window overlap has already been checked for.
        /// </summary>
        /// <param name="line">The line to compare with the shape</param>
        /// <returns>True if intersection found.</returns>
        bool IsIntersect(LineGeometry line)
        {
            //IntersectionResult xres = new IntersectionResult(line);
            //return (xres.IntersectMultiSegment(this) > 0);

            IntersectionResult xres = new IntersectionResult(line);

            // Intersect each segment of this shape with the line.
            IPointGeometry[] data = this.Data;
            for (int i=1; i<data.Length; i++)
            {
                LineSegmentGeometry thisSeg = new LineSegmentGeometry(data[i-1], data[i]);
                if (xres.IntersectSegment(thisSeg) > 0)
                    return true;
            }

            return false;
        }
Exemple #14
0
 void WriteLineGeometry(LineGeometry geom)
 {
     if (geom is SegmentGeometry)
         WriteSegment((SegmentGeometry)geom);
     else if (geom is ArcGeometry)
         WriteArc((ArcGeometry)geom);
     else if (geom is MultiSegmentGeometry)
         WriteMultiSegment((MultiSegmentGeometry)geom);
     else if (geom is SectionGeometry)
         WriteSection((SectionGeometry)geom);
     else
         throw new NotImplementedException("Unexpected line geometry type: " + geom.GetType().Name);
 }