Example #1
0
            /// <summary>
            /// Recalculate the output of the curves
            /// </summary>
            internal override void RecalculateCurvesAndAnnotations(bool hasMeasureElements)
            {
                // We only check for valid elements in case we are more away than so many pixels
                double checkValidMinDistance = CSUnitsForPixels(5);

                // Display the Along-side segment text (in direction of base), when more than so many pixels long
                double displayAlongSideTextMinDistance = CSUnitsForPixels(65);

                // Display the Cumulative text when the segment is longer than the specified pixels
                double displayAlongSideEndTextMinDistance = CSUnitsForPixels(100);

                // Display the orthogonal text when the ortho-length is more than the specified pixels
                double displayOrthogonalTextMinDistance = CSUnitsForPixels(65);

                // Display the Ortho Total when the Along-side Distance (the segment in base-direction)
                // is longer than the given length. For clarity to the end-user this could be set to the
                // same value as displaying the segment-length itself but can be done earlier if required.
                double displayOrthogonalEndTextMinAlongDistance = CSUnitsForPixels(50);

                // Keep Ortho-Total-MinOrth-Distance the same as the ortho-distance itself,
                // so total-ortho text does only appear in case the ortho text itself is displayed.
                // If not, the user might confuse this one with the ortho-value itself (since it is
                // displayed and the ortho-text maybe is not yet).
                double displayOrthogonalEndTextMinOrthogonalDistance = CSUnitsForPixels(65);

                // Display the points in case the length of the corresponding segment is longer than the
                // specified pixels
                double displayPointsMinDistance = CSUnitsForPixels(24);

                // Display the points in case the length of the corresponding segment is longer than the
                // specified pixels. This applies to drawing ortho-points in case the along-side segment
                // is longer than the specified pixels.
                double displayOtherPointsMinAlongDistance = CSUnitsForPixels(15);

                // The offset in pixels above the lines (for the segment and ortho texts, not the totals).
                double offsetPixelsInCSUnits = CSUnitsForPixels(2);

                // Initialize the output geometry
                Curves      = new List <Line>();
                Annotations = new List <FrameworkElement>();
                Points      = new List <System.Windows.Shapes.Polygon>();

                // Start by calculating the intermediate (intersection) point.
                CalculateIntermediate();

                // Setting up the along curve (the one going straight again and again)
                var alongCurve = new Curve(new LineString(CoordinateSystem, Start, Intermediate));
                var alongLine  = new Line {
                    X1 = Start.X, Y1 = Start.Y, X2 = Intermediate.X, Y2 = Intermediate.Y, Stroke = _measureLineStyle
                };
                var alongLengthInCSUnits = Start.DistanceTo(Intermediate);
                var alongLengthInMeters  = LiteMapMeasurerBase.LengthInMeters(CoordinateSystem, Transform, Start, Intermediate);

                // Setting up the orthogonal curve
                var orthogonalCurve = new Curve(new LineString(CoordinateSystem, Intermediate, End));
                var orthogonalLine  = new Line {
                    X1 = Intermediate.X, Y1 = Intermediate.Y, X2 = End.X, Y2 = End.Y, Stroke = _measureLineStyle
                };
                var orthogonalLengthInCSUnits = Intermediate.DistanceTo(End);
                var orthogonalLengthInMeters  = LiteMapMeasurerBase.LengthInMeters(CoordinateSystem, Transform, Intermediate, End);

                // Check whether we are Valid (not going in the wrong direction).
                // This applies not to the first point, that can be used to determine the direction, but applies
                // to subsequent points only.
                // We still do use the valid-flag for the first element though, just to indicate that we need to reverse the lot
                Valid = true;
                if (alongLengthInCSUnits > checkValidMinDistance && Math.Abs(Base.Angle - Start.AngleTo(Intermediate)) > 1)
                {
                    if (!First)
                    {
                        alongLine.Stroke      = _measureInvalidLineStyle;
                        orthogonalLine.Stroke = _measureInvalidLineStyle;
                    }
                    Valid = false;
                }

                // Add the curves to the output. These are the along-curve (in the base-line's direction) and the ortho-curve
                Curves.Add(alongLine);
                Curves.Add(orthogonalLine);

                // In case we are not valid do not draw the result, unless we are the first measure-element.
                // In that case we can act as any other, since the first element can be used to determine direction
                if (!Valid && !First)
                {
                    return;
                }

                // The point drawing (dimension endpoints)
                // We can choose to only draw points when all points are capable of being shown (direct and ortho)
                // This leads to a neater way of display the dimensions.
                bool drawPointsDirect = alongLengthInCSUnits > displayPointsMinDistance;
                bool drawPointsOrtho  = orthogonalLengthInCSUnits > displayPointsMinDistance && alongLengthInCSUnits > displayOtherPointsMinAlongDistance;
                bool drawPoints       = drawPointsDirect && drawPointsOrtho;

                // Draw the DimPoints on the direct line, either make dependent on
                // - drawPointsDirect (these can be drawn)
                // - drawPoints       (direct + ortho points can be drawn)
                if (drawPointsDirect)
                {
                    double ptAngle = Start.AngleTo(Intermediate);

                    Points.Add(PointPolygonFor(Start, ptAngle + MathSE.HalfPI, 10, _dimPointStyle));
                    Points.Add(PointPolygonFor(Intermediate, ptAngle - MathSE.HalfPI, 10, _dimPointStyle));
                }

                // Draw the DimPoints on the Orthogonal line, either make dependent on
                // - drawPointsOrtho (these can be drawn)
                // - drawPoints      (ortho + direct points can be drawn)
                if (drawPointsOrtho)
                {
                    double ptAngle2 = End.AngleTo(Intermediate);

                    Points.Add(PointPolygonFor(Intermediate, ptAngle2 - MathSE.HalfPI, 10, _dimPointStyle));
                    Points.Add(PointPolygonFor(End, ptAngle2 + MathSE.HalfPI, 10, _dimPointStyle));
                }

                // Draw the Text in the direct part (segment length)
                if (alongLengthInCSUnits > displayAlongSideTextMinDistance)
                {
                    var    baseToIntermediateCoordinate      = Start.Middle(Intermediate);
                    double baseToIntermediateCoordinateAngle = MathSE.NormalizedAngle(Start.AngleTo(Intermediate));

                    //TextAlignment alignment = TextAlignment.Bottom;
                    TextAlignment alignment = TextAlignment.Center;

                    if (baseToIntermediateCoordinateAngle > MathSE.HalfPI && baseToIntermediateCoordinateAngle < 3 * MathSE.HalfPI)
                    {
                        baseToIntermediateCoordinateAngle += MathSE.PI;
                    }

                    // Get the text slightly up (couple of pixels), to make sure it is drawn loose from the line
                    double upAngle = baseToIntermediateCoordinateAngle + MathSE.HalfPI;
                    baseToIntermediateCoordinate = Coordinate.NewAtDistanceAngleFrom(baseToIntermediateCoordinate, offsetPixelsInCSUnits, upAngle);

                    Annotations.Add(AnnotationForLength(this.CoordinateSystem, baseToIntermediateCoordinate, baseToIntermediateCoordinateAngle, _measureAnnotationStyle, 9, alongLengthInMeters, alignment, 15));
                }

                // Draw the orthogonal Text in the orthogonal part
                if (orthogonalLengthInCSUnits > displayOrthogonalTextMinDistance)
                {
                    var baseToIntermediateCoordinate      = Intermediate.Middle(End);
                    var baseToIntermediateCoordinateAngle = MathSE.NormalizedAngle(Intermediate.AngleTo(End));
                    //var alignment = TextAlignment.Bottom;
                    var alignment = TextAlignment.Center;

                    if (baseToIntermediateCoordinateAngle > MathSE.HalfPI && baseToIntermediateCoordinateAngle < 3 * MathSE.HalfPI)
                    {
                        baseToIntermediateCoordinateAngle += MathSE.PI;
                    }

                    double upAngle = baseToIntermediateCoordinateAngle + MathSE.HalfPI;
                    baseToIntermediateCoordinate = Coordinate.NewAtDistanceAngleFrom(baseToIntermediateCoordinate, offsetPixelsInCSUnits, upAngle);

                    Annotations.Add(AnnotationForLength(this.CoordinateSystem, baseToIntermediateCoordinate, baseToIntermediateCoordinateAngle, _measureAnnotationStyle, 9, orthogonalLengthInMeters, alignment, 15));
                }

                // Draw the segment End and Orthogonal End Texts
                // The total length will not be displayed for the first segment (same value)
                bool allowLengthTotalUnitsDisplay = !First && (alongLengthInCSUnits > displayAlongSideEndTextMinDistance);

                // The ortho length will be displayed in case
                // - the orthogonal value itself is displayed (to make sure the values are understood)
                // - it is the first segment or the length of the along-side is long enough (for the first segment, there is nothing 'in the way')
                bool allowOrthoTotalUnitsDisplay = orthogonalLengthInCSUnits > displayOrthogonalEndTextMinOrthogonalDistance && (alongLengthInCSUnits > displayOrthogonalEndTextMinAlongDistance || First);

                if (allowLengthTotalUnitsDisplay || allowOrthoTotalUnitsDisplay)
                {
                    // Get the text alignments, by checking in which sub-quadrants (divided in 8) each elements' lies
                    // Dependent on these directions, the most appropriate text-alignment will be picked.
                    // This kind of behavior should go with quadrant behavior in core. Should be a one-liner.
                    var alignments = new TextAlignment[]
                    {
                        TextAlignment.Left,
                        TextAlignment.Left,
                        TextAlignment.Center,
                        TextAlignment.Right,
                        TextAlignment.Right,
                        TextAlignment.Right,
                        TextAlignment.Center,
                        TextAlignment.Left
                    };

                    // Do total length, but not for the first dimension-line
                    var directAlignment = TextAlignment.Center;
                    var orthoAlignment  = TextAlignment.Center;

                    double angleToUse  = MathSE.NormalizedAngle(End.AngleTo(Intermediate));
                    double directAngle = MathSE.NormalizedAngle(angleToUse + (Math.PI / 8));
                    for (int nr = 0; nr < 8; nr++)
                    {
                        if (directAngle < ((nr + 1) * Math.PI) / 4)
                        {
                            directAlignment = alignments[nr];
                            orthoAlignment  = alignments[(nr + 4) % 8];
                            break;
                        }
                    }

                    // Get some extra space/distance from the linears and segment texts
                    double extraOrthoDistanceInCSUnits = CSUnitsForPixels(10);
                    if (allowLengthTotalUnitsDisplay)
                    {
                        // Total length
                        Curve allSegmentsCurve          = new Curve(CoordinateSystem, new LineString(CoordinateSystem, Base.End, Intermediate));
                        var   allSegmentsLengthInMeters = LiteMapMeasurerBase.LengthInMeters(CoordinateSystem, Transform, Base.End, Intermediate);

                        // Place the texts at intersections (cumulative totals at end of segments)
                        Coordinate alongTotalCoordinate = Coordinate.NewAtDistanceAngleFrom(Intermediate, extraOrthoDistanceInCSUnits, angleToUse);
                        // Annotations.Add(AnnotationFor(this.CoordinateSystem, alongTotalCoordinate, 0.0, _measureAnnotationStyle, 14, allSegmentsLengthInMeters, directAlignment));
                    }

                    if (allowOrthoTotalUnitsDisplay)
                    {
                        // Place the 'total' text at the end of each point that is actually dimensioned
                        var orthoTotalCoordinate = Coordinate.NewAtDistanceAngleFrom(End, extraOrthoDistanceInCSUnits, angleToUse + Math.PI);
                        var orthoTotalLength     = alongLengthInMeters + orthogonalLengthInMeters;

                        // No-op for now
                        // We could use this to display the orto total text
                    }
                }
            }