/// <summary>
        /// Creates a new <c>SectionGeometry</c>
        /// </summary>
        /// <param name="baseLine">The line the section is based on (not null).</param>
        /// <param name="start">The point at the start of the section (coincident with
        /// the specified line)</param>
        /// <param name="end">The point at the end of the section (coincident with
        /// the specified line)</param>
        /// <exception cref="ArgumentNullException">If a null line was specified</exception>
        internal SectionGeometry(LineFeature baseLine, PointFeature start, PointFeature end)
            : base(start, end)
        {
            if (baseLine==null)
                throw new ArgumentNullException();

            m_Base = baseLine;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="SectionGeometry"/> class
        /// using the data read from persistent storage.
        /// </summary>
        /// <param name="editDeserializer">The mechanism for reading back content.</param>
        internal SectionGeometry(EditDeserializer editDeserializer)
            : base(editDeserializer)
        {
            m_Base = editDeserializer.ReadFeatureRef<LineFeature>(DataField.Base);

            if (m_Base == null)
                throw new ArgumentNullException();
        }
        /// <summary>
        /// Records information for a line split
        /// </summary>
        /// <param name="parentLine">The line that may be getting split</param>
        /// <param name="field">The tag of the item that should be attached to the line split info</param>
        /// <param name="dataId">The ID for the section (null if there is no split)</param>
        /// <returns>True if a line split was recorded, false if the <paramref name="splitSection"/> is null.</returns>
        internal bool AddLineSplit(LineFeature parentLine, DataField field, string dataId)
        {
            if (dataId == null)
                return false;

            InternalIdValue id = new InternalIdValue(dataId);
            AddFeatureDescription(field, new FeatureStub(Creator, id, parentLine.EntityType, null));
            return true;
        }
        /// <summary>
        /// Creates a new <c>SectionTopologyList</c> that relates to the specified line,
        /// and with the specified list of sections.
        /// </summary>
        /// <param name="line">The line that any topological sections relate to.</param>
        /// <param name="sections">The topological sections (must all refer to <paramref name="line"/>)</param>
        /// <exception cref="ArgumentException">If any of the specified sections do not
        /// relate to <paramref name="line"/>
        /// </exception>
        internal SectionTopologyList(LineFeature line, List<IDivider> sections)
            : base(line)
        {
            foreach (IDivider d in sections)
            {
                if (d.Line != line)
                    throw new ArgumentException("Topological section refers to inconsistent line");
            }

            m_Sections = sections;
        }
        /// <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 something that has already been added to
        /// the spatial index. This ensures that the line is not intersected with itself.
        /// </summary>
        /// <param name="index">The spatial index to search</param>
        /// <param name="line">The line feature to intersect.</param>
        /// <param name="wantEndEnd">Specify true if you want end-to-end intersections in the results.</param>
        internal FindIntersectionsQuery(ISpatialIndex index, LineFeature line, bool wantEndEnd)
        {
            if (index == null)
                throw new ArgumentNullException("FindIntersectionsQuery");

            m_Feature = line;
            m_Geom = GetUnsectionedLineGeometry(line.LineGeometry);
            m_WantEndEnd = wantEndEnd;
            m_Result = new List<IntersectionResult>(100);

            FindIntersections(index);
        }
        /// <summary>
        /// Creates a new <c>SectionDivider</c> that relates to the specified section of line,
        /// with undefined polygon rings on left and right.
        /// </summary>
        /// <param name="line">The line this topological section partially coincides with.</param>
        /// <param name="from">The start position for the topological section.</param>
        /// <param name="to">The end position for the topological section.</param>
        internal SectionDivider(LineFeature line, ITerminal from, ITerminal to)
            : base(line, from, to)
        {
            m_Left = m_Right = null;

            if (from is Intersection)
                (from as Intersection).Add(line);
            else if (from is PointFeature)
                (from as PointFeature).AddReference(line);

            if (to is Intersection)
                (to as Intersection).Add(line);
            else if (to is PointFeature)
                (to as PointFeature).AddReference(line);
        }
 /// <summary>
 /// Creates a new <c>SectionTopologyList</c> that relates to the specified line,
 /// but with an empty list of sections.
 /// </summary>
 /// <param name="line">The line that any topological sections must relate to.</param>
 internal SectionTopologyList(LineFeature line)
     : base(line)
 {
     m_Sections = new List<IDivider>();
 }
 /// <summary>
 /// Reacts to the selection of a line feature.
 /// </summary>
 /// <param name="line">The line (if any) that has been selected.</param>
 internal override void OnSelectLine(LineFeature line)
 {
 }
 /// <summary>
 /// Creates a new <c>LineTopology</c> that relates to a complete line.
 /// Base class for <see cref="LineDivider"/> and <see cref="LineOverlap"/>.
 /// </summary>
 /// <param name="line">The line the topology relates to.</param>
 /// <seealso cref="SectionTopology"/>
 protected LineTopology(LineFeature line)
     : base(line)
 {
 }
 /// <summary>
 /// Creates a new <c>SectionOverlap</c> that relates to a section of the specified line.
 /// </summary>
 /// <param name="line">The line the overlap topology is for (this is <b>not</b>
 /// the line that is overlapped by this section)</param>
 /// <param name="from">The start position for the section.</param>
 /// <param name="to">The end position for the section.</param>
 internal SectionOverlap(LineFeature line, ITerminal from, ITerminal to)
     : base(line, from, to)
 {
 }
Beispiel #11
0
 /// <summary>
 /// Creates a new <c>LineOverlap</c> that relates to the specified line.
 /// </summary>
 /// <param name="line">The line the overlap topology is for (<b>not</b>
 /// the line that is overlapped)</param>
 internal LineOverlap(LineFeature line)
     : base(line)
 {
 }
 /// <summary>
 /// Creates a new <c>IntersectionFinder</c> for the specified line feature.
 /// Use this constructor when intersecting something that has already been added to
 /// the map model. This ensures that the line is not intersected with itself.
 /// </summary>
 /// <param name="line">The line feature to intersect.</param>
 /// <param name="wantEndEnd">Specify true if you want end-to-end intersections in the results.</param>
 internal IntersectionFinder(LineFeature line, bool wantEndEnd)
 {
     m_Line = line;
     ISpatialIndex index = CadastralMapModel.Current.Index;
     m_Intersects = new FindIntersectionsQuery(index, line, wantEndEnd).Result;
 }
Beispiel #13
0
 /// <summary>
 /// Creates a new <c>Divider</c> that relates to the specified line.
 /// </summary>
 /// <param name="line">The line the topology relates to.</param>
 internal LineDivider(LineFeature line)
     : base(line)
 {
     m_Left = m_Right = null;
 }
Beispiel #14
0
        private Feature ImportLine(ILength tol, Ntx.Line line, Operation creator)
        {
            // Circular arcs are handled elsewhere
            if (line.IsCurve)
                return null;

            IEntity what = GetEntityType(line, SpatialType.Line);

            PointGeometry[] pts = GetPositions(line);

            // Ignore zero-length lines
            if (HasZeroLength(pts))
                return null;

            // Ensure point features exist at both ends of the line.
            PointFeature ps = EnsurePointExists(pts[0], tol, creator);
            PointFeature pe = EnsurePointExists(pts[pts.Length-1], tol, creator);

            // Force end positions to match
            pts[0] = ps.PointGeometry;
            pts[pts.Length-1] = pe.PointGeometry;

            // It's possible we've now produced a zero-length line
            if (Object.ReferenceEquals(ps, pe) && HasZeroLength(pts))
                return null;

            // If we're dealing with a multi-segment, I have occasionally seen tiny glitches
            // at the end of the incoming lines (whether this is a real data problem, or an
            // imperfection in the import software is unknown). So double check now.

            // In the longer term, the import software should also check for more complex
            // issues, like missing intersections. In the meantime, I assume that incoming
            // topological data is generally clean.

            if (pts.Length > 2 && line.IsTopologicalArc)
                pts = CheckMultiSegmentEnds(pts);

            LineFeature result;
            InternalIdValue id = CadastralMapModel.Current.WorkingSession.AllocateNextId();

            if (pts.Length==2)
                result = new LineFeature(creator, id, what, ps, pe);
            else
                result = new LineFeature(creator, id, what, ps, pe, pts);

            // The toological status of the incoming arc may override the status that the
            // constructor derived from the entity type
            result.SetTopology(line.IsTopologicalArc);

            return result;
        }
 /// <summary>
 /// Creates a new <c>SectionTopology</c>
 /// </summary>
 /// <param name="line">The line this topological section partially coincides with.</param>
 /// <param name="from">The start position for the topological section.</param>
 /// <param name="to">The end position for the topological section.</param>
 protected SectionTopology(LineFeature line, ITerminal from, ITerminal to)
 {
     m_Line = line;
     m_From = from;
     m_To = to;
 }
Beispiel #16
0
 /// <summary>
 /// Reacts to the selection of a line feature.
 /// </summary>
 /// <param name="line">The line (if any) that has been selected.</param>
 internal abstract void OnSelectLine(LineFeature line);
Beispiel #17
0
        /// <summary>
        /// Mark this line as inactive.
        /// </summary>
        /// <param name="op">The operation that is doing this</param>
        /*
        internal void SetInactive(Operation op)
        {
            throw new NotImplementedException();
        }
        */
        /*
        //	@mfunc	Mark this arc as inactive. When you do this, any
        //			system-defined split sections will be eliminated.
        //
        //	@parm	The operation that is doing this. This operation will
        //			hold any sub-features that get created as a result of
        //			de-activating this arc. Only SetDeleted is expected to
        //			pass in a null value.
        //	@parm	Is the arc being de-activated in order to trim a
        //			dangling system-generated arc section? If so, DON'T
        //			undo any splits that are incident on this arc. A
        //			TRUE value should be specified ONLY by <mf CeSplit::
        //			Trim>. Default=FALSE.
        //
        //	@rdesc	Any sub-feature that was created to represent the
        //			layers that this feature was NOT de-activated on.

        CeFeature* CeArc::SetInactive ( CeOperation* pop
                              , const LOGICAL isTrim ) {

        // Return if this arc is already inactive (or marked for deletion).
        if ( this->IsInactive() ) return 0;

        // De-activate the base class.
        CeFeature* pSub = CeFeature::SetInactive(pop);

        // Ensure polygons on the left and right have been marked
        // for deletion.
        SetPolDeleted();

        // Get any split operation listing arc sections (only returns
        // something if FFL_SYSTOPOL is set).

        CeSplit* pSplit = GetpSplit();

        if ( pSplit ) {

        // Return if the splits have been revealed.
        if ( pSplit->IsRevealed() ) return pSub;

        // Mark all splits for deletion.
        RemoveSplits();

        // If we created a sub-arc to represent layers that are
        // not being de-activated, mark it as moved, to force
        // re-intersection.
        if ( pSub ) pSub->SetMoved();
        }

        // Check for overlaps with the line's end locations.
        if ( !isTrim ) m_pLine->UndoEndOverlaps(*this);

        return pSub;

        } // end of SetInactive
         */
        /// <summary>
        /// Make a new line that corresponds to a sub-section of this line.
        /// </summary>
        /// <param name="creator">The operation that should be noted as the creator of the new line.</param>
        /// <param name="id">The internal ID to assign to the sub-section.</param>
        /// <param name="section">The geometry for the new line.</param>
        /// <returns>The new line</returns>
        internal LineFeature MakeSubSection(Operation creator, InternalIdValue id, SectionGeometry section)
        {
            LineFeature result = new LineFeature(creator, id, section);

            //PointFeature start = (PointFeature)section.Start;
            //PointFeature end = (PointFeature)section.End;

            //LineFeature result = new LineFeature(this.EntityType, op, start, end, section);
            DefineFeature(result);

            // The resultant sub-section should always have the same topological status
            //if (result.IsTopological)
            //    result.m_Topology = Topology.CreateTopology(result);
            result.SetTopology(this.IsTopological);

            return result;
        }
Beispiel #18
0
        /// <summary>
        /// Intersect this line with another line.
        /// </summary>
        /// <param name="line">The line to intersect with (not equal to THIS line)</param>
        /// <param name="closeTo">The point that the intersection should be closest to.
        /// Specify null if you don't care. In that case, if there are multiple intersections,
        /// you get the intersection that is closest to one of 3 points: the start of the
        /// direction line, the start of the line, or the end of the line.</param>
        /// <param name="xsect">The position of the intersection (if any). Null if not found.</param>
        /// <param name="closest">The default point that is closest to the intersection. Null if
        /// intersection wasn't found.</param>
        /// <returns>True if intersection was found.</returns>
        internal bool Intersect( LineFeature line
            , PointFeature closeTo
            , out IPosition xsect
            , out PointFeature closest)
        {
            // Initialize results
            xsect = null;
            closest = null;

            // Don't intersect a line with itself.
            if (Object.ReferenceEquals(this, line))
                throw new Exception("Cannot intersect a line with itself.");

            // Intersect this line with the other one.
            IntersectionResult xres = new IntersectionResult(this);
            uint nx = line.LineGeometry.Intersect(xres);
            if (nx==0)
                return false;

            // Determine which terminal point is the best.
            double mindsq = Double.MaxValue;

            if (xres.GetCloserPoint(this.StartPoint, ref mindsq, ref xsect))
                closest = this.StartPoint;

            if (xres.GetCloserPoint(this.EndPoint, ref mindsq, ref xsect))
                closest = this.EndPoint;

            if (xres.GetCloserPoint(line.StartPoint, ref mindsq, ref xsect))
                closest = line.StartPoint;

            if (xres.GetCloserPoint(line.EndPoint, ref mindsq, ref xsect))
                closest = line.EndPoint;

            // If a close-to point has been specified, that overrides
            // everything else (however, doing the above has the desired
            // effect of defining the best of the default points). In
            // this case, we allow an intersection that coincides with
            // the line being intersected.

            if (closeTo!=null)
                xres.GetClosest(closeTo, out xsect, 0.0);

            return (xsect!=null);
        }
Beispiel #19
0
 /// <summary>
 /// Initializes a new instance of the <see cref="LineFeature"/> class that corresponds to
 /// a section of another line, and records it as part of the map model.
 /// </summary>
 /// <param name="f">Basic information about the feature (not null).</param>
 /// <param name="baseLine">The line that this section is part of</param>
 /// <param name="start">The point at the start of the line</param>
 /// <param name="end">The point at the end of the line</param>
 /// <exception cref="ArgumentNullException">If either <paramref name="ent"/> or
 /// <paramref name="creator"/> is null.</exception>
 internal LineFeature(IFeature f, LineFeature baseLine, PointFeature start, PointFeature end, bool isTopological)
     : this(f, start, end, new SectionGeometry(baseLine, start, end), isTopological)
 {
 }
Beispiel #20
0
 /// <summary>
 /// Attempts to locate a superseded (inactive) line that was the parent of
 /// a specific line.
 /// </summary>
 /// <param name="line">The line of interest</param>
 /// <returns>A line that was superseded by this edit in order to produce
 /// the line of interest.</returns>
 internal abstract LineFeature GetPredecessor(LineFeature line);
Beispiel #21
0
 /// <summary>
 /// Removes the specified line from this intersection.
 /// </summary>
 /// <param name="line">The line to remove</param>
 /// <returns>True if the line was removed. False if it was not associated
 /// with this intersection</returns>
 internal bool Remove(LineFeature line)
 {
     return m_Lines.Remove(line);
 }
Beispiel #22
0
 /// <summary>
 /// Convenience method that marks a line as "moved" (first checks whether
 /// the specified line is null). This is normally called by implementations
 /// of the <c>Intersect</c> method.
 /// </summary>
 /// <param name="line">The line to mark as moved (may be null)</param>
 protected void SetMoved(LineFeature line)
 {
     if (line!=null)
         line.IsMoved = true;
 }
Beispiel #23
0
 /// <summary>
 /// Highlights the specified line on the command's active display.
 /// </summary>
 /// <param name="line">The line to highlight (ignored if null)</param>
 protected void Highlight(LineFeature line)
 {
     if (line!=null)
     {
         IDrawStyle style = Controller.HighlightStyle;
         ISpatialDisplay display = ActiveDisplay;
         line.Render(display, style);
     }
 }
        /// <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);
        }
Beispiel #25
0
        /// <summary>
        /// Associates this intersection with the specified line.
        /// </summary>
        /// <param name="line">The line that passes through this intersection (not null)</param>
        /// <exception cref="ArgumentNullException">If the specified line is null</exception>
        internal void Add(LineFeature line)
        {
            if (line == null)
                throw new ArgumentNullException();

            if (!m_Lines.Contains(line))
                m_Lines.Add(line);
        }
Beispiel #26
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="line"></param>
        internal void OnLineDeactivation(LineFeature line)
        {
            // Remove the reference the intersection has to the line
            Remove(line);

            // If the intersection now refers only to one line, it's no longer
            // an intersection, so remove it from the spatial index and merge
            // the sections incident on the intersection.
            if (m_Lines.Count<=1)
            {
                if (IsIndexed)
                {
                    CadastralMapModel map = line.MapModel;
                    EditingIndex index = map.EditingIndex;
                    index.RemoveIntersection(this);
                }

                if (m_Lines.Count>0)
                {
                    Topology t = m_Lines[0].Topology;
                    if (t != null)
                    {
                        // Merge the two sections - if we end up with just one
                        // section covering the whole line, replace list topology
                        // with fresh topology for the whole line.
                        if (t.MergeSections(this) == 1)
                        {
                            m_Lines[0].SetTopology(true);
                        }
                    }
                }
            }
        }
 /// <summary>
 /// Creates a new line section
 /// </summary>
 /// <param name="itemName">The name for the item involved</param>
 /// <param name="baseLine">The line that this section is part of</param>
 /// <param name="from">The point at the start of the section</param>
 /// <param name="to">The point at the end of the section</param>
 /// <returns>The created section (never null)</returns>
 internal override LineFeature CreateSection(string itemName, LineFeature baseLine,
     PointFeature from, PointFeature to)
 {
     IFeature f = new FeatureStub(this.Creator, InternalIdValue.Empty, baseLine.EntityType, null);
     return new LineFeature(f, baseLine, from, to, baseLine.IsTopological);
 }