void ShowResult() { // If we have the first two points, get the distance between // them, format the result, and display it. if (m_Point1 != null && m_Point2 != null) { double metric = Geom.Distance(m_Point1, m_Point2); distance1TextBox.Text = Format(metric, m_Point1, m_Point2); } // Same for the second pair of points. if (m_Point2 != null && m_Point3 != null) { double metric = Geom.Distance(m_Point2, m_Point3); distance2TextBox.Text = Format(metric, m_Point2, m_Point3); } // If we have all 3 points, display the angle. if (m_Point1 != null && m_Point2 != null && m_Point3 != null) { // Get the clockwise angle. Turn reft = new Turn(m_Point2, m_Point1); double ang = reft.GetAngleInRadians(m_Point3); // Get the complement if we actually want it anti-clockwise. if (!m_Clockwise) { ang = Constants.PIMUL2 - ang; } angleTextBox.Text = RadianValue.AsString(ang); } }
/// <summary> /// Performs the data processing associated with this editing operation. /// </summary> /// <param name="ctx">The context in which the geometry is being calculated.</param> internal override void CalculateGeometry(EditingContext ctx) { //IPosition p = (base.CheckPosition == null ? Calculate() : base.CheckPosition); IPosition p = Calculate(); if (p == null) { p = CheckPosition; Log(String.Format("Id={0} (CEdit={1:0.0}E {2:0.0}N", this.EditSequence, p.X, p.Y)); } else if (CheckPosition != null) { double d = Geom.Distance(p, CheckPosition); if (d > 1.0) { Log(String.Format("Id={0} (CEdit={1:0.0}E {2:0.0}N) (Backsight={3:0.0}E {4:0.0}N) Delta={5:0.000}", this.EditSequence, CheckPosition.Easting.Meters, CheckPosition.Northing.Meters, p.X, p.Y, d)); } p = CheckPosition; } PointGeometry pg = PointGeometry.Create(p); m_Intersection.ApplyPointGeometry(ctx, pg); }
/// <summary> /// Returns the offset for the parallel, in units on the mapping plane. In order /// for this to work, a prior call to Calculate must be made. /// </summary> /// <returns>The offset distance on the mapping plane (>= 0).</returns> internal double GetPlanarOffset() { // If the reference line or the parallel points are undefined, there's nothing we can do. if (m_Line == null || m_Par1 == null || m_Par2 == null) { return(0.0); } // If the reference line is a curve, get the curve info. ArcFeature arc = m_Line.GetArcBase(); if (arc != null) { // Get the (planar) radial offset from the circle to one of the parallel positions. double radius = arc.Circle.Radius; IPosition center = arc.Circle.Center; return(Math.Abs(Geom.Distance(center, m_Par1) - radius)); } // Get the ends of the reference line. IPosition spos = m_Line.StartPoint; IPosition epos = m_Line.EndPoint; // And its bearing. double bearing = Geom.BearingInRadians(spos, epos); // Get the perpendicular distance (signed) from one of the // parallel points to the reference line. double offdist = Geom.SignedDistance(spos.X, spos.Y, bearing, m_Par1.X, m_Par1.Y); return(Math.Abs(offdist)); }
internal virtual void ShowResult() { // If we have two points, get the distance between them, // format the result, and display it. if (m_Point1 != null && m_Point2 != null) { // Get the distance on the mapping plane. double metric = Geom.Distance(m_Point1, m_Point2); distanceTextBox.Text = Format(metric, m_Point1, m_Point2); } }
public void TestCrossPosition() { Vector a = new Vector(0, 400); Vector b = new Vector(640, 400); Vector c = new Vector(50, 397.8131f); Vector e = new Vector(500, 376.573f); Line ab = new Line(a, b); float dist1 = Geom.Distance(ab, c); float dist2 = Geom.Distance(ab, e); Console.Out.WriteLine("dist1 = " + dist1); Console.Out.WriteLine("dist2 = " + dist2); }
/// <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); }
/// <summary> /// Uses the currently displayed information to try to construct a /// circle representing the distance. /// </summary> /// <returns>The constructed circle (null if a circle cannot be created /// based on the information that's currently displayed)</returns> Circle GetCurrentCircle() { Circle result = null; // Undefine the address of the relevant distance observation. m_ObservedDistance = null; if (m_From == null) { return(null); } if (m_DistancePoint != null || (m_Distance != null && m_Distance.Meters > Constants.TINY)) { double radius; // If we have an offset point, get the radius. if (m_DistancePoint != null) { radius = Geom.Distance(m_From, m_DistancePoint); } else { radius = m_Distance.Meters; } // Construct the circle result = new Circle(m_From, radius); // Create the appropriate distance observation (this is what // gets picked up when we actually go to work out the // intersection on the last page of the intersect dialog. if (m_DistancePoint != null) { m_OffsetPoint = new OffsetPoint(m_DistancePoint); m_ObservedDistance = m_OffsetPoint; } else { m_ObservedDistance = m_Distance; } } return(result); }
/// <summary> /// Performs the data processing associated with this editing operation. /// </summary> /// <param name="ctx">The context in which the geometry is being calculated.</param> internal override void CalculateGeometry(EditingContext ctx) { // Calculate the end positions IPosition spos, epos; if (!Calculate(out spos, out epos)) { throw new Exception("Failed to calculate parallel line positions"); } // Apply the calculated positions so long as the end points of the parallel line // were created by this edit if (m_ParLine.StartPoint.Creator == this) { m_ParLine.StartPoint.ApplyPointGeometry(ctx, PointGeometry.Create(spos)); } if (m_ParLine.EndPoint.Creator == this) { m_ParLine.EndPoint.ApplyPointGeometry(ctx, PointGeometry.Create(epos)); } // If the parallel is an arc, define the geometry if (m_ParLine is ArcFeature) { // Get the center of the reference line ArcFeature refArc = m_RefLine.GetArcBase(); PointFeature center = refArc.Circle.CenterPoint; // Obtain a circle for the parallel double radius = Geom.Distance(center, m_ParLine.StartPoint); Circle circle = MapModel.AddCircle(center, radius); // Define arc direction bool iscw = refArc.IsClockwise; if (IsArcReversed) { iscw = !iscw; } ArcGeometry geom = new ArcGeometry(circle, m_ParLine.StartPoint, m_ParLine.EndPoint, iscw); (m_ParLine as ArcFeature).Geometry = geom; } }
/// <summary> /// Uses the currently displayed information to try to construct a /// circle object. /// </summary> /// <returns>The constructed circle (null if a circle cannot be created /// based on the information that's currently displayed)</returns> Circle GetCurrentCircle() { Circle result = null; // Get rid of any previous radius observation. m_Radius = null; if (m_Center != null && (m_RadiusPoint != null || m_RadiusDistance != null)) { double radius; // If we have an offset point, get the radius. if (m_RadiusPoint != null) { radius = Geom.Distance(m_Center, m_RadiusPoint); } else { radius = m_RadiusDistance.Meters; } // Create the circle result = new Circle(m_Center, radius); // Create the appropriate distance observation. // (not sure why these were needed, it certainly looks out of place as // part of this method) if (m_RadiusPoint != null) { m_Radius = new OffsetPoint(m_RadiusPoint); } else { m_Radius = new Distance(m_RadiusDistance); } } return(result); }
/// <summary> /// The diagonal length of a line that spans the display when it is /// drawn at the overview scale. /// </summary> /// <param name="display"></param> /// <returns></returns> double GetMaxDiagonal(ISpatialDisplay display) { IWindow x = display.MaxExtent; return(Geom.Distance(x.Min, x.Max)); }
/// <summary> /// Intersects this direction with a line. /// </summary> /// <param name="line">The line to intersect with.</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; // Define the length of the direction line as the length // of a diagonal that crosses the map's extent. IWindow mapWin = SpatialController.Current.MapModel.Extent; Debug.Assert(mapWin != null); // If the window is currently undefined (e.g. during deserialization), // just use a really big distance. // TODO: This is a hack, but hopefully it may be shortlived, because // new logic is in the works for handling updates. double dist = (mapWin.IsEmpty ? 100000.0 : Geom.Distance(mapWin.Min, mapWin.Max)); // Define the position of the direction line. DON'T use the from- // point, because there may be an offset to the direction. IPosition fromPos = this.StartPosition; IPosition toPos = Geom.Polar(fromPos, this.Bearing.Radians, dist); // Construct a corresponding line segment. ITerminal start = new FloatingTerminal(fromPos); ITerminal end = new FloatingTerminal(toPos); SegmentGeometry seg = new SegmentGeometry(start, end); // Intersect the line segment with the other one. IntersectionResult xres = new IntersectionResult(line); uint nx = seg.Intersect(xres); if (nx == 0) { return(false); } // Determine which terminal point is the best. Start with the // ends of the intersected line. double mindsq = Double.MaxValue; if (xres.GetCloserPoint(line.StartPoint, ref mindsq, ref xsect)) { closest = line.StartPoint; } if (xres.GetCloserPoint(line.EndPoint, ref mindsq, ref xsect)) { closest = line.EndPoint; } // Check whether the direction from-point is any closer (the position may be // different from the start of the direction line, because the direction may // have an offset). if (xres.GetCloserPoint(this.From, ref mindsq, ref xsect)) { closest = this.From; } // 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. // -- actually, we don't, since GetClosest uses a > 0 test if (closeTo != null) { xres.GetClosest(closeTo, out xsect, 0.0); /* * IPosition xCloseTo; * xres.GetClosest(closeTo, out xCloseTo, 0.0); * * if (xCloseTo != null) * xsect = xCloseTo; */ } return(xsect != null); }
/// <summary> /// Returns the intersection of the parallel with a line. A prior call to Calculate is required. /// </summary> /// <param name="line">The line to intersect with.</param> /// <param name="isEndParallel">Is the intersection biased towards the end of the parallel?</param> /// <returns>The intersection (if any). In cases where the line intersects the parallel /// more than once, you get an arbitrary intersection.</returns> internal IPosition GetIntersect(LineFeature line, bool isEndParallel) { // Make sure the intersection is undefined. IPosition result = null; // Return if the parallel points are undefined. if (m_Par1 == null || m_Par2 == null) { return(null); } // If the reference line is a circular arc, get the curve info. ArcFeature arc = m_Line.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 parallel points (assumed to have the same distance // with respect to the centre of the circle). double parrad = Geom.Distance(centre, m_Par1); // 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 parallel point // that has the bias. if (isEndParallel) { xres.GetClosest(m_Par2, out result, 0.0); } else { xres.GetClosest(m_Par1, out result, 0.0); } } else { // Get the bearing from the start to the end of the parallel. double bearing = Geom.BearingInRadians(m_Par1, m_Par2); // Get the ground dimension of a line that crosses the // extent of the draw window. double dist = MaxDiagonal; // Project the parallel line to positions that are well // beyond the draw extent. IPosition start = Geom.Polar(m_Par1, bearing + Constants.PI, dist); IPosition end = Geom.Polar(m_Par2, bearing, dist); // Intersect the line segment with the line to intersect with. IntersectionResult xres = new IntersectionResult(line); IPointGeometry sg = PointGeometry.Create(start); IPointGeometry eg = PointGeometry.Create(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 parallel point // that has the bias. if (isEndParallel) { xres.GetClosest(m_Par2, out result, 0.0); } else { xres.GetClosest(m_Par1, out result, 0.0); } } return(result); }
/// <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); }
private void okButton_Click(object sender, EventArgs e) { // Get the northing & easting. double y; if (!Double.TryParse(northingTextBox.Text, out y)) { MessageBox.Show("Bad northing"); northingTextBox.Focus(); return; } double x; if (!Double.TryParse(eastingTextBox.Text, out x)) { MessageBox.Show("Bad easting"); eastingTextBox.Focus(); return; } if (Math.Abs(x) < Double.Epsilon || Math.Abs(y) < Double.Epsilon) { MessageBox.Show("Position has not been specified."); return; } // See if there is an elevation (get 0.0 if not). double z = 0.0; if (elevationTextBox.Text.Length > 0) { if (!Double.TryParse(elevationTextBox.Text, out z)) { MessageBox.Show("Bad elevation"); elevationTextBox.Focus(); return; } } m_Position = new Position(x, y); m_Elevation = z; // Check whether the position is on screen. If not, issue a warning // message, and let the user cancel if desired. ISpatialDisplay display = EditingController.Current.ActiveDisplay; IWindow extent = display.Extent; if (extent == null || !extent.IsOverlap(m_Position)) { if (MessageBox.Show("Specified position does not overlap current draw window. Continue?", "Off screen", MessageBoxButtons.YesNo) == DialogResult.No) { return; } } // Are we doing an update? PointFeature pupt = this.UpdatePoint; // Confirm that there is no selectable point already at the specified position. Allow // a tolerance of 1cm on the ground. Only check in 2D. // The seatch should be restricted to those points that are currently visible. CadastralMapModel map = CadastralMapModel.Current; ILength tol = new Length(0.01); PointFeature close = (PointFeature)map.QueryClosest(m_Position, tol, SpatialType.Point); if (close != null) { // Get the ground distance between the existing point & the new one. double dist = Geom.Distance(m_Position, close); // Confirm if the points are coincident. Unless we're doing an update, // and it's the one we're doing. if (pupt == null || !Object.ReferenceEquals(close, pupt)) { if (dist < Constants.TINY) { string msg = String.Format("Specified position coincides with existing point {0}. Continue?", close.FormattedKey); if (MessageBox.Show(msg, "Coincident point", MessageBoxButtons.YesNo) == DialogResult.No) { return; } } else { string msg = String.Format("Specified position is only {0:0.000} metres away from point {1}. Continue?", dist, close.FormattedKey); if (MessageBox.Show(msg, "Very near another point", MessageBoxButtons.YesNo) == DialogResult.No) { return; } } } } // If we're updating a 3D position, update ONLY the elevation // now. We must leave the planimetric change to NewPointUI, // since it is in charge of controlling rollforward. if (pupt != null) { // For the time being, we do not provide the ability to change // a 2D location into a 3D one. Would need to modify the location, // thereby changing its address (or possibly create a duplicate // location in XY, although that could cause problems elsewhere). if (m_Elevation > Constants.TINY && !(pupt is IEditPosition3D)) { MessageBox.Show("Cannot convert a 2D point into 3D"); return; } // The point MUST be associated with a creating operation (either // a eNewPoint or a GetControl operation). Operation creator = (Operation)pupt.Creator; if (creator == null) { MessageBox.Show("Point cannot be updated because it has no associated edit."); return; } if (!(creator.EditId == EditingActionId.NewPoint || creator.EditId == EditingActionId.GetControl)) { MessageBox.Show("Unexpected editing operation"); return; } // Define new elevation if we have a 3D location. if (m_Elevation > Constants.TINY) { IEditPosition3D p3D = (pupt as IEditPosition3D); if (p3D == null) { MessageBox.Show("Unable to assign elevation"); } else { p3D.Z = m_Elevation; } } } m_Cmd.DialFinish(this); }