/// <summary> /// Gets the position that is a specific distance from the start of a circular arc. /// </summary> /// <param name="g">The geometry for the circular arc</param> /// <param name="distance">The distance from the start of the arc.</param> /// <param name="result">The position found</param> /// <returns>True if the distance is somewhere ON the arc. False if the distance /// was less than zero, or more than the arc length (in that case, the position /// found corresponds to the corresponding terminal point).</returns> public static bool GetPosition(ICircularArcGeometry g, ILength distance, out IPosition result) { // Allow 1 micron tolerance const double TOL = 0.000001; // Check for invalid distances. double d = distance.Meters; if (d < 0.0) { result = g.BC; return(false); } double clen = g.Length.Meters; // Arc length if (d > (clen + TOL)) { result = g.EC; return(false); } // Check for limiting values (if you don't do this, minute // roundoff at the BC & EC can lead to spurious locations). // (although it's possible to use TINY here, use 1 micron // instead, since we can't represent position any better // than that). if (d < TOL) { result = g.BC; return(true); } if (Math.Abs(d - clen) < TOL) { result = g.EC; return(true); } // Get the bearing of the BC ICircleGeometry circle = g.Circle; IPosition c = circle.Center; double radius = circle.Radius; double bearing = BasicGeom.BearingInRadians(c, g.BC); // Add the angle that subtends the required distance (or // subtract if the curve goes anti-clockwise). if (g.IsClockwise) { bearing += (d / radius); } else { bearing -= (d / radius); } // Figure out the required point from the new bearing. result = BasicGeom.Polar(c, bearing, radius); return(true); }
/// <summary> /// Obtains annotation for this line. /// </summary> /// <param name="dist">The observed distance (if any).</param> /// <param name="drawObserved">Draw observed distance? Specify <c>false</c> for /// actual distance.</param> /// <returns>The annotation (null if it cannot be obtained)</returns> Annotation GetAnnotation(Distance dist, bool drawObserved) { // @devnote This function may not be that hot for curves that // are complete circles. At the moment though, I can't see why // we'd be drawing a distance alongside a circle. // Get the length of the arc double len = this.Length.Meters; // Get the string to output. string distr = GetDistance(len, dist, drawObserved); if (distr == null) { return(null); } // Get the mid-point of this arc. IPosition mid; this.GetPosition(new Length(len * 0.5), out mid); // Get the bearing from the center to the midpoint. IPosition center = m_Circle.Center; double bearing = BasicGeom.BearingInRadians(center, mid); // Get the height of the text, in meters on the ground. double grheight = EditingController.Current.LineAnnotationStyle.Height; // We will offset by 20% of the height (give a bit of space // between the text and the line). //double offset = grheight * 0.2; // ...looks fine with no offset (there is a space, but it's for descenders // that aren't there since we're dealing just with numbers). double offset = 0.0; // Get the rotation of the text. double rotation = bearing - MathConstants.PI; // If the midpoint is above the circle centre, we get upside-down // text so rotate it the other way. If we don't switch the // rotation, we need to make an extra shift, because the text // is aligned along its baseline. // This depends on whether the annotation is on the default // side or not. // Not sure about the following... (c.f. revised handling in SegmentGeometry) /* * if (mid.Y > center.Y) * { * rotation += MathConstants.PI; * if (isFlipped) * offset = -0.9 * grheight; * } * else * { * if (isFlipped) * offset = -offset; * else * offset = 0.9 * grheight; // 1.0 * grheight is too much * } */ // ...try this instead if (mid.Y > center.Y) { rotation += MathConstants.PI; } else { offset = 1.3 * grheight; // push the text to the outer edge of the arc } if (dist != null && dist.IsAnnotationFlipped) { rotation += MathConstants.PI; // and may need to adjust offset... } // Project to the offset point. IPosition p = Geom.Polar(center, bearing, m_Circle.Radius + offset); Annotation result = new Annotation(distr, p, grheight, rotation); result.FontStyle = FontStyle.Italic; return(result); }
public static double GetStartBearingInRadians(ICircularArcGeometry g) { return(BasicGeom.BearingInRadians(g.Circle.Center, g.First)); }