/// <summary> /// Handler for changes in the active measurer's geometry /// </summary> /// <param name="sender">The sender of the changed geometry</param> /// <param name="geometry">The new geometry</param> void MeasurerFeatureGeometryChanged(LiteMapMeasurerBase sender, System.Collections.Generic.List <FrameworkElement> geometry) { if (_interactionLayer != null) { _interactionLayer.Clear(); foreach (var element in geometry) { _interactionLayer.Add(element); } } }
internal void RecalculateCurvesAndAnnotations() { // Display the Along-side segment text (in direction of elements) double displayAlongSideTextMinDistance = CSUnitsForPixels(40); double displayTotalTextMinDistance = CSUnitsForPixels(60); double totalAlongLengthInMeters = 0.0; // The offset in pixels above the lines double offsetPixelsInCSUnits = CSUnitsForPixels(2); double totalTextOffsetPixelsInCSUnits = CSUnitsForPixels(15); _geometry.Clear(); for (int nr = 0; nr < _coordinates.Count - 1; nr++) { var isLast = nr >= _coordinates.Count - 2; var style = _isFinalized || !isLast ? _lineStyle : _grayLineStyle; var fromCoordinate = _coordinates[nr]; var toCoordinate = _coordinates[nr + 1]; var line = new Line { X1 = fromCoordinate.X, Y1 = fromCoordinate.Y, X2 = toCoordinate.X, Y2 = toCoordinate.Y, Stroke = style }; _geometry.Add(line); var alongLengthInCSUnits = fromCoordinate.DistanceTo(toCoordinate); //Código genera las distancias var alongLengthInMeters = LiteMapMeasurerBase.LengthInMeters(CoordinateSystem, Transform, fromCoordinate, toCoordinate); totalAlongLengthInMeters += alongLengthInMeters; if (alongLengthInCSUnits > displayAlongSideTextMinDistance) { //No son necesarias las distancias /* * var baseToIntermediateCoordinate = fromCoordinate.Middle(toCoordinate); * double baseToIntermediateCoordinateAngle = MathSE.NormalizedAngle(fromCoordinate.AngleTo(toCoordinate)); * * //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); * * * _geometry.Add(AnnotationFor(this.CoordinateSystem, baseToIntermediateCoordinate, baseToIntermediateCoordinateAngle, _segmentAnnotationStyle, 9, alongLengthInMeters, alignment, 15)); * * * //Este código genera los totales de la linea, se comento por que no se requiere * if (alongLengthInCSUnits > displayTotalTextMinDistance) * { * * // Now do the total Length at the coordinates themselves (but within the loop, so only when length of previous is long enough) * if (isLast && !toCoordinate.Equals(_coordinates[0])) * { * // If this is the last coordinate; just place the thingie at a decent offset * var direction = fromCoordinate.AngleTo(toCoordinate); * var position = Coordinate.NewAtDistanceAngleFrom(toCoordinate, totalTextOffsetPixelsInCSUnits, direction); * * _geometry.Add(AnnotationFor(this.CoordinateSystem, position, 0.0, _totalAnnotationStyle, 9, totalAlongLengthInMeters, alignment, 0)); * } * else * { * // Not the last coordinate - so we need to calculate a decent position for the coordinate * // at the intersection of the two segments it is placed between * var nextCoordinate = isLast ? _coordinates[1] : _coordinates[nr + 2]; * * // Only place the lot, when the next coordinate is suffiently away as well * var alongLengthNextInCSUnits = toCoordinate.DistanceTo(nextCoordinate); * if (alongLengthNextInCSUnits > displayTotalTextMinDistance) * { * var angleBetween = (fromCoordinate - toCoordinate).AngleWith(nextCoordinate - toCoordinate); * int extra = 25; * // Make sure we get the right direction * if (nextCoordinate.SideOf(fromCoordinate, toCoordinate) == GeometrySide.Left) * { * angleBetween = -angleBetween; * extra = 0; * } * * var direction = fromCoordinate.AngleTo(toCoordinate) + (angleBetween / 2.0); * var position = Coordinate.NewAtDistanceAngleFrom(toCoordinate, totalTextOffsetPixelsInCSUnits, direction); * * _geometry.Add(AnnotationFor(this.CoordinateSystem, position, 0.0, _totalAnnotationStyle, 9, totalAlongLengthInMeters, alignment, extra)); * } * } * }*/ } } // For-loop with coords if (_coordinates.Count > 2) { // We could display the area of the measurer } }
internal void RecalculateCurvesAndAnnotations() { // Display the Along-side segment text (in direction of elements) double displayAlongSideTextMinDistance = CSUnitsForPixels(40); double displayTotalTextMinDistance = CSUnitsForPixels(60); double totalAlongLengthInMeters = 0.0; // The offset in pixels above the lines double offsetPixelsInCSUnits = CSUnitsForPixels(2); double totalTextOffsetPixelsInCSUnits = CSUnitsForPixels(15); _geometry.Clear(); for (int nr = 0; nr < _coordinates.Count - 1; nr++) { var isLast = nr >= _coordinates.Count - 2; var style = _isFinalized || !isLast ? _lineStyle : _grayLineStyle; var fromCoordinate = _coordinates[nr]; var toCoordinate = _coordinates[nr + 1]; var line = new Line { X1 = fromCoordinate.X, Y1 = fromCoordinate.Y, X2 = toCoordinate.X, Y2 = toCoordinate.Y, Stroke = style }; _geometry.Add(line); var alongLengthInCSUnits = fromCoordinate.DistanceTo(toCoordinate); var alongLengthInMeters = LiteMapMeasurerBase.LengthInMeters(CoordinateSystem, Transform, fromCoordinate, toCoordinate); totalAlongLengthInMeters += alongLengthInMeters; if (alongLengthInCSUnits > displayAlongSideTextMinDistance) { var baseToIntermediateCoordinate = fromCoordinate.Middle(toCoordinate); double baseToIntermediateCoordinateAngle = MathSE.NormalizedAngle(fromCoordinate.AngleTo(toCoordinate)); //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); _geometry.Add(AnnotationForLength(this.CoordinateSystem, baseToIntermediateCoordinate, baseToIntermediateCoordinateAngle, _segmentAnnotationStyle, 9, alongLengthInMeters, alignment, 15)); if (alongLengthInCSUnits > displayTotalTextMinDistance) { // Now do the total Length at the coordinates themselves (but within the loop, so only when length of previous is long enough) if (isLast && !toCoordinate.Equals(_coordinates[0])) { // If this is the last coordinate; just place the thingie at a decent offset var direction = fromCoordinate.AngleTo(toCoordinate); var position = Coordinate.NewAtDistanceAngleFrom(toCoordinate, totalTextOffsetPixelsInCSUnits, direction); _geometry.Add(AnnotationForLength(this.CoordinateSystem, position, 0.0, _totalAnnotationStyle, 9, totalAlongLengthInMeters, alignment, 0)); } else { // Not the last coordinate - so we need to calculate a decent position for the coordinate // at the intersection of the two segments it is placed between var nextCoordinate = isLast ? _coordinates[1] : _coordinates[nr + 2]; // Only place the lot, when the next coordinate is suffiently away as well var alongLengthNextInCSUnits = toCoordinate.DistanceTo(nextCoordinate); if (alongLengthNextInCSUnits > displayTotalTextMinDistance) { var angleBetween = (fromCoordinate - toCoordinate).AngleWith(nextCoordinate - toCoordinate); int extra = 25; // Make sure we get the right direction if (nextCoordinate.SideOf(fromCoordinate, toCoordinate) == GeometrySide.Left) { angleBetween = -angleBetween; extra = 0; } var direction = fromCoordinate.AngleTo(toCoordinate) + (angleBetween / 2.0); var position = Coordinate.NewAtDistanceAngleFrom(toCoordinate, totalTextOffsetPixelsInCSUnits, direction); _geometry.Add(AnnotationForLength(this.CoordinateSystem, position, 0.0, _totalAnnotationStyle, 9, totalAlongLengthInMeters, alignment, extra)); } } } } } // For-loop with coords if (_coordinates.Count > 2) { // We could display the area of the measurer var closedRing = CreateClosedRing(this.CoordinateSystem, _coordinates); var area = CalculateAreaContribution(closedRing); if (area > 0) { _geometry.Add(AnnotationForArea(this.CoordinateSystem, closedRing.CenterCoordinate(PolygonCentreCoordinateMode.CentreOfEnvelope), _areaAnnotationStyle, 9, area)); } } }
/// <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 } } }