Skip to content

Commit

Permalink
CNX-9445 arc gis precision check for acrs circles curves ellipse (#3428)
Browse files Browse the repository at this point in the history
* clean segment converters

* send densified curved segments using Map CRS precision

* receive circles without segmentation

* convert precision points to meters; use factoryCode for unit conversion to Speckle; add USfeet unit

* remove unused conversions

* fix

* remove line segment converter

* merge conflicts
  • Loading branch information
KatKatKateryna authored May 30, 2024
1 parent b12e7eb commit 9aa8249
Show file tree
Hide file tree
Showing 7 changed files with 87 additions and 189 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,7 @@ public List<CardSetting> GetSendSettings()
public async Task Send(string modelCardId)
{
//poc: dupe code between connectors
using IUnitOfWork<SendOperation<MapMember>> unitOfWork = _unitOfWorkFactory.Resolve<SendOperation<MapMember>>();
using var unitOfWork = _unitOfWorkFactory.Resolve<SendOperation<MapMember>>();
try
{
if (_store.GetModelById(modelCardId) is not SenderModelCard modelCard)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,31 +7,28 @@ namespace Speckle.Converters.ArcGIS3;

public class ArcGISToSpeckleUnitConverter : IHostToSpeckleUnitConverter<Unit>
{
private static readonly IReadOnlyDictionary<string, string> s_unitMapping = Create();
private readonly Dictionary<int, string> _unitMapping = new();

private static IReadOnlyDictionary<string, string> Create()
private ArcGISToSpeckleUnitConverter()
{
var dict = new Dictionary<string, string>();
// POC: we should have a unit test to confirm these are as expected and don't change
//_unitMapping[LinearUnit.] = Units.Meters;
dict[LinearUnit.Millimeters.Name] = Units.Millimeters;
dict[LinearUnit.Centimeters.Name] = Units.Centimeters;
dict[LinearUnit.Meters.Name] = Units.Meters;
dict[LinearUnit.Kilometers.Name] = Units.Kilometers;
dict[LinearUnit.Inches.Name] = Units.Inches;
dict[LinearUnit.Feet.Name] = Units.Feet;
dict[LinearUnit.Yards.Name] = Units.Yards;
dict[LinearUnit.Miles.Name] = Units.Miles;
//_unitMapping[LinearUnit.Decimeters] = Units.;
//_unitMapping[LinearUnit.NauticalMiles] = Units.;
return dict;
// more units: https://pro.arcgis.com/en/pro-app/latest/sdk/api-reference/topic8349.html
_unitMapping[LinearUnit.Millimeters.FactoryCode] = Units.Millimeters;
_unitMapping[LinearUnit.Centimeters.FactoryCode] = Units.Centimeters;
_unitMapping[LinearUnit.Meters.FactoryCode] = Units.Meters;
_unitMapping[LinearUnit.Kilometers.FactoryCode] = Units.Kilometers;
_unitMapping[LinearUnit.Inches.FactoryCode] = Units.Inches;
_unitMapping[LinearUnit.Feet.FactoryCode] = Units.Feet;
_unitMapping[LinearUnit.Yards.FactoryCode] = Units.Yards;
_unitMapping[LinearUnit.Miles.FactoryCode] = Units.Miles;
_unitMapping[9003] = Units.USFeet;
}

public string ConvertOrThrow(Unit hostUnit)
{
var linearUnit = LinearUnit.CreateLinearUnit(hostUnit.Wkt).Name;
int linearUnit = LinearUnit.CreateLinearUnit(hostUnit.Wkt).FactoryCode;

if (s_unitMapping.TryGetValue(linearUnit, out string? value))
if (_unitMapping.TryGetValue(linearUnit, out string? value))
{
return value;
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,21 +1,46 @@
using ArcGIS.Desktop.Mapping;
using Speckle.Converters.Common;
using Speckle.Converters.Common.Objects;

namespace Speckle.Converters.ArcGIS3.Features;

public class PolyineFeatureToSpeckleConverter : ITypedConverter<ACG.Polyline, IReadOnlyList<SOG.Polyline>>
{
private readonly ITypedConverter<ACG.ReadOnlySegmentCollection, SOG.Polyline> _segmentConverter;
private readonly IConversionContextStack<Map, ACG.Unit> _contextStack;

public PolyineFeatureToSpeckleConverter(ITypedConverter<ACG.ReadOnlySegmentCollection, SOG.Polyline> segmentConverter)
public PolyineFeatureToSpeckleConverter(
ITypedConverter<ACG.ReadOnlySegmentCollection, SOG.Polyline> segmentConverter,
IConversionContextStack<Map, ACG.Unit> contextStack
)
{
_segmentConverter = segmentConverter;
_contextStack = contextStack;
}

public IReadOnlyList<SOG.Polyline> Convert(ACG.Polyline target)
{
// https://pro.arcgis.com/en/pro-app/latest/sdk/api-reference/topic8480.html
List<SOG.Polyline> polylineList = new();
foreach (var segmentCollection in target.Parts)
ACG.Polyline polylineToConvert = target;

// segmentize the polylines with curves using precision value of the Map's Spatial Reference
if (target.HasCurves is true)
{
double tolerance = _contextStack.Current.Document.SpatialReference.XYTolerance;
double conversionFactorToMeter = _contextStack.Current.Document.SpatialReference.Unit.ConversionFactor;
var densifiedPolyline = ACG.GeometryEngine.Instance.DensifyByDeviation(
target,
tolerance * conversionFactorToMeter
);
polylineToConvert = (ACG.Polyline)densifiedPolyline;
if (densifiedPolyline == null)
{
throw new ArgumentException("Polyline densification failed");
}
}

foreach (var segmentCollection in polylineToConvert.Parts)
{
polylineList.Add(_segmentConverter.Convert(segmentCollection));
}
Expand Down

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using ArcGIS.Desktop.Mapping;
using Speckle.Converters.Common;
using Speckle.Converters.Common.Objects;
using Speckle.Core.Kits;
using Speckle.Core.Models;

namespace Speckle.Converters.ArcGIS3.Geometry.ISpeckleObjectToHost;
Expand All @@ -8,45 +10,38 @@ namespace Speckle.Converters.ArcGIS3.Geometry.ISpeckleObjectToHost;
public class CircleToHostConverter : IToHostTopLevelConverter, ITypedConverter<SOG.Circle, ACG.Polyline>
{
private readonly ITypedConverter<SOG.Point, ACG.MapPoint> _pointConverter;
private readonly IConversionContextStack<Map, ACG.Unit> _contextStack;

public CircleToHostConverter(ITypedConverter<SOG.Point, ACG.MapPoint> pointConverter)
public CircleToHostConverter(
ITypedConverter<SOG.Point, ACG.MapPoint> pointConverter,
IConversionContextStack<Map, ACG.Unit> contextStack
)
{
_pointConverter = pointConverter;
_contextStack = contextStack;
}

public object Convert(Base target) => Convert((SOG.Circle)target);

public ACG.Polyline Convert(SOG.Circle target)
{
// Determine the number of vertices to create along the cirlce
int numVertices = Math.Max((int)target.length, 100); // Determine based on desired segment length or other criteria
List<SOG.Point> pointsOriginal = new();

if (target.radius == null)
{
throw new SpeckleConversionException("Conversion failed: Circle doesn't have a radius");
}

// Calculate the vertices along the arc
for (int i = 0; i <= numVertices; i++)
{
// Calculate the point along the arc
double angle = 2 * Math.PI * (i / (double)numVertices);
SOG.Point pointOnCircle =
new(
target.plane.origin.x + (double)target.radius * Math.Cos(angle),
target.plane.origin.y + (double)target.radius * Math.Sin(angle),
target.plane.origin.z
);

pointsOriginal.Add(pointOnCircle);
}
if (pointsOriginal[0] != pointsOriginal[^1])
{
pointsOriginal.Add(pointsOriginal[0]);
}
// create a native ArcGIS circle segment
ACG.MapPoint centerPt = _pointConverter.Convert(target.plane.origin);

double scaleFactor = Units.GetConversionFactor(target.units, _contextStack.Current.SpeckleUnits);
ACG.EllipticArcSegment circleSegment = ACG.EllipticArcBuilderEx.CreateCircle(
new ACG.Coordinate2D(centerPt.X, centerPt.Y),
(double)target.radius * scaleFactor,
ACG.ArcOrientation.ArcClockwise
);

var circlePolyline = new ACG.PolylineBuilderEx(circleSegment, ACG.AttributeFlags.HasZ).ToGeometry();

var points = pointsOriginal.Select(x => _pointConverter.Convert(x));
return new ACG.PolylineBuilderEx(points, ACG.AttributeFlags.HasZ).ToGeometry();
return circlePolyline;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,14 @@ public class SegmentCollectionToSpeckleConverter : ITypedConverter<ACG.ReadOnlyS
{
private readonly IConversionContextStack<Map, ACG.Unit> _contextStack;
private readonly ITypedConverter<ACG.MapPoint, SOG.Point> _pointConverter;
private readonly ITypedConverter<ACG.EllipticArcSegment, SOG.Polyline> _arcConverter;
private readonly ITypedConverter<ACG.CubicBezierSegment, SOG.Polyline> _bezierConverter;

public SegmentCollectionToSpeckleConverter(
IConversionContextStack<Map, ACG.Unit> contextStack,
ITypedConverter<ACG.MapPoint, SOG.Point> pointConverter,
ITypedConverter<ACG.EllipticArcSegment, SOG.Polyline> arcConverter,
ITypedConverter<ACG.CubicBezierSegment, SOG.Polyline> bezierConverter
ITypedConverter<ACG.MapPoint, SOG.Point> pointConverter
)
{
_contextStack = contextStack;
_pointConverter = pointConverter;
_arcConverter = arcConverter;
_bezierConverter = bezierConverter;
}

public SOG.Polyline Convert(ACG.ReadOnlySegmentCollection target)
Expand All @@ -34,27 +28,39 @@ public SOG.Polyline Convert(ACG.ReadOnlySegmentCollection target)
{
len += segment.Length;

// do something specific per segment type
// specific conversion per segment type
switch (segment.SegmentType)
{
case ACG.SegmentType.Line:
points.Add(_pointConverter.Convert(segment.StartPoint));
points.Add(_pointConverter.Convert(segment.EndPoint));
break;
case ACG.SegmentType.Bezier:
var segmentBezier = (ACG.CubicBezierSegment)segment;
points.AddRange(_bezierConverter.Convert(segmentBezier).GetPoints());
break;
case ACG.SegmentType.EllipticArc:
var segmentElliptic = (ACG.EllipticArcSegment)segment;
points.AddRange(_arcConverter.Convert(segmentElliptic).GetPoints());
points = AddPtsToPolylinePts(
points,
new List<SOG.Point>()
{
_pointConverter.Convert(segment.StartPoint),
_pointConverter.Convert(segment.EndPoint)
}
);
break;
default:
throw new SpeckleConversionException($"Segment of type '{segment.SegmentType}' cannot be converted");
}
}
// var box = _boxConverter.Convert(target.Extent);
SOG.Polyline polyline =
new(points.SelectMany(pt => new[] { pt.x, pt.y, pt.z }).ToList(), _contextStack.Current.SpeckleUnits) { };

return polyline;
}

private List<SOG.Point> AddPtsToPolylinePts(List<SOG.Point> points, List<SOG.Point> newSegmentPts)
{
if (points.Count == 0 || points[^1] != newSegmentPts[0])
{
points.AddRange(newSegmentPts);
}
else
{
points.AddRange(newSegmentPts.GetRange(1, newSegmentPts.Count - 1));
}
return points;
}
}

0 comments on commit 9aa8249

Please sign in to comment.