/// <summary> /// Performs data processing that involves creating or retiring spatial features. /// Newly created features will not have any definition for their geometry - a /// subsequent call to <see cref="CalculateGeometry"/> is needed to to that. /// </summary> /// <param name="ff">The factory class for generating any spatial features</param> internal override void ProcessFeatures(FeatureFactory ff) { // If this method is being called during deserialization from the database, you // can't easily determine whether the parallel ends at an offset point (since we // haven't yet calculated where the parallel line is located). In that case, we // can utilize the IDs of the "From" and "To" items that should be there on // deserialization. // The problem is that during the initial execution, we don't have a way to // pass through the positions that were determined in the Execute method. To // cover that, the Execute method is expected to add an item description if // a new feature needs to be created. PointFeature from, to; if (ff.HasFeatureDescription(DataField.From)) { from = ff.CreatePointFeature(DataField.From); } else { from = this.OffsetPoint; } if (ff.HasFeatureDescription(DataField.To)) { to = ff.CreatePointFeature(DataField.To); } else { to = this.OffsetPoint; } Debug.Assert(from != null); Debug.Assert(to != null); // Create a circular arc (without any circle) if the reference line is a circular // arc, or a section that's based on a circular arc. if (m_RefLine.GetArcBase() == null) { m_ParLine = ff.CreateSegmentLineFeature(DataField.NewLine, from, to); } else { m_ParLine = ff.CreateArcFeature(DataField.NewLine, from, to); } }
/// <summary> /// Creates any new spatial features (without any geometry) /// </summary> /// <param name="ff">The factory class for generating spatial features</param> internal override void ProcessFeatures(FeatureFactory ff) { m_NewPoint = ff.CreatePointFeature(DataField.NewPoint); if (ff.HasFeatureDescription(DataField.NewLine)) { PointFeature from = (m_IsExtendFromEnd ? m_ExtendLine.EndPoint : m_ExtendLine.StartPoint); ArcFeature arc = m_ExtendLine.GetArcBase(); if (arc == null) { m_NewLine = ff.CreateSegmentLineFeature(DataField.NewLine, from, m_NewPoint); } else { m_NewLine = ff.CreateArcFeature(DataField.NewLine, from, m_NewPoint); } m_NewLine.ObservedLength = m_Length; } }
/// <summary> /// Calculates positions that are parallel to a line. /// </summary> /// <param name="line">The reference line.</param> /// <param name="offpoint">The point the parallel must pass through.</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 refline, PointFeature offpoint, out IPosition sres, out IPosition eres) { // No result positions so far. sres = eres = null; // Get the ends of the reference line. IPosition spos = refline.StartPoint; IPosition epos = refline.EndPoint; // If the reference line is a circular arc ArcFeature arc = refline.GetArcBase(); if (arc != null) { // Get the curve info Circle circle = arc.Circle; double radius = circle.Radius; IPosition centre = circle.Center; bool iscw = arc.IsClockwise; // Get the (planar) distance from the centre of the // circle to the offset point. double offdist = Geom.Distance(offpoint, centre); // Project the BC/EC radially. double sbear = Geom.BearingInRadians(centre, spos); sres = Geom.Polar(centre, sbear, offdist); double ebear = Geom.BearingInRadians(centre, epos); eres = Geom.Polar(centre, ebear, offdist); } else { double bearing = Geom.BearingInRadians(spos, epos); // Get the perpendicular distance (signed) from the offset point // to the reference line. double offdist = Geom.SignedDistance(spos.X, spos.Y, bearing, offpoint.X, offpoint.Y); // Calculate the parallel points. bearing += Constants.PIDIV2; sres = Geom.Polar(spos, bearing, offdist); eres = Geom.Polar(epos, bearing, offdist); } return(true); }
internal void Draw() // was Paint { // Nothing to do if parallel points undefined. if (m_South == null || m_North == null) { return; } Debug.Assert(m_Line != null); ISpatialDisplay draw = m_Cmd.ActiveDisplay; IDrawStyle solidStyle = EditingController.Current.Style(Color.Magenta); IDrawStyle dottedStyle = new DottedStyle(); ArcFeature arc = m_Line.GetArcBase(); if (arc != null) { // The parallel portion is solid, while the remaining portion of the circle is dotted. CircularArcGeometry cg = new CircularArcGeometry(arc.Circle.Center, m_South, m_North, arc.IsClockwise); solidStyle.Render(draw, cg); cg.IsClockwise = !cg.IsClockwise; dottedStyle.Render(draw, cg); } else { // What's the bearing from the start to the end of the parallel? double bearing = Geom.BearingInRadians(m_South, m_North); // What's the max length of a diagonal crossing the entire screen? double maxdiag = m_Cmd.MaxDiagonal; // Project to a point below the southern end of the parallel, as // well as a point above the northern end. IPosition below = Geom.Polar(m_South, bearing + Constants.PI, maxdiag); IPosition above = Geom.Polar(m_North, bearing, maxdiag); LineSegmentGeometry.Render(below, m_South, draw, dottedStyle); LineSegmentGeometry.Render(m_South, m_North, draw, solidStyle); LineSegmentGeometry.Render(m_North, above, draw, dottedStyle); // If we have an offset point, draw it in green. if (m_Point != null) { m_Point.Draw(draw, Color.Green); } } }
/// <summary> /// Calculates positions that are parallel to a line. /// </summary> /// <param name="line">The reference line.</param> /// <param name="offset">The offset to the parallel, in ground units. Signed to denote /// which side (less than zero means it's to the left of the reference line).</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> static bool Calculate(LineFeature line, Distance offset, out IPosition sres, out IPosition eres) { // No result positions so far. sres = eres = null; // Get the ends of the reference line. IPosition spos = line.StartPoint; IPosition epos = line.EndPoint; ISpatialSystem sys = CadastralMapModel.Current.SpatialSystem; // If the reference line is a circular arc, get the curve info. ArcFeature arc = line.GetArcBase(); if (arc != null) { Circle circle = arc.Circle; double radius = circle.Radius; IPosition centre = circle.Center; bool iscw = arc.IsClockwise; // Get the midpoint of the curve. The reduction of the // ground distance will be along the line that goes // from the centre of the circle & through this position. ILength len = line.Length; ILength halfLen = new Length(len.Meters * 0.5); IPosition middle; line.LineGeometry.GetPosition(halfLen, out middle); // Get the bearing from the centre to the mid-position // and use that to reduce the offset to the mapping plane. double bearing = Geom.BearingInRadians(centre, middle); double offdist = offset.GetPlanarMetric(middle, bearing, sys); // No parallel if the offset exceeds the radius. // if ( offdist > radius ) return FALSE; // Calculate the parallel points. double sbear = Geom.BearingInRadians(centre, spos); sres = Geom.Polar(centre, sbear, offdist + radius); double ebear = Geom.BearingInRadians(centre, epos); eres = Geom.Polar(centre, ebear, offdist + radius); } else { // Get the bearing.of the line. double bearing = Geom.BearingInRadians(spos, epos); // Get the planar distance for a perpendicular line that passes // through the midpoint of the reference line. The planar distance // will have the same sign as the ground value. IPosition middle = Position.CreateMidpoint(spos, epos); bearing += Constants.PIDIV2; double offdist = offset.GetPlanarMetric(middle, bearing, sys); // Calculate the parallel points. sres = Geom.Polar(spos, bearing, offdist); eres = Geom.Polar(epos, bearing, offdist); } return(true); }
/// <summary> /// Draws the current state of the edit /// </summary> internal void Draw() { Debug.Assert(m_Line != null); ISpatialDisplay view = ActiveDisplay; // Figure out the positions for the ends of the parallel line (if any) ... // Assume we already know both terminals. IPosition start = m_Term1; IPosition end = m_Term2; // If either one is undefined, but a dialog for it is active, // try to get the terminal from there instead. if (m_TermDial1 != null && start == null) { start = m_TermDial1.TerminalPosition; } if (m_TermDial2 != null && end == null) { end = m_TermDial2.TerminalPosition; } // If they weren't actually defined, use the parallel points instead. if (start == null) { start = m_Par1; } if (end == null) { end = m_Par2; } // If those weren't defined either, try to calculate them now. if (end == null && Calculate()) { start = m_Par1; end = m_Par2; } // Any offset point if (m_OffsetPoint != null) { m_OffsetPoint.Draw(view, Color.Green); } // Everything else should draw in usual command-style colour. IDrawStyle style = EditingController.Current.Style(Color.Magenta); IDrawStyle dottedStyle = new DottedStyle(); // If the reference line is a curve, get the curve info. ArcFeature arc = m_Line.GetArcBase(); if (arc != null) { bool iscw = arc.IsClockwise; // Reverse the direction if necessary. if (m_IsReversed) { iscw = !iscw; } // Draw the parallel line (the rest of the circle being dotted). if (start != null) { CircularArcGeometry parArc = new CircularArcGeometry(arc.Circle, start, end, iscw); style.Render(view, parArc); parArc.IsClockwise = !parArc.IsClockwise; dottedStyle.Render(view, parArc); } } else { // PARALLEL IS STRAIGHT // If we've got something, figure out positions for dotted portion. if (start != null) { // What's the max length of a diagonal crossing the entire screen? double maxdiag = this.MaxDiagonal; // What's the bearing from the start to the end of the parallel? double bearing = Geom.BearingInRadians(start, end); // Project to a point before the start end of the parallel, as // well as a point after the end. IPosition before = Geom.Polar(start, bearing + Constants.PI, maxdiag); IPosition after = Geom.Polar(end, bearing, maxdiag); LineSegmentGeometry.Render(before, start, view, dottedStyle); LineSegmentGeometry.Render(start, end, view, style); LineSegmentGeometry.Render(end, after, view, dottedStyle); } } // Draw terminal positions (if defined). if (m_Term1 != null) { style.Render(view, m_Term1); } if (m_Term2 != null) { style.Render(view, m_Term2); } // The terminal lines. if (m_TermLine1 != null) { m_TermLine1.Render(view, style); } if (m_TermLine2 != null) { m_TermLine2.Render(view, style); } // Do the active dialog last so their stuff draws on top. if (m_ParDial != null) { m_ParDial.Draw(); } if (m_TermDial1 != null) { m_TermDial1.Draw(); } if (m_TermDial2 != null) { m_TermDial2.Draw(); } }
/// <summary> /// Returns the intersection of the parallel with a line. /// </summary> /// <param name="refline">The reference line.</param> /// <param name="parpos">Search position that coincides with the parallel.</param> /// <param name="line">The line to intersect with.</param> /// <returns>The intersection (if any). In cases where the line intersects the /// parallel more than once, you get the intersection that is closest to the /// search position.</returns> internal static IPosition GetIntersect(LineFeature refline, IPosition parpos, LineFeature line) { // Make sure the intersection is undefined. IPosition result = null; // Return if the parallel point is undefined. if (parpos == null) { return(null); } // If the reference line is a circular arc (or a section based on an arc), get the curve info. ArcFeature arc = refline.GetArcBase(); if (arc != null) { Circle circle = arc.Circle; double radius = circle.Radius; IPointGeometry centre = circle.Center; bool iscw = arc.IsClockwise; // Construct a circle that passes through the search position double parrad = Geom.Distance(centre, parpos); // Intersect the circle with the line to intersect with. IntersectionResult xres = new IntersectionResult(line); uint nx = xres.Intersect(centre, parrad); if (nx == 0) { return(null); } // If there is only one intersection, that's what we want. if (nx == 1) { return(xres.Intersections[0].P1); } // Get the intersection that is closest to the search position. xres.GetClosest(parpos, out result, 0.0); } else { // Get the bearing from the start to the end of the reference line. IPosition spos = refline.StartPoint; IPosition epos = refline.EndPoint; double bearing = Geom.BearingInRadians(spos, epos); // Project the parallel line to positions that are a long way away (but make sure we // don't end up with negative numbers). Window searchWindow = new Window(line.Extent); searchWindow.Union(refline.Extent); searchWindow.Union(parpos); double dist = Geom.Distance(searchWindow.Min, searchWindow.Max); IPosition start = Geom.Polar(parpos, bearing + Constants.PI, dist); IPosition end = Geom.Polar(parpos, bearing, dist); // Intersect the line segment with the line to intersect with. IntersectionResult xres = new IntersectionResult(line); IPointGeometry sg = new PointGeometry(start); IPointGeometry eg = new PointGeometry(end); uint nx = xres.Intersect(sg, eg); if (nx == 0) { return(null); } // If there is only one intersection, that's what we want. if (nx == 1) { return(xres.Intersections[0].P1); } // Get the intersection that is closest to the search position xres.GetClosest(parpos, out result, 0.0); } return(result); }
/// <summary> /// Calculates positions that are parallel to a line. /// </summary> /// <param name="line">The reference line.</param> /// <param name="offset">The offset to the parallel, in ground units. Signed to denote /// which side (less than zero means it's to the left of the reference line).</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> static bool Calculate(LineFeature line, Distance offset, out IPosition sres, out IPosition eres) { // No result positions so far. sres = eres = null; // Get the ends of the reference line. IPosition spos = line.StartPoint; IPosition epos = line.EndPoint; ISpatialSystem sys = CadastralMapModel.Current.SpatialSystem; // If the reference line is a circular arc, get the curve info. ArcFeature arc = line.GetArcBase(); if (arc != null) { Circle circle = arc.Circle; double radius = circle.Radius; IPosition centre = circle.Center; bool iscw = arc.IsClockwise; // Get the midpoint of the curve. The reduction of the // ground distance will be along the line that goes // from the centre of the circle & through this position. ILength len = line.Length; ILength halfLen = new Length(len.Meters * 0.5); IPosition middle; line.LineGeometry.GetPosition(halfLen, out middle); // Get the bearing from the centre to the mid-position // and use that to reduce the offset to the mapping plane. double bearing = Geom.BearingInRadians(centre, middle); double offdist = offset.GetPlanarMetric(middle, bearing, sys); // No parallel if the offset exceeds the radius. // if ( offdist > radius ) return FALSE; // Calculate the parallel points. double sbear = Geom.BearingInRadians(centre, spos); sres = Geom.Polar(centre, sbear, offdist+radius); double ebear = Geom.BearingInRadians(centre, epos); eres = Geom.Polar(centre, ebear, offdist+radius); } else { // Get the bearing.of the line. double bearing = Geom.BearingInRadians(spos, epos); // Get the planar distance for a perpendicular line that passes // through the midpoint of the reference line. The planar distance // will have the same sign as the ground value. IPosition middle = Position.CreateMidpoint(spos, epos); bearing += Constants.PIDIV2; double offdist = offset.GetPlanarMetric(middle, bearing, sys); // Calculate the parallel points. sres = Geom.Polar(spos, bearing, offdist); eres = Geom.Polar(epos, bearing, offdist); } return true; }
/// <summary> /// Returns the intersection of the parallel with a line. /// </summary> /// <param name="refline">The reference line.</param> /// <param name="parpos">Search position that coincides with the parallel.</param> /// <param name="line">The line to intersect with.</param> /// <returns>The intersection (if any). In cases where the line intersects the /// parallel more than once, you get the intersection that is closest to the /// search position.</returns> internal static IPosition GetIntersect(LineFeature refline, IPosition parpos, LineFeature line) { // Make sure the intersection is undefined. IPosition result = null; // Return if the parallel point is undefined. if (parpos==null) return null; // If the reference line is a circular arc (or a section based on an arc), get the curve info. ArcFeature arc = refline.GetArcBase(); if (arc != null) { Circle circle = arc.Circle; double radius = circle.Radius; IPointGeometry centre = circle.Center; bool iscw = arc.IsClockwise; // Construct a circle that passes through the search position double parrad = Geom.Distance(centre, parpos); // Intersect the circle with the line to intersect with. IntersectionResult xres = new IntersectionResult(line); uint nx = xres.Intersect(centre, parrad); if (nx==0) return null; // If there is only one intersection, that's what we want. if (nx==1) return xres.Intersections[0].P1; // Get the intersection that is closest to the search position. xres.GetClosest(parpos, out result, 0.0); } else { // Get the bearing from the start to the end of the reference line. IPosition spos = refline.StartPoint; IPosition epos = refline.EndPoint; double bearing = Geom.BearingInRadians(spos, epos); // Project the parallel line to positions that are a long way away (but make sure we // don't end up with negative numbers). Window searchWindow = new Window(line.Extent); searchWindow.Union(refline.Extent); searchWindow.Union(parpos); double dist = Geom.Distance(searchWindow.Min, searchWindow.Max); IPosition start = Geom.Polar(parpos, bearing+Constants.PI, dist); IPosition end = Geom.Polar(parpos, bearing, dist); // Intersect the line segment with the line to intersect with. IntersectionResult xres = new IntersectionResult(line); IPointGeometry sg = new PointGeometry(start); IPointGeometry eg = new PointGeometry(end); uint nx = xres.Intersect(sg, eg); if (nx==0) return null; // If there is only one intersection, that's what we want. if (nx==1) return xres.Intersections[0].P1; // Get the intersection that is closest to the search position xres.GetClosest(parpos, out result, 0.0); } return result; }
/// <summary> /// Calculates positions that are parallel to a line. /// </summary> /// <param name="line">The reference line.</param> /// <param name="offpoint">The point the parallel must pass through.</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 refline, PointFeature offpoint, out IPosition sres, out IPosition eres) { // No result positions so far. sres = eres = null; // Get the ends of the reference line. IPosition spos = refline.StartPoint; IPosition epos = refline.EndPoint; // If the reference line is a circular arc ArcFeature arc = refline.GetArcBase(); if (arc != null) { // Get the curve info Circle circle = arc.Circle; double radius = circle.Radius; IPosition centre = circle.Center; bool iscw = arc.IsClockwise; // Get the (planar) distance from the centre of the // circle to the offset point. double offdist = Geom.Distance(offpoint, centre); // Project the BC/EC radially. double sbear = Geom.BearingInRadians(centre, spos); sres = Geom.Polar(centre, sbear, offdist); double ebear = Geom.BearingInRadians(centre, epos); eres = Geom.Polar(centre, ebear, offdist); } else { double bearing = Geom.BearingInRadians(spos, epos); // Get the perpendicular distance (signed) from the offset point // to the reference line. double offdist = Geom.SignedDistance(spos.X, spos.Y, bearing, offpoint.X, offpoint.Y); // Calculate the parallel points. bearing += Constants.PIDIV2; sres = Geom.Polar(spos, bearing, offdist); eres = Geom.Polar(epos, bearing, offdist); } return true; }