/// <summary> /// Renders the geometry for the spans along a leg. /// </summary> /// <param name="display">The display to draw to</param> /// <param name="spans">Information about each observed span</param> /// <param name="sections">The geometry that corresponds to each span</param> void DrawSpans(ISpatialDisplay display, SpanInfo[] spans, ILineGeometry[] sections) { Debug.Assert(spans.Length == sections.Length); IDrawStyle solidStyle = EditingController.Current.Style(Color.Magenta); IDrawStyle dottedStyle = new DottedStyle(Color.Magenta); for (int i = 0; i < spans.Length; i++) { ILineGeometry geom = sections[i]; IDrawStyle style = (spans[i].HasLine ? solidStyle : dottedStyle); if (geom is IClockwiseCircularArcGeometry) { style.Render(display, (IClockwiseCircularArcGeometry)geom); } else { style.Render(display, new IPosition[] { geom.Start, geom.End }); } if (spans[i].HasEndPoint) { solidStyle.Render(display, geom.End); } } }
/// <summary> /// Checks whether any intersections occur at positions that do not coincide /// with the end points of a line. /// </summary> /// <param name="line">The line to check. This should be the same line that /// was supplied to the <c>IntersectionFinder</c> constructor that created THIS results /// object (doing otherwise doesn't make any sense).</param> /// <returns>TRUE if any intersection does not coincide with the end points /// of the specified line.</returns> internal bool IsSplitOn(ILineGeometry line) { // Get the locations of the line end points. IPointGeometry start = line.Start; IPointGeometry end = line.End; // Go through each intersection, looking for one that does // not correspond to the line ends. foreach (IntersectionData d in m_Data) { IPointGeometry loc1 = new PointGeometry(d.P1); if (!start.IsCoincident(loc1) && !end.IsCoincident(loc1)) { return(true); } if (d.IsGraze) { /* * Huh? This was the original, but it always ended up returning true. * * IPointGeometry loc2 = PointGeometry.New(d.P2); * if (!start.IsCoincident(loc2) && !end.IsCoincident(loc2)) * return true; * * return true; */ return(true); } } return(false); }
/// <summary> /// Obtains the geometry for spans along this leg. /// </summary> /// <param name="pos">The position for the start of the leg. /// <param name="bearing">The bearing of the leg.</param> /// <param name="sfac">Scale factor to apply to distances.</param> /// <param name="spans">Information for the spans coinciding with this leg.</param> /// <returns>The sections along this leg</returns> internal override ILineGeometry[] GetSpanSections(IPosition pos, double bearing, double sfac, SpanInfo[] spans) { var result = new ILineGeometry[spans.Length]; // A leg with just one span, but no observed distance is due to the fact that the Leg constructor // that accepts a span count will always produce an array with at least one span (this covers cul-de-sacs // defined only with a central angle). May be better to handle it there. if (spans.Length == 1 && spans[0].ObservedDistance == null) { result[0] = new LineSegmentGeometry(pos, pos); return(result); } double sinBearing = Math.Sin(bearing); double cosBearing = Math.Cos(bearing); IPosition sPos = pos; IPosition ePos = null; double edist = 0.0; for (int i = 0; i < result.Length; i++, sPos = ePos) { edist += (spans[i].ObservedDistance.Meters * sfac); ePos = new Position(pos.X + (edist * sinBearing), pos.Y + (edist * cosBearing)); result[i] = new LineSegmentGeometry(sPos, ePos); } return(result); }
/// <summary> /// Does any painting that this dialog does. /// </summary> /// <param name="display">The display to draw to</param> internal void Render(ISpatialDisplay display) { // Draw the original path (in pale gray) IDrawStyle gray = new DrawStyle(Color.LightGray); m_pop.Render(display, gray, true); // Draw the current path (in magenta). PathInfo p = new PathInfo(m_pop.StartPoint, m_pop.EndPoint, GetLegs()); p.Render(display); // Highlight the currently selected line. int index = distancesListBox.SelectedIndex; if (index >= 0 && index < m_FaceSections.Length) { IDrawStyle style = new HighlightStyle(); ILineGeometry geom = m_FaceSections[index]; if (geom is IClockwiseCircularArcGeometry) { style.Render(display, (IClockwiseCircularArcGeometry)geom); } else { style.Render(display, new IPosition[] { geom.Start, geom.End }); } } }
/// <summary> /// Obtains the geometry for spans along an alternate face attached to this leg. /// </summary> /// <param name="legStart">The position for the start of the leg. /// <param name="legEnd">The position for the end of the leg.</param> /// <param name="spans">Information for the spans coinciding with this leg.</param> /// <returns>The sections along this leg</returns> internal override ILineGeometry[] GetSpanSections(IPosition legStart, IPosition legEnd, SpanInfo[] spans) { var result = new ILineGeometry[spans.Length]; Debug.Assert(AlternateFace != null); // Define the arc that corresponds to the complete leg (the circle should have been // already defined when we processed the primary face_. Debug.Assert(Circle != null); var arc = new CircularArcGeometry(Circle, legStart, legEnd, m_Metrics.IsClockwise); // Handle case where the leg is a cul-de-sac with no observed spans on the alternate face if (spans.Length == 1 && spans[0].ObservedDistance == null) { result[0] = arc; return(result); } // Get the required arc length (in meters on the ground) double len = arc.Length.Meters; // Get the observed arc length (in meters on the ground) double obs = AlternateFace.GetTotal(); // Get the adjustment factor for stretching-compressing the observed distances. double factor = len / obs; // Define start of first arc. IPosition sPos = legStart; IPosition ePos = null; // Haven't got anywhere yet. double totobs = 0.0; // Figure out the location of each span for (int i = 0; i < result.Length; i++, sPos = ePos) { if (i == result.Length - 1) { ePos = legEnd; } else { // Add on the unscaled distance totobs += spans[i].ObservedDistance.Meters; // Scale to the required length for the overall leg double elen = totobs * factor; // Define the end position. arc.GetPosition(new Length(elen), out ePos); } result[i] = new CircularArcGeometry(Circle, sPos, ePos, m_Metrics.IsClockwise); } return(result); }
/// <summary> /// Returns the context code for a grazing intersection with a line. /// </summary> /// <param name="loc1">The 1st intersection.</param> /// <param name="loc2">The 2nd intersection.</param> /// <param name="line">The line the context code is for.</param> /// <returns>The context code.</returns> static IntersectionType GetContext(IPointGeometry loc1, IPointGeometry loc2, ILineGeometry line) { // Get the context of the start and end of the graze. IntersectionType context1 = GetContext(loc1, line); IntersectionType context2 = GetContext(loc2, line); if (context1 == IntersectionType.TouchOther) { if (context2 == IntersectionType.TouchStart) { return(IntersectionType.GrazeStart); } if (context2 == IntersectionType.TouchOther) { return(IntersectionType.GrazeOther); } return(IntersectionType.GrazeEnd); } else if (context1 == IntersectionType.TouchStart) { if (context2 == IntersectionType.TouchStart) { return(IntersectionType.GrazeTotal); } if (context2 == IntersectionType.TouchOther) { return(IntersectionType.GrazeStart); } return(IntersectionType.GrazeTotal); } // context1 == IntersectionType.TounchEnd if (context2 == IntersectionType.TouchStart) { return(IntersectionType.GrazeTotal); } if (context2 == IntersectionType.TouchOther) { return(IntersectionType.GrazeEnd); } return(IntersectionType.GrazeTotal); }
/// <summary> /// Marks intersection data with flags that signify the relationship of these /// intersection results to the position of a specific line (presumably the /// line that caused the generation of these results). /// </summary> /// <param name="line">The line to compare with.</param> /// <returns>TRUE if any context settings were made. It will be FALSE if there /// are no intersections, or these results do not refer to a line.</returns> internal bool SetContext(ILineGeometry line) { // Return if there are no intersections. if (m_Data == null || m_Data.Count == 0) { return(false); } // Go through each intersected object. For those that are // lines, figure out the relationship to the supplied line. foreach (IntersectionData d in m_Data) { d.SetContext(m_IntersectedObject.LineGeometry, line); } return(true); }
/// <summary> /// Define the relationship that this intersection has to a pair of lines. /// </summary> /// <param name="line1">The 1st line.</param> /// <param name="line2">The 2nd line.</param> internal void SetContext(ILineGeometry line1, ILineGeometry line2) { m_Context1 = 0; m_Context2 = 0; if (this.IsGraze) { IPointGeometry loc1 = new PointGeometry(m_X1); IPointGeometry loc2 = new PointGeometry(m_X2); m_Context1 = GetContext(loc1, loc2, line1); m_Context2 = GetContext(loc1, loc2, line2); } else { IPointGeometry loc = new PointGeometry(m_X1); m_Context1 = GetContext(loc, line1); m_Context2 = GetContext(loc, line2); } }
/// <summary> /// Returns the context code for a simple intersection with a line. /// </summary> /// <param name="loc">The location of the intersection.</param> /// <param name="line">The line to compare with.</param> /// <returns>The context code.</returns> static IntersectionType GetContext(IPointGeometry loc, ILineGeometry line) { IntersectionType context = 0; if (loc.IsCoincident(line.Start)) { context |= IntersectionType.TouchStart; } if (loc.IsCoincident(line.End)) { context |= IntersectionType.TouchEnd; } if (context == 0) { context = IntersectionType.TouchOther; } return(context); }
/// <summary> /// Obtains the geometry for spans along this leg. /// </summary> /// <param name="bc">The position for the start of the leg. /// <param name="bcBearing">The bearing on entry into the leg.</param> /// <param name="sfac">Scale factor to apply to distances.</param> /// <param name="spans">Information for the spans coinciding with this leg.</param> /// <returns>The sections along this leg</returns> internal override ILineGeometry[] GetSpanSections(IPosition bc, double bcBearing, double sfac, SpanInfo[] spans) { // Can't do anything if the leg radius isn't defined if (m_Metrics.ObservedRadius == null) throw new InvalidOperationException("Cannot create sections for circular leg with undefined radius"); var result = new ILineGeometry[spans.Length]; // Use supplied stuff to derive info on the center and EC. IPosition center; IPosition ec; double bearingToBC; double ecBearing; GetPositions(bc, bcBearing, sfac, out center, out bearingToBC, out ec, out ecBearing); // Define the underlying circle ICircleGeometry circle = new CircleGeometry(PointGeometry.Create(center), BasicGeom.Distance(center, bc)); // Handle case where the leg is a cul-de-sac with no observed spans if (spans.Length == 1 && spans[0].ObservedDistance == null) { result[0] = new CircularArcGeometry(circle, bc, ec, m_Metrics.IsClockwise); return result; } /// Initialize scaling factor for distances in cul-de-sacs (ratio of the length calculated from /// the CA & Radius, versus the observed distances that were actually specified). For curves that /// are not cul-de-sacs, this will be 1.0 double culFactor = 1.0; if (m_Metrics.IsCulDeSac) { double obsv = PrimaryFace.GetTotal(); if (obsv > MathConstants.TINY) culFactor = Length.Meters / obsv; } IPosition sPos = bc; IPosition ePos = null; bool isClockwise = m_Metrics.IsClockwise; double radius = RadiusInMeters; double edist = 0.0; for (int i = 0; i < result.Length; i++, sPos = ePos) { // Add on the unscaled distance edist += spans[i].ObservedDistance.Meters; // Get the angle subtended at the center of the circle. We use // unscaled values here, since the scale factors would cancel out. // However, we DO apply any cul-de-sac scaling factor, to account // for the fact that the distance may be inconsistent with the // curve length derived from the CA and radius. For example, it // is possible that the calculated curve length=200, although the // total of the observed spans is somehow only 100. In that case, // if the supplied distance is 50, we actually want to use a // value of 50 * (200/100) = 100. double angle = (edist * culFactor) / radius; // Get the bearing of the point with respect to the center of the circle. double bearing; if (isClockwise) bearing = bearingToBC + angle; else bearing = bearingToBC - angle; // Calculate the position using the scaled radius. ePos = Geom.Polar(center, bearing, radius * sfac); result[i] = new CircularArcGeometry(circle, sPos, ePos, isClockwise); } return result; }
/// <summary> /// Obtains the geometry for spans along this leg. /// </summary> /// <param name="bc">The position for the start of the leg. /// <param name="bcBearing">The bearing on entry into the leg.</param> /// <param name="sfac">Scale factor to apply to distances.</param> /// <param name="spans">Information for the spans coinciding with this leg.</param> /// <returns>The sections along this leg</returns> internal override ILineGeometry[] GetSpanSections(IPosition bc, double bcBearing, double sfac, SpanInfo[] spans) { // Can't do anything if the leg radius isn't defined if (m_Metrics.ObservedRadius == null) { throw new InvalidOperationException("Cannot create sections for circular leg with undefined radius"); } var result = new ILineGeometry[spans.Length]; // Use supplied stuff to derive info on the center and EC. IPosition center; IPosition ec; double bearingToBC; double ecBearing; GetPositions(bc, bcBearing, sfac, out center, out bearingToBC, out ec, out ecBearing); // Define the underlying circle ICircleGeometry circle = new CircleGeometry(PointGeometry.Create(center), BasicGeom.Distance(center, bc)); // Handle case where the leg is a cul-de-sac with no observed spans if (spans.Length == 1 && spans[0].ObservedDistance == null) { result[0] = new CircularArcGeometry(circle, bc, ec, m_Metrics.IsClockwise); return(result); } /// Initialize scaling factor for distances in cul-de-sacs (ratio of the length calculated from /// the CA & Radius, versus the observed distances that were actually specified). For curves that /// are not cul-de-sacs, this will be 1.0 double culFactor = 1.0; if (m_Metrics.IsCulDeSac) { double obsv = PrimaryFace.GetTotal(); if (obsv > MathConstants.TINY) { culFactor = Length.Meters / obsv; } } IPosition sPos = bc; IPosition ePos = null; bool isClockwise = m_Metrics.IsClockwise; double radius = RadiusInMeters; double edist = 0.0; for (int i = 0; i < result.Length; i++, sPos = ePos) { // Add on the unscaled distance edist += spans[i].ObservedDistance.Meters; // Get the angle subtended at the center of the circle. We use // unscaled values here, since the scale factors would cancel out. // However, we DO apply any cul-de-sac scaling factor, to account // for the fact that the distance may be inconsistent with the // curve length derived from the CA and radius. For example, it // is possible that the calculated curve length=200, although the // total of the observed spans is somehow only 100. In that case, // if the supplied distance is 50, we actually want to use a // value of 50 * (200/100) = 100. double angle = (edist * culFactor) / radius; // Get the bearing of the point with respect to the center of the circle. double bearing; if (isClockwise) { bearing = bearingToBC + angle; } else { bearing = bearingToBC - angle; } // Calculate the position using the scaled radius. ePos = Geom.Polar(center, bearing, radius * sfac); result[i] = new CircularArcGeometry(circle, sPos, ePos, isClockwise); } return(result); }
/// <summary> /// Attaches geometry to the spans along a leg. /// </summary> /// <param name="ctx">The context in which the geometry is being defined.</param> /// <param name="spans">Information about each observed span</param> /// <param name="sections">The geometry that corresponds to each span</param> void AttachGeometry(EditingContext ctx, SpanInfo[] spans, ILineGeometry[] sections) { Debug.Assert(spans.Length == sections.Length); for (int i = 0; i < spans.Length; i++) { SpanInfo data = spans[i]; Feature feat = data.CreatedFeature; PointFeature endPoint = null; if (feat is PointFeature) endPoint = (PointFeature)feat; else if (feat is LineFeature) endPoint = (feat as LineFeature).EndPoint; if (endPoint != null && endPoint.PointGeometry == null) { PointGeometry pg = PointGeometry.Create(sections[i].End); endPoint.ApplyPointGeometry(ctx, pg); } } }
/// <summary> /// Obtains the geometry for spans along this leg. /// </summary> /// <param name="pos">The position for the start of the leg. /// <param name="bearing">The bearing of the leg.</param> /// <param name="sfac">Scale factor to apply to distances.</param> /// <param name="spans">Information for the spans coinciding with this leg.</param> /// <returns>The sections along this leg</returns> internal override ILineGeometry[] GetSpanSections(IPosition pos, double bearing, double sfac, SpanInfo[] spans) { var result = new ILineGeometry[spans.Length]; // A leg with just one span, but no observed distance is due to the fact that the Leg constructor // that accepts a span count will always produce an array with at least one span (this covers cul-de-sacs // defined only with a central angle). May be better to handle it there. if (spans.Length == 1 && spans[0].ObservedDistance == null) { result[0] = new LineSegmentGeometry(pos, pos); return result; } double sinBearing = Math.Sin(bearing); double cosBearing = Math.Cos(bearing); IPosition sPos = pos; IPosition ePos = null; double edist = 0.0; for (int i = 0; i < result.Length; i++, sPos=ePos) { edist += (spans[i].ObservedDistance.Meters * sfac); ePos = new Position(pos.X + (edist * sinBearing), pos.Y + (edist * cosBearing)); result[i] = new LineSegmentGeometry(sPos, ePos); } return result; }
/// <summary> /// Renders the geometry for the spans along a leg. /// </summary> /// <param name="display">The display to draw to</param> /// <param name="spans">Information about each observed span</param> /// <param name="sections">The geometry that corresponds to each span</param> void DrawSpans(ISpatialDisplay display, SpanInfo[] spans, ILineGeometry[] sections) { Debug.Assert(spans.Length == sections.Length); IDrawStyle solidStyle = EditingController.Current.Style(Color.Magenta); IDrawStyle dottedStyle = new DottedStyle(Color.Magenta); for (int i = 0; i < spans.Length; i++) { ILineGeometry geom = sections[i]; IDrawStyle style = (spans[i].HasLine ? solidStyle : dottedStyle); if (geom is IClockwiseCircularArcGeometry) style.Render(display, (IClockwiseCircularArcGeometry)geom); else style.Render(display, new IPosition[] { geom.Start, geom.End }); if (spans[i].HasEndPoint) solidStyle.Render(display, geom.End); } }
/// <summary> /// Checks whether any intersections occur at positions that do not coincide /// with the end points of a line. /// </summary> /// <param name="line">The line to check. This should be the same line that /// was supplied to the <c>IntersectionFinder</c> constructor that created THIS results /// object (doing otherwise doesn't make any sense).</param> /// <returns>TRUE if any intersection does not coincide with the end points /// of the specified line.</returns> internal bool IsSplitOn(ILineGeometry line) { // Get the locations of the line end points. IPointGeometry start = line.Start; IPointGeometry end = line.End; // Go through each intersection, looking for one that does // not correspond to the line ends. foreach (IntersectionData d in m_Data) { IPointGeometry loc1 = new PointGeometry(d.P1); if (!start.IsCoincident(loc1) && !end.IsCoincident(loc1)) return true; if (d.IsGraze) { /* * Huh? This was the original, but it always ended up returning true. * IPointGeometry loc2 = PointGeometry.New(d.P2); if (!start.IsCoincident(loc2) && !end.IsCoincident(loc2)) return true; return true; */ return true; } } return false; }
/// <summary> /// Marks intersection data with flags that signify the relationship of these /// intersection results to the position of a specific line (presumably the /// line that caused the generation of these results). /// </summary> /// <param name="line">The line to compare with.</param> /// <returns>TRUE if any context settings were made. It will be FALSE if there /// are no intersections, or these results do not refer to a line.</returns> internal bool SetContext(ILineGeometry line) { // Return if there are no intersections. if (m_Data==null || m_Data.Count==0) return false; // Go through each intersected object. For those that are // lines, figure out the relationship to the supplied line. foreach (IntersectionData d in m_Data) { d.SetContext(m_IntersectedObject.LineGeometry, line); } return true; }
/// <summary> /// Obtains the geometry for spans along an alternate face attached to this leg. /// </summary> /// <param name="legStart">The position for the start of the leg. /// <param name="legEnd">The position for the end of the leg.</param> /// <param name="spans">Information for the spans coinciding with this leg.</param> /// <returns>The sections along this leg</returns> internal override ILineGeometry[] GetSpanSections(IPosition legStart, IPosition legEnd, SpanInfo[] spans) { var result = new ILineGeometry[spans.Length]; Debug.Assert(AlternateFace != null); // Define the arc that corresponds to the complete leg (the circle should have been // already defined when we processed the primary face_. Debug.Assert(Circle != null); var arc = new CircularArcGeometry(Circle, legStart, legEnd, m_Metrics.IsClockwise); // Handle case where the leg is a cul-de-sac with no observed spans on the alternate face if (spans.Length == 1 && spans[0].ObservedDistance == null) { result[0] = arc; return result; } // Get the required arc length (in meters on the ground) double len = arc.Length.Meters; // Get the observed arc length (in meters on the ground) double obs = AlternateFace.GetTotal(); // Get the adjustment factor for stretching-compressing the observed distances. double factor = len / obs; // Define start of first arc. IPosition sPos = legStart; IPosition ePos = null; // Haven't got anywhere yet. double totobs = 0.0; // Figure out the location of each span for (int i = 0; i < result.Length; i++, sPos = ePos) { if (i == result.Length - 1) { ePos = legEnd; } else { // Add on the unscaled distance totobs += spans[i].ObservedDistance.Meters; // Scale to the required length for the overall leg double elen = totobs * factor; // Define the end position. arc.GetPosition(new Length(elen), out ePos); } result[i] = new CircularArcGeometry(Circle, sPos, ePos, m_Metrics.IsClockwise); } return result; }