private void noTerminalCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            // If we previously had a terminal line, erase the terminal
            // position and unhighlight the arc.

            ISpatialDisplay draw = m_Cmd.ActiveDisplay;

            if (m_Line != null)
            {
                m_Cmd.ErasePainting();
            }

            m_Line = null;
            ParallelLineUI cmd = Command;

            // Draw the parallel point instead.
            if (m_IsLast)
            {
                m_Terminal = cmd.ParallelTwo;
            }
            else
            {
                m_Terminal = cmd.ParallelOne;
            }

            EditingController.Current.Style(Color.Yellow).Render(draw, m_Terminal);
        }
        /// <summary>
        /// Tries to find a terminal line to end the parallel on.
        /// </summary>
        /// <returns>False if parallel positions are not available. True
        /// otherwise (that does not mean that a terminal was actually found).
        /// </returns>
        bool FindTerminal()
        {
            // Get the position of the parallel point.
            ParallelLineUI cmd = this.Command;
            IPosition      parpos;

            if (m_IsLast)
            {
                parpos = cmd.ParallelTwo;
            }
            else
            {
                parpos = cmd.ParallelOne;
            }

            // The parallel point HAS to be known.
            if (parpos == null)
            {
                MessageBox.Show("Parallel point has not been calculated");
                return(false);
            }

            // Treat the parallel point as the initial terminal.
            m_Terminal = parpos;

            // Get the offset to the parallel.
            double offset = cmd.GetPlanarOffset();

            // Figure out a search radius (the smaller of half the offset,
            // or half a centimetre at the current draw scale).
            double  scale = cmd.ActiveDisplay.MapScale;
            ILength tol   = new Length(Math.Min(offset * 0.5, scale * 0.005));

            // Search for the line closest to the parallel point, and
            // within the search radius. The line has to be visible
            // and selectable.
            CadastralMapModel map = CadastralMapModel.Current;

            //m_Line = map.FindClosestLine(parpos, tol, true);
            m_Line = (map.Index.QueryClosest(parpos, tol, SpatialType.Line) as LineFeature);

            // If we found something, highlight it (after confirming that
            // it really does intersect the parallel).
            if (m_Line != null)
            {
                IPosition xsect = cmd.GetIntersect(m_Line, m_IsLast);
                if (xsect == null)
                {
                    m_Line = null;
                }
                else
                {
                    //pView->UnHighlight(m_pArc);
                    //pView->Highlight(*m_pArc);
                    m_Terminal = xsect;
                }
            }

            return(true);
        }
Exemple #3
0
        /// <summary>
        /// Delegate that's called whenever the index finds a line.
        /// </summary>
        /// <param name="item">The item to process</param>
        /// <returns>True (always), indicating that the query should continue.</returns>
        private bool CheckLine(ISpatialObject item)
        {
            Debug.Assert(item is LineFeature);
            LineFeature line = (LineFeature)item;

            // Return if the line is non-topological
            if (!line.IsTopological)
            {
                return(true);
            }

            Topology t = line.Topology;

            if (t != null)
            {
                foreach (IDivider d in t)
                {
                    CheckType types = (m_Options & DividerCheck.Check(d));
                    if (types != CheckType.Null)
                    {
                        DividerCheck check = new DividerCheck(d, types);
                        m_Result.Add(check);
                    }
                }
            }

            return(OnCheck());
        }
Exemple #4
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);
                        }
                    }
                }
            }
        }
        internal LineSubdivisionControl(LineSubdivisionUI cmd, LineFeature line, Operation recall)
        {
            InitializeComponent();

            // Remember the command.
            m_Cmd = cmd;

            // Remember the line involved & its length (in meters)
            m_Line = line;
            m_GroundLength = line.GroundLength.Meters;

            // No distances so far.
            m_Distances = null;
            m_FromStart = true;

            // If we are recalling a previous operation, grab the observed distances from there (only the primary face)
            LineSubdivisionOperation op = (recall as LineSubdivisionOperation);

            if (op!=null)
            {
                LineFeature[] sections = op.Face.Sections;
                m_Distances = new List<Distance>(sections.Length);
                foreach (LineFeature s in sections)
                    m_Distances.Add(new Distance(s.ObservedLength));
            }
        }
        /// <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;
        }
Exemple #7
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;
     }
 }
        /// <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));
        }
Exemple #9
0
        /// <summary>
        /// Reacts to action that concludes the command dialog.
        /// </summary>
        /// <param name="wnd">The dialog window where the action originated (not used)</param>
        /// <returns>True if command finished ok. This implementation returns the
        /// result of a call to <see cref="FinishCommand"/>.</returns>
        internal override bool DialFinish(Control wnd)
        {
            // Ensure any reserved ID has been returned to the pool
            m_PolygonId.DiscardReservedId();

            // Ensure any text outline has been erased.
            EraseRect();

            // Clear any polygon fill
            DrawPolygon(false);

            // And un-highlight any orientation line
            if (m_Orient != null)
            {
                ErasePainting();
                m_Orient = null;
            }

            // If the last row we created was not associated with a label, get rid of it now.
            //if (m_pLastRow && !m_pLastRow->GetpId())
            //{
            //    delete m_pLastRow;
            //    m_pLastRow = 0;
            //}

            // Get the base class to finish up.
            return(base.DialFinish(wnd));
        }
 /// <summary>
 /// Creates a new <c>AttachPointUI</c>
 /// </summary>
 /// <param name="action">The action that initiated the command</param>
 internal AttachPointUI(IUserAction action)
     : base(action)
 {
     m_PointType = null;
     m_Repeat = false;
     m_Line = null;
 }
        /// <summary>
        /// Rollback this operation (occurs when a user undoes the last edit).
        /// </summary>
        internal override void Undo()
        {
            base.OnRollback();

            // Get rid of the observation
            m_Direction.OnRollback(this);

            // Cut direct refs made by this operation.
            if (m_Line != null)
            {
                m_Line.CutOp(this);
            }

            if (m_CloseTo != null)
            {
                m_CloseTo.CutOp(this);
            }

            // Undo the intersect point and any lines
            Rollback(m_Intersection);
            Rollback(m_DirLine);
            Rollback(m_LineA);
            Rollback(m_LineB);

            // If we actually did a split, re-activate the original line.
            if (m_LineA != null || m_LineB != null)
            {
                m_LineA = null;
                m_LineB = null;
                m_Line.Restore();
            }
        }
        void InitUpdate(LineExtensionOperation pop)
        {
            Form parent = ParentForm;

            parent.Text = "Update Line Extension";

            m_ExtendLine      = pop.ExtendedLine;
            m_IsExtendFromEnd = pop.IsExtendFromEnd;
            m_Length          = new Distance(pop.Length);

            // Was an extension line added?
            m_WantLine = (pop.NewLine != null);

            // Scroll the entity combo to the previously defined
            // entity type for the extension point.
            PointFeature point = pop.NewPoint;
            IEntity      ent   = point.EntityType;

            if (ent != null)
            {
                pointTypeComboBox.SelectEntity(ent);
            }

            // Display the original observed length.
            lengthTextBox.Text = m_Length.Format();

            // Display the point key (if any)
            idComboBox.DropDownStyle = ComboBoxStyle.DropDown;
            idComboBox.Text          = point.FormattedKey;
        }
Exemple #13
0
 /// <summary>
 /// Creates new topology for the specified line.
 /// </summary>
 /// <param name="line">The line the topology is associated with</param>
 /// <returns>New topology for the line (with undefined topological relationships)</returns>
 internal static Topology CreateTopology(LineFeature line)
 {
     // Return topology that's suitable for representing the complete line. This
     // may need to be converted into a SectionTopologyList once we get around to
     // calculating intersections.
     return new LineDivider(line);
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="LineSubdivisionOperation"/> class
        /// using the data read from persistent storage.
        /// </summary>
        /// <param name="editDeserializer">The mechanism for reading back content.</param>
        internal LineSubdivisionOperation(EditDeserializer editDeserializer)
            : base(editDeserializer)
        {
            m_Line = editDeserializer.ReadFeatureRef <LineFeature>(DataField.Line);
            m_Face = editDeserializer.ReadPersistent <LineSubdivisionFace>(DataField.Face);
            //FeatureStub[] sections = editDeserializer.ReadFeatureStubArray(DataField.Result);

            if (editDeserializer.IsNextField(DataField.OtherSide))
            {
                InternalIdValue id = editDeserializer.ReadInternalId(DataField.OtherSide);
                OtherSide = (LineSubdivisionOperation)editDeserializer.MapModel.FindOperation(id);
                Debug.Assert(OtherSide != null);
                OtherSide.OtherSide = this;
            }

            Project p         = editDeserializer.Project;
            IEntity pointType = editDeserializer.ReadEntity(DataField.PointType);

            FeatureStub[] sections = CreateStubs(p, pointType, m_Line.EntityType);

            DeserializationFactory result = new DeserializationFactory(this, sections);

            ProcessFeatures(result);

            // Apply any IDs
            if (editDeserializer.IsNextField(DataField.Ids))
            {
                editDeserializer.ReadIdMappings(DataField.Ids);
            }
        }
Exemple #15
0
        /// <summary>
        /// Attempts to calculate the position of the intersect, using the currently
        /// entered information.
        /// </summary>
        /// <returns>The position of the intersect (null if there isn't one)</returns>
        internal override IPosition CalculateIntersect()
        {
            Direction dir = getDirection.Direction;

            if (dir == null)
            {
                return(null);
            }

            LineFeature line = getLine.Line;

            if (line == null)
            {
                return(null);
            }

            // The closest point may be null if the finish page has never been shown
            PointFeature closeTo = intersectInfo.ClosestPoint;
            IPosition    xsect;
            PointFeature closest;

            dir.Intersect(line, closeTo, out xsect, out closest);
            return(xsect);

            /*
             *
             * // If we got an intersection, and we did not previously have
             * // a close-to point, define that now.
             * if (ok && !m_pCloseTo)
             * {
             *  m_pCloseTo = pClosest;
             *  ShowCloseTo();
             * }
             */
        }
        Image GetImage(Operation op, LineFeature line)
        {
            // If the creating op can't be updated, use a no-entry sign.
            if (!(op is IRevisable))
            {
                return(smallImageList.Images["NoEntry"]);
            }

            // If the line is not a circular curve, use the line icon.
            ArcFeature arc = (line as ArcFeature);

            if (arc == null)
            {
                return(smallImageList.Images["Line"]);
            }

            // This leaves us with either a circle, or gray circle.
            if (arc.Circle.Creator == op)
            {
                return(smallImageList.Images["Circle"]);
            }
            else
            {
                return(smallImageList.Images["GrayCircle"]);
            }
        }
        /// <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>The superseded line that the line of interest was derived from. Null if
        /// this edit did not create the line of interest.</returns>
        internal override LineFeature GetPredecessor(LineFeature line)
        {
            // No predecessors (for same reason that DeletionOperation does
            // not return predecessors)? Not sure about this.

            return(null);
        }
        /// <summary>
        /// Checks if an object is acceptable for trimming.
        /// </summary>
        /// <param name="thing">The candidate object.</param>
        /// <returns>The supplied candidate, cast to a line (given that the candidate is
        /// suitable for trimming). Null if the candidate is not a line, or not suitable
        /// for trimming.</returns>
        static LineFeature PreCheck(ISpatialObject thing)
        {
            // It has no be a line
            LineFeature line = (thing as LineFeature);

            if (line == null)
            {
                return(null);
            }

            // It has to be topological
            Topology t = line.Topology;

            if (t == null)
            {
                return(null);
            }

            // The line should have system-defined topological line
            // sections (if it doesn't that would mean that the complete
            // line dangles).
            SectionTopologyList sectionList = (t as SectionTopologyList);

            if (sectionList == null)
            {
                return(null);
            }

            if (sectionList.CanTrim())
            {
                return(line);
            }

            return(null);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="NewLineOperation"/> class
 /// using the data read from persistent storage.
 /// </summary>
 /// <param name="editDeserializer">The mechanism for reading back content.</param>
 protected NewLineOperation(EditDeserializer editDeserializer)
     : base(editDeserializer)
 {
     // Bit of a hack - does NewCircleOperation actually need to extend NewLineOperation?
     if (!(this is NewCircleOperation) && !(this is NewArcOperation))
         m_NewLine = editDeserializer.ReadPersistent<LineFeature>(DataField.Line);
 }
        /// <summary>
        /// Initializes a new instance of the <see cref="LineSubdivisionOperation"/> class
        /// using the data read from persistent storage.
        /// </summary>
        /// <param name="editDeserializer">The mechanism for reading back content.</param>
        internal LineSubdivisionOperation(EditDeserializer editDeserializer)
            : base(editDeserializer)
        {
            m_Line = editDeserializer.ReadFeatureRef<LineFeature>(DataField.Line);
            m_Face = editDeserializer.ReadPersistent<LineSubdivisionFace>(DataField.Face);
            //FeatureStub[] sections = editDeserializer.ReadFeatureStubArray(DataField.Result);

            if (editDeserializer.IsNextField(DataField.OtherSide))
            {
                InternalIdValue id = editDeserializer.ReadInternalId(DataField.OtherSide);
                OtherSide = (LineSubdivisionOperation)editDeserializer.MapModel.FindOperation(id);
                Debug.Assert(OtherSide != null);
                OtherSide.OtherSide = this;
            }

            Project p = editDeserializer.Project;
            IEntity pointType = editDeserializer.ReadEntity(DataField.PointType);
            FeatureStub[] sections = CreateStubs(p, pointType, m_Line.EntityType);

            DeserializationFactory result = new DeserializationFactory(this, sections);
            ProcessFeatures(result);

            // Apply any IDs
            if (editDeserializer.IsNextField(DataField.Ids))
                editDeserializer.ReadIdMappings(DataField.Ids);
        }
Exemple #21
0
        internal LineSubdivisionControl(LineSubdivisionUI cmd, LineFeature line, Operation recall)
        {
            InitializeComponent();

            // Remember the command.
            m_Cmd = cmd;

            // Remember the line involved & its length (in meters)
            m_Line         = line;
            m_GroundLength = line.GroundLength.Meters;

            // No distances so far.
            m_Distances = null;
            m_FromStart = true;

            // If we are recalling a previous operation, grab the observed distances from there (only the primary face)
            LineSubdivisionOperation op = (recall as LineSubdivisionOperation);

            if (op != null)
            {
                LineFeature[] sections = op.Face.Sections;
                m_Distances = new List <Distance>(sections.Length);
                foreach (LineFeature s in sections)
                {
                    m_Distances.Add(new Distance(s.ObservedLength));
                }
            }
        }
Exemple #22
0
        /// <summary>
        /// Displays info about any previous incarnations of the feature
        /// currently selected for update.
        /// </summary>
        internal void Predecessors()
        {
            // Return if there is no predecessor.
            LineFeature prevLine = GetPredecessor(m_SelectedFeature);

            if (prevLine == null)
            {
                return;
            }

            // Get a list of all the predecessor lines
            List <LineFeature> prev = new List <LineFeature>();

            while (prevLine != null)
            {
                prev.Add(prevLine);
                prevLine = prevLine.GetPredecessor();
            }

            // Display list of the edits
            using (PickPredecessorForm dial = new PickPredecessorForm(prev.ToArray(), true))
            {
                if (dial.ShowDialog() == DialogResult.OK)
                {
                    Run(dial.SelectedLine);
                }
            }
        }
        private void PickPredecessorForm_Shown(object sender, EventArgs e)
        {
            grid.RowCount = m_Lines.Length;

            for (int i = 0; i < m_Lines.Length; i++)
            {
                LineFeature     line = m_Lines[i];
                Operation       op   = line.Creator;
                DataGridViewRow row  = grid.Rows[i];

                row.Tag = line;
                row.Cells["imageColumn"].Value     = GetImage(op, line);
                row.Cells["opIdColumn"].Value      = op.InternalId;
                row.Cells["operationColumn"].Value = op.Name;
                row.Cells["createdColumn"].Value   = op.Session.StartTime.ToShortDateString();
                row.Cells["editorColumn"].Value    = op.Session.User;

                // If the line was created by a connection path, display the precision.
                if (op is PathOperation)
                {
                    PathOperation path = (PathOperation)op;
                    row.Cells["precisionColumn"].Value = path.GetPrecision();
                }
            }

            grid.CurrentCell = null;
        }
Exemple #24
0
        /// <summary>
        /// Creates a new <c>Topology</c> that relates to the specified line.
        /// </summary>
        /// <param name="line">The line the topology relates to (not null)</param>
        internal Topology(LineFeature line)
        {
            if (line==null)
                throw new ArgumentNullException();

            m_Line = line;
        }
Exemple #25
0
        internal void Resolve(CadastralMapModel model)
        {
            IFeatureRef fr = m_LineRef.ReferenceFrom;

            Debug.Assert(fr is Operation);

            Feature f = model.Find <Feature>(m_LineRef.InternalId);

            if (f == null)
            {
                throw new ApplicationException("Cannot locate forward reference " + m_LineRef.InternalId);
            }

            // Only IntersectDirectionAndLineOperation has forward splits, so follow that logic
            LineFeature line = (LineFeature)f;
            var         dff  = new DeserializationFactory(fr as Operation);

            dff.AddLineSplit(line, DataField.SplitBefore, m_SplitBeforeId);
            dff.AddLineSplit(line, DataField.SplitAfter, m_SplitAfterId);

            IntersectOperation xop = (IntersectOperation)fr;
            LineFeature        lineBefore, lineAfter;

            dff.MakeSections(line, DataField.SplitBefore, xop.IntersectionPoint, DataField.SplitAfter,
                             out lineBefore, out lineAfter);
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="SimpleLineSubdivisionOperation"/> class
 /// </summary>
 /// <param name="splitLine">The line to split.</param>
 /// <param name="dist">The distance to the split point.</param>
 /// <param name="isFromEnd">Is the distance observed from the end of the line?</param>
 internal SimpleLineSubdivisionOperation(LineFeature splitLine, Distance dist, bool isFromEnd)
     : base()
 {
     m_Line      = splitLine;
     m_Distance  = dist;
     m_IsFromEnd = isFromEnd;
 }
Exemple #27
0
        /*
         *
         * //
         * //	@parm	AutoCad entity.
         * //	@parm	Cross-reference of CED entity types to AutoCad layers.
         * //	@parm	The style for the annotations.
         * //	@parm	The point involved.
         * //
         * //	@rdesc	TRUE if annotation was written.
         * LOGICAL CeAutoCad::ExportAngles ( const AD_DB_HANDLE DwgHandle
         *                                                      , AD_VMADDR pEntityList
         *                                                      , PAD_ENT_HDR pEntityHeader
         *                                                      , PAD_ENT pEntity
         *                                                      , CacadLayerEntitySet* pLESet
         *                                                      , AD_SHPTB* pStyle
         *                                                      , const CePoint& pt ) const {
         *
         * // Skip if there is no AutoCad layer for the specified point
         * // (the annotations will be going onto the same layer).
         * AD_OBJHANDLE* pLayerHandle = pLESet->GetpLayerHandle(&pt,
         *      m_ContinuousLineTypeHandle,TRUE);
         * if ( !pLayerHandle ) return FALSE;
         *
         * // Get the point to create a set of miscellaneous text
         * // objects.
         * CPtrList text;
         * UINT4 nAngle = pt.CreateAngleText(text,FALSE);
         * if ( nAngle==0 ) return FALSE;
         *
         * // Export each item of text (deleting each item as we go).
         * POSITION pos = text.GetHeadPosition();
         * while ( pos ) {
         *      CeMiscText* pText = (CeMiscText*)text.GetNext(pos);
         *
         *      // What's the actual text string?
         *      CString text;
         *      pText->GetText(text);
         *
         *      // If the text position is to the west of the point,
         *      // align it on the right.
         *      FLOAT8 xt = pText->GetEasting();
         *      FLOAT8 yt = pText->GetNorthing();
         *      INT4 halign = AD_TEXT_JUST_LEFT;
         *
         *      // Take special care with vertical text (allow up to 1mm
         *      // of roundoff).
         *      if ( (xt+0.001) < pt.GetEasting() ) halign = AD_TEXT_JUST_RIGHT;
         *
         *      // Pull out values for function call below.
         *      CeVertex posn(xt,yt);
         *      FLOAT8 grheight = pText->GetHeight();
         *      FLOAT8 rotation = pText->GetRotation();
         *
         *      CacadText AcadText(DwgHandle,pEntityList,pEntityHeader,pEntity);
         *      AcadText.ExportAngleDistText(pStyle,pLayerHandle,pText,text,posn
         *                                                              ,grheight,rotation
         *                                                              ,halign,AD_TEXT_VALIGN_MIDDLE);
         *
         *      delete pText;
         * }
         *
         * // Ensure pointer to the text have been removed too.
         * text.RemoveAll();
         *
         * return TRUE;
         */

        bool WriteLine(ISpatialObject item)
        {
            LineFeature line = (LineFeature)item;

            WriteLineGeometry(line.LineGeometry);
            return(true);
        }
        /// <summary>
        /// Performs the data processing associated with this face.
        /// </summary>
        /// <param name="parentLine">The line that is being subdivided</param>
        /// <param name="ctx">The context in which the geometry is being calculated.</param>
        internal void CalculateGeometry(LineFeature parentLine, EditingContext ctx)
        {
            // Get adjusted lengths for each section
            double[] adjray = GetAdjustedLengths(parentLine, m_Distances);

            double       edist    = 0.0; // Distance to end of section.
            PointFeature start    = parentLine.StartPoint;
            LineGeometry lineGeom = parentLine.LineGeometry;

            for (int i = 0; i < adjray.Length; i++)
            {
                // Calculate the position at the end of the span
                edist += adjray[i];
                IPosition to;
                if (!lineGeom.GetPosition(new Length(edist), out to))
                {
                    throw new Exception("Cannot adjust line section");
                }

                // Get the point feature at the end of the span
                LineFeature  line = m_Sections[i];
                PointFeature end  = line.EndPoint;

                // Assign the calculated position so long as we're not at
                // the end of the line
                if (end != parentLine.EndPoint)
                {
                    end.ApplyPointGeometry(ctx, PointGeometry.Create(to));
                }

                // The end of the current span is the start of the next one
                start = end;
            }
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="SimpleLineSubdivisionOperation"/> class
 /// </summary>
 /// <param name="splitLine">The line to split.</param>
 /// <param name="dist">The distance to the split point.</param>
 /// <param name="isFromEnd">Is the distance observed from the end of the line?</param>
 internal SimpleLineSubdivisionOperation(LineFeature splitLine, Distance dist, bool isFromEnd)
     : base()
 {
     m_Line = splitLine;
     m_Distance = dist;
     m_IsFromEnd = isFromEnd;
 }
 /// <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)
 {
     if (getDirection.Visible)
     {
         getDirection.OnSelectLine(line);
     }
 }
Exemple #31
0
        /// <summary>
        /// Calculates positions that are parallel to a line.
        /// </summary>
        /// <param name="line">The reference line.</param>
        /// <param name="offset">The observed offset (either a <c>Distance</c> or an <c>OffsetPoint</c>).</param>
        /// <param name="sres">The position of the start of the parallel.</param>
        /// <param name="eres">The position of the end of the parallel.</param>
        /// <returns>True if positions calculated ok</returns>
        internal static bool Calculate(LineFeature line, Observation offset, out IPosition sres, out IPosition eres)
        {
            sres = eres = null;

            // Can't calculate if there is insufficient data.
            if (line == null || offset == null)
            {
                return(false);
            }

            // Is it an observed distance?
            Distance dist = (offset as Distance);

            if (dist != null)
            {
                return(ParallelLineUI.Calculate(line, dist, out sres, out eres));
            }

            // The only other thing it could be is an offset point.
            OffsetPoint offPoint = (offset as OffsetPoint);

            if (offPoint != null)
            {
                PointFeature point = offPoint.Point;
                return(ParallelLineUI.Calculate(line, point, out sres, out eres));
            }

            MessageBox.Show("ParallelLineUI.Calculate - Unexpected sort of observation");
            return(false);
        }
Exemple #32
0
        internal override void MouseMove(IPosition p)
        {
            // The following is pretty much the same as what the controller would do to
            // cover auto-select...

            // The ground tolerance is 1mm at the draw scale.
            ISpatialDisplay draw = ActiveDisplay;
            ILength         tol  = new Length(0.001 * draw.MapScale);

            // Just return if we previously selected something, and the
            // search point lies within tolerance.
            if (m_Line != null)
            {
                ILength dist = m_Line.Distance(p);
                if (dist.Meters < tol.Meters)
                {
                    return;
                }

                // Ensure the previously select line gets un-highlighted
                m_Line = null;
                ErasePainting();
            }

            // Ask the map to find the closest line (if any)
            ISpatialIndex index = CadastralMapModel.Current.Index;

            m_Line = (index.QueryClosest(p, tol, SpatialType.Line) as LineFeature);
            Highlight(m_Line);
        }
Exemple #33
0
        /// <summary>
        /// Displays info for a specific line.
        /// </summary>
        /// <param name="line">The selected line.</param>
        /// <param name="wantsplit">True if the line should be split.</param>
        void ShowLine(LineFeature line, bool wantsplit)
        {
            // Define the selected line and whether it should be split.
            OnSelectLine(line);

            SetWantSplit(wantsplit);
        }
Exemple #34
0
 /// <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)
 {
     if (m_Dialog != null)
     {
         m_Dialog.OnSelectLine(line);
     }
 }
Exemple #35
0
 /// <summary>
 /// Creates a new <c>AttachPointUI</c>
 /// </summary>
 /// <param name="action">The action that initiated the command</param>
 internal AttachPointUI(IUserAction action)
     : base(action)
 {
     m_PointType = null;
     m_Repeat    = false;
     m_Line      = null;
 }
        /// <summary>
        /// Creates a new <c>SetTopologyUI</c>
        /// </summary>
        /// <param name="action">The action that initiated this command</param>
        /// <param name="line">The line to change topological status (not null)</param>
        internal SetTopologyUI(IUserAction action, LineFeature line)
            : base(action)
        {
            if (line==null)
                throw new ArgumentNullException();

            m_Line = line;
        }
        public GetLineControl()
        {
            InitializeComponent();

            m_Line = null;
            m_WantSplit = 0;
            m_LineColor = Color.Magenta;
        }
        internal TerminalControl(ParallelLineUI cmd, bool isLast)
        {
            InitializeComponent();

            m_Cmd = cmd;
            m_IsLast = isLast;
            m_Line = null;
            m_Terminal = null;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="SetTopologyOperation"/> class.
        /// </summary>
        /// <param name="line">The line that needs to be changed.</param>
        internal SetTopologyOperation(LineFeature line)
            : base()
        {
            if (line == null)
                throw new ArgumentNullException();

            m_Line = line;
            m_Topological = !line.IsTopological;
        }
        /// <summary>
        /// Constructor for a new line subdivision.
        /// </summary>
        /// <param name="cc">The container for any dialogs</param>
        /// <param name="action">The action that initiated this command</param>
        /// <exception cref="InvalidOperationException">If a specific line is not currently selected</exception>
        internal LineSubdivisionUI(IControlContainer cc, IUserAction action)
            : base(cc, action)
        {
            LineFeature selLine = EditingController.SelectedLine;
            if (selLine == null)
                throw new InvalidOperationException("You must initially select the line you want to subdivide.");

            m_Parent = selLine;
        }
        internal TerminalControl(UpdateUI updcmd, bool isLast)
        {
            InitializeComponent();

            m_Cmd = updcmd;
            m_IsLast = isLast;
            m_Line = null;
            m_Terminal = null;
        }
        /// <summary>
        /// Constructor for doing an update.
        /// </summary>
        /// <param name="editId">The ID of the edit this command deals with.</param>
        /// <param name="updcmd">The update command.</param>
        internal LineSubdivisionUI(IControlContainer cc, EditingActionId editId, UpdateUI updcmd)
            : base(cc, editId, updcmd)
        {
            // The dialog will be created by Run()
            m_Dialog = null;
            m_UpDial = null;

            // The line being subdivided is known via the update.
            m_Parent = null;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="AttachPointOperation"/> class.
        /// </summary>
        /// <param name="line">The line the point should appear on.</param>
        /// <param name="positionRatio">The position ratio of the attached point. A point coincident with the start
        /// of the line is a value of 0. A point at the end of the line is a value of
        /// 1 billion  (1,000,000,000).</param>
        internal AttachPointOperation(LineFeature line, uint positionRatio)
            : base()
        {
            if (line == null)
                throw new ArgumentNullException();

            m_Line = line;
            m_PositionRatio = positionRatio;
            m_Point = null;
        }
        /// <summary>
        /// Constructor to subdivide the currently selected line.
        /// </summary>
        /// <param name="cc">The container for any dialogs</param>
        /// <param name="action">The action that initiated this command</param>
        internal SimpleLineSubdivisionUI(IControlContainer cc, IUserAction action)
            : base(cc, action)
        {
            LineFeature line = EditingController.SelectedLine;
            if (line == null)
                throw new InvalidOperationException("You must initially select the line you want to subdivide.");

            SetInitialValues();
            m_Line = line;
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="LineExtensionOperation"/> class
        /// </summary>
        /// <param name="extendLine">The line that's being extended.</param>
        /// <param name="isFromEnd">True if extending from the end | False from the start.</param>
        /// <param name="length">The length of the extension.</param>
        internal LineExtensionOperation(LineFeature extendLine, bool isFromEnd, Distance length)
            : base()
        {
            m_ExtendLine = extendLine;
            m_IsExtendFromEnd = isFromEnd;
            m_Length = length;

            m_NewLine = null;
            m_NewPoint = null;
        }
        internal LineExtensionControl(LineExtensionUI cmd, LineFeature extendLine, Operation recall)
        {
            InitializeComponent();

            Zero();
            m_Cmd = cmd;
            m_ExtendLine = extendLine;

            LineExtensionOperation op = (recall as LineExtensionOperation);
            if (op!=null)
            {
                m_IsExtendFromEnd = op.IsExtendFromEnd;
                m_Length = new Distance(op.Length);
                m_WantLine = (op.NewLine!=null);
            }
        }
        /// <summary>
        /// Constructor to extend the currently selected line.
        /// </summary>
        /// <param name="cc">The container for any dialogs</param>
        /// <param name="action">The action that initiated this command</param>
        /// <exception cref="InvalidOperationException">If a line is not currently selected</exception>
        internal LineExtensionUI(IControlContainer cc, IUserAction action)
            : base(cc, action)
        {
            LineFeature line = EditingController.SelectedLine;
            if (line == null)
                throw new InvalidOperationException("You must initially select the line you want to extend.");

            // The dialog will be created by Run().
            m_Dialog = null;

            // Remember the line that is being extended.
            m_ExtendLine = line;

            // And initialize the parameters for the operation's Execute() call.
            m_Length = null;
            m_IsExtendFromEnd = true;
            m_LineType = null;
        }
        /// <summary>
        /// Tries to find a terminal line to end the parallel on.
        /// </summary>
        /// <returns>False if parallel positions are not available. True
        /// otherwise (that does not mean that a terminal was actually found).
        /// </returns>
        bool FindTerminal()
        {
            // Get the position of the parallel point.
            ParallelLineUI cmd = this.Command;
            IPosition parpos;

            if (m_IsLast)
                parpos = cmd.ParallelTwo;
            else
                parpos = cmd.ParallelOne;

            // The parallel point HAS to be known.
            if (parpos==null)
            {
                MessageBox.Show("Parallel point has not been calculated");
                return false;
            }

            // Treat the parallel point as the initial terminal.
            m_Terminal = parpos;

            // Get the offset to the parallel.
            double offset = cmd.GetPlanarOffset();

            // Figure out a search radius (the smaller of half the offset,
            // or half a centimetre at the current draw scale).
            double scale = cmd.ActiveDisplay.MapScale;
            ILength tol = new Length(Math.Min(offset*0.5, scale*0.005));

            // Search for the line closest to the parallel point, and
            // within the search radius. The line has to be visible
            // and selectable.
            CadastralMapModel map = CadastralMapModel.Current;
            //m_Line = map.FindClosestLine(parpos, tol, true);
            m_Line = (map.Index.QueryClosest(parpos, tol, SpatialType.Line) as LineFeature);

            // If we found something, highlight it (after confirming that
            // it really does intersect the parallel).
            if (m_Line!=null)
            {
                IPosition xsect = cmd.GetIntersect(m_Line, m_IsLast);
                if (xsect==null)
                    m_Line = null;
                else
                {
                    //pView->UnHighlight(m_pArc);
                    //pView->Highlight(*m_pArc);
                    m_Terminal = xsect;
                }
            }

            return true;
        }
        int InitUpdate()
        {
            // Get the creating op.
            ParallelLineOperation op = UpdateOp;
            if (op==null)
                return 0;

            ISpatialDisplay view = m_Cmd.ActiveDisplay;
            ParallelLineUI cmd = Command;

            // The originally produced parallel may have been
            // changed to have a different offset.

            // Get the line that the parallel originally terminated on (if any).
            if (m_IsLast)
                m_Line = op.Terminal2;
            else
                m_Line = op.Terminal1;

            // If we didn't terminate on any particular line, that's
            // the way it will remain, Otherwise confirm that the
            // parallel continues to intersect it. In the event that
            // the parallel no longer intersects, get another
            // terminal position (and maybe a different terminal line).
            if (m_Line != null)
            {
                m_Terminal = cmd.GetIntersect(m_Line, m_IsLast);
                if (m_Terminal != null)
                {
                    // The parallel still intersects the terminal line that was originally specified,
                    // so highlight the terminal line (having de-selected and unhighlighted
                    // anything that was previously highlighted).

                    m_Line.Render(view, new HighlightStyle());
                }
                else
                {
                    // Get a new terminal position (preferably coincident with some other line).

                    // DON'T try to find a new terminal if the op is being corrected due to a
                    // problem in rollforward preview. In that case, we want the user to see
                    // where the old terminal was ... well, leave that nicety for now.

                    if (!FindTerminal())
                        return -1;
                }
            }
            else
            {
                // Parallel did not terminate on a line, so grab the start or end of the parallel line
                LineFeature parLine = op.ParallelLine;
                if (m_IsLast)
                    m_Terminal = parLine.EndPoint;
                else
                    m_Terminal = parLine.StartPoint;
            }

            return 1;
        }
        internal void OnSelectLine(LineFeature line)
        {
            // Return if line is not defined.
            if (line==null)
                return;

            // If the focus is in the backsight field, and the selected
            // line connects to the from-point, define the backsight to
            // be the point at the other end of the line.
            if (m_From==null || m_Focus!=backsightTextBox)
                return;

            PointFeature point = null;

            if (m_From.IsCoincident(line.StartPoint))
                point = line.EndPoint;
            else if (m_From.IsCoincident(line.EndPoint))
                point = line.StartPoint;

            // Return if a connected point cannot be found.
            if (point==null)
            {
                MessageBox.Show("Cannot locate backsight point.");
                return;
            }

            OnSelectPoint(point);
        }
        /// <summary>
        /// Reacts to the selection of a line feature.
        /// </summary>
        /// <param name="line">The line (if any) that has been selected.</param>
        internal void SelectLine(LineFeature line)
        {
            ISpatialDisplay view = m_Cmd.ActiveDisplay;
            IPosition xsect = null;
            ParallelLineUI cmd = Command;

            // Confirm that the line actually intersects the parallel.
            if (line!=null)
            {
                xsect = cmd.GetIntersect(line, m_IsLast);
                if (xsect==null)
                {
                    MessageBox.Show("Selected line does not intersect the parallel");

                    // De-select the line the user picked
                    EditingController.Current.ClearSelection();

                    // Re-highlight the arc if had originally (if any).
                    if (m_Line!=null)
                        EditingController.Current.Select(m_Line);

                    return;
                }
            }

            // Ensure everything is erased.
            m_Cmd.ErasePainting();

            // Hold on to new terminal position.
            if (xsect!=null)
                m_Terminal = xsect;
            else if (m_IsLast)
                m_Terminal = cmd.ParallelTwo;
            else
                m_Terminal = cmd.ParallelOne;

            // If we previously had an arc selected (and it's not the
            // newly selected line), ensure that it's been unhighlighted.
            //if (m_pArc && m_pArc != pArc) m_pArc->UnHighlight();

            // Hold on to the new terminal arc (if any).
            m_Line = line;

            // If it's defined, ensure the "don't use terminal" check
            // box is clear. And change the static text that tells the
            // user what to do.
            if (m_Line!=null)
            {
                noTerminalCheckBox.Checked = false;
                messageLabel2.Text = "If you want to terminate on a different line, select it.";
            }

            // Ensure everything is drawn as expected.
            cmd.Draw();

            // Resume focus on the Next/Finish button.
            okButton.Focus();
        }
 /// <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>The superseded line that the line of interest was derived from. Null if
 /// this edit did not create the line of interest.</returns>
 internal override LineFeature GetPredecessor(LineFeature line)
 {
     // This edit doesn't supersede anything
     return null;
 }
        /// <summary>
        /// Calculates the start and end positions of a straight line extension.
        /// </summary>
        /// <param name="extendLine">The line being extended.</param>
        /// <param name="isFromEnd">True if extending from the end of the line.</param>
        /// <param name="dist">The length of the extension.</param>
        /// <param name="start">The position of the start of the extension.</param>
        /// <param name="end">The position of the end of the extension.</param>
        /// <returns>True if position have been worked out. False if there is insufficient data,
        /// or the extension is not straight (in that case, the start and end positions come
        /// back as nulls)</returns>
        internal static bool Calculate(LineFeature extendLine, bool isFromEnd, Distance dist,
            out IPosition start, out IPosition end)
        {
            start = end = null;

            // Can't calculate if there is insufficient data.
            if (extendLine==null || dist==null)
                return false;

            // The length must be defined.
            if (!dist.IsDefined)
                return false;

            // The line that's being extended can't be a circular arc.
            if (extendLine is ArcFeature)
                return false;

            // Get the point we're extending from.
            start = (isFromEnd ? extendLine.EndPoint : extendLine.StartPoint);

            // Get the point we're extending to ...

            // Get the orientation point. For multi-segments, we use the
            // point prior to the appropriate end point.
            IPosition orient = extendLine.LineGeometry.GetOrient(!isFromEnd, 0.0);

            // Get the bearing from the orientation point to the start of the extension.
            Turn turn = new Turn(orient, start);
            double bearing = turn.BearingInRadians;

            // Get the distance on the mapping plane.
            double plandist = dist.GetPlanarMetric(start, bearing, extendLine.SpatialSystem);

            // Figure out the end of the extension.
            end = Geom.Polar(start, bearing, plandist);
            return true;
        }
        /// <summary>
        /// Calculates the start and end positions of an extension to a circular arc.
        /// </summary>
        /// <param name="extendLine">The line being extended.</param>
        /// <param name="isFromEnd">True if extending from the end of the line.</param>
        /// <param name="dist">The length of the extension.</param>
        /// <param name="start">The position of the start of the extension.</param>
        /// <param name="end">The position of the end of the extension.</param>
        /// <param name="center">The center of the circle on which the arc lies.</param>
        /// <param name="iscw">Is the circular arc directed clockwise?</param>
        /// <returns>True if position have been worked out. False if there is insufficient data,
        /// or the extension is not on a circular arc, or the length is more than the circumference
        /// of the circle (in those cases, the start and end positions come back as nulls)</returns>
        internal static bool Calculate(LineFeature extendLine, bool isFromEnd, Distance dist,
            out IPosition start, out IPosition end, out IPosition center, out bool iscw)
        {
            start = end = null;
            center = null;
            iscw = true;

            // Can't calculate if there is insufficient data.
            if (extendLine==null || dist==null)
                return false;

            // The length must be defined.
            if (!dist.IsDefined)
                return false;

            // The line that's being extended must be a circular arc.
            ArcFeature arc = (extendLine as ArcFeature);
            if (arc==null)
                return false;

            center = arc.Circle.Center;
            double radius = arc.Circle.Radius;
            iscw = arc.IsClockwise;

            // Get the length of the arc extension, in meters on the ground.
            double arclen = dist.Meters;

            // If the arc length exceeds the length of the circumference,
            // the end point can't be calculated.
            double circumf = Constants.PIMUL2 * radius;
            if (arclen > circumf)
                return false;

            // If we're extending from the start of the arc, the curve direction has
            // to be reversed too.
            if (!isFromEnd)
                iscw = !iscw;

            // Get the point we're extending from.
            start = (isFromEnd ? extendLine.EndPoint : extendLine.StartPoint);

            // Get the point we're extending to ...

            // Get the bearing from the center of the circle to the start of the arc.
            Turn turn = new Turn(center, start);
            double sbearing = turn.BearingInRadians;

            // Get the sector angle (in radians).
            double sector = arclen / radius;

            double ebearing = sbearing;
            if (iscw)
                ebearing += sector;
            else
                ebearing -= sector;

            end = Geom.Polar(center, ebearing, radius);

            // Re-calculate the arc length on the mapping plane,
            arclen = dist.GetPlanarMetric(start, end, extendLine.SpatialSystem);

            // And adjust the end position accordingly.
            sector = arclen / radius;

            if (iscw)
                ebearing = sbearing + sector;
            else
                ebearing = sbearing - sector;

            end = Geom.Polar(center, ebearing, radius);
            return true;
        }
        private void newFaceButton_Click(object sender, EventArgs e)
        {
            // If we previously highlighted something, draw it normally (since it cannot exist as part of any other face).
            m_SelectedLine = null;

            // If a second face doesn't already exist, get the user to specify the distances.

            if (m_Face2 == null)
            {
                try
                {
                    this.WindowState = FormWindowState.Minimized;

                    // Get the distance observations

                    using (LegForm dial = new LegForm(GetObservedLength()))
                    {
                        if (dial.ShowDialog() != DialogResult.OK)
                            return;

                        // Must be at least two distances
                        Distance[] dists = dial.Distances;
                        if (dists == null || dists.Length < 2)
                        {
                            MessageBox.Show("The new face must have at least two spans");
                            return;
                        }

                        // Default annotations to the flip side
                        foreach (Distance d in dists)
                            d.IsAnnotationFlipped = true;

                        // Create the new face (for use in preview only)
                        m_Face2 = new LineSubdivisionFace(dists, m_Face1.IsEntryFromEnd);
                        InitializeWorkingFace(m_Face2, false);

                        newFaceButton.Text = "&Other Face";
                    }
                }

                finally
                {
                    this.WindowState = FormWindowState.Normal;
                }
            }

            // Switch to the other face (possibly the one just added)

            if (m_CurrentFace == m_Face1)
                m_CurrentFace = m_Face2;
            else
                m_CurrentFace = m_Face1;

            RefreshList();
        }
        private void noTerminalCheckBox_CheckedChanged(object sender, EventArgs e)
        {
            // If we previously had a terminal line, erase the terminal
            // position and unhighlight the arc.

            ISpatialDisplay draw = m_Cmd.ActiveDisplay;

            if (m_Line!=null)
                m_Cmd.ErasePainting();

            m_Line = null;
            ParallelLineUI cmd = Command;

            // Draw the parallel point instead.
            if (m_IsLast)
                m_Terminal = cmd.ParallelTwo;
            else
                m_Terminal = cmd.ParallelOne;

            EditingController.Current.Style(Color.Yellow).Render(draw, m_Terminal);
        }
        private void LineSubdivisionUpdateForm_Shown(object sender, EventArgs e)
        {
            // Get the object that was selected for update.
            Feature feat = m_UpdCmd.GetUpdate();
            if (feat == null)
                throw new InvalidOperationException("Unexpected update object");

            // Get the edit that created the primary face
            m_pop = (feat.Creator as LineSubdivisionOperation);
            Debug.Assert(m_pop != null);

            if (!m_pop.IsPrimaryFace)
            {
                m_pop = m_pop.OtherSide;
                Debug.Assert(m_pop != null);
                Debug.Assert(m_pop.IsPrimaryFace);
            }

            // Grab something we throw away if the user decides to cancel
            m_Face1 = CreateWorkingFace(m_pop.Face, true);
            m_Face2 = (m_pop.OtherSide == null ? null : CreateWorkingFace(m_pop.OtherSide.Face, false));

            // If we have two faces, the "New Face" button means you want to switch to the other face.
            if (m_Face2 != null)
                newFaceButton.Text = "&Other Face";

            // Default to the face containing the initially selected feature
            m_CurrentFace = (feat.Creator == m_pop ? m_Face1 : m_Face2);

            // If a line was selected, remember where it is in our working copy (and if it's actually on
            // the alternate face, make that the initial face for editing).
            m_SelectedLine = null;
            LineFeature selectedLine = (feat as LineFeature);
            if (selectedLine != null)
            {
                LineFeature[] sections = (m_CurrentFace == m_Face1 ? m_pop.Face.Sections : m_pop.OtherSide.Face.Sections);
                int lineIndex = Array.FindIndex<LineFeature>(sections, t => t == selectedLine);

                if (lineIndex >= 0)
                    m_SelectedLine = m_CurrentFace.Sections[lineIndex];
            }

            // Disable the option to flip annotation if annotation is currently invisible
            if (!EditingController.Current.AreLineAnnotationsDrawn)
                flipDistButton.Enabled = false;

            // Reload the list and repaint
            RefreshList();
        }
        private void listBox_SelectedValueChanged(object sender, EventArgs e)
        {
            // Get the currently selected line (if any).
            m_SelectedLine = GetSelectedLine();

            // Ensure stuff gets repainted in idle time
            m_UpdCmd.ErasePainting();
        }
        /// <summary>
        /// Constructor for doing an update.
        /// </summary>
        /// <param name="editId">The ID of the edit this command deals with.</param>
        /// <param name="updcmd">The update command.</param>
        internal LineExtensionUI(IControlContainer cc, EditingActionId editId, UpdateUI updcmd)
            : base(cc, editId, updcmd)
        {
            // The dialog will be created by Run().
            m_Dialog = null;

            // The line we extended is known via the update.
            m_ExtendLine = null;

            // And initialize the parameters for the operation's Execute() call.
            m_Length = null;
            m_IsExtendFromEnd = true;
            m_LineType = null;
        }
        internal override void MouseMove(IPosition p)
        {
            // The following is pretty much the same as what the controller would do to
            // cover auto-select...

            // The ground tolerance is 1mm at the draw scale.
            ISpatialDisplay draw = ActiveDisplay;
            ILength tol = new Length(0.001 * draw.MapScale);

            // Just return if we previously selected something, and the
            // search point lies within tolerance.
            if (m_Line!=null)
            {
                ILength dist = m_Line.Distance(p);
                if (dist.Meters < tol.Meters)
                    return;

                // Ensure the previously select line gets un-highlighted
                m_Line = null;
                ErasePainting();
            }

            // Ask the map to find the closest line (if any)
            ISpatialIndex index = CadastralMapModel.Current.Index;
            m_Line = (index.QueryClosest(p, tol, SpatialType.Line) as LineFeature);
            Highlight(m_Line);
        }