Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DUI3-426 PR moved from https://github.com/specklesystems/speckle-sharp/pull/3545 #7

Merged
merged 20 commits into from
Jul 15, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,9 @@ public HostObjectBuilderResult Build(
CancellationToken cancellationToken
)
{
// TODO get spatialRef and offsets & rotation from ProjectInfo in CommitObject
// ATM, GIS commit CRS is stored per layer (in FeatureClass converter), but should be moved to the Root level too

// Prompt the UI conversion started. Progress bar will swoosh.
onOperationProgressed?.Invoke("Converting", null);

Expand Down Expand Up @@ -211,7 +214,7 @@ Dictionary<string, GroupLayer> createdLayerGroups
)
{
// get layer details
string? datasetId = trackerItem.DatasetId; // should not ne null here
string? datasetId = trackerItem.DatasetId; // should not be null here
Uri uri = new($"{_contextStack.Current.Document.SpeckleDatabasePath.AbsolutePath.Replace('/', '\\')}\\{datasetId}");
string nestedLayerName = trackerItem.NestedLayerName;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
using System.Diagnostics;
using ArcGIS.Core.Geometry;
using ArcGIS.Desktop.Mapping;
using Objects.GIS;
using Speckle.Autofac.DependencyInjection;
using Speckle.Connectors.Utils.Builders;
using Speckle.Connectors.Utils.Caching;
using Speckle.Connectors.Utils.Conversion;
using Speckle.Connectors.Utils.Operations;
using Speckle.Converters.ArcGIS3;
using Speckle.Converters.ArcGIS3.Utils;
using Speckle.Converters.Common;
using Speckle.Core.Logging;
using Speckle.Core.Models;
Expand All @@ -16,13 +20,19 @@ namespace Speckle.Connectors.ArcGis.Operations.Send;
/// </summary>
public class ArcGISRootObjectBuilder : IRootObjectBuilder<MapMember>
{
private readonly IUnitOfWorkFactory _unitOfWorkFactory;
private readonly IRootToSpeckleConverter _rootToSpeckleConverter;
private readonly ISendConversionCache _sendConversionCache;
private readonly IConversionContextStack<ArcGISDocument, Unit> _contextStack;

public ArcGISRootObjectBuilder(IUnitOfWorkFactory unitOfWorkFactory, ISendConversionCache sendConversionCache)
public ArcGISRootObjectBuilder(
ISendConversionCache sendConversionCache,
IConversionContextStack<ArcGISDocument, Unit> contextStack,
IRootToSpeckleConverter rootToSpeckleConverter
)
{
_unitOfWorkFactory = unitOfWorkFactory;
_sendConversionCache = sendConversionCache;
_contextStack = contextStack;
_rootToSpeckleConverter = rootToSpeckleConverter;
}

public RootObjectBuilderResult Build(
Expand All @@ -32,10 +42,8 @@ public RootObjectBuilderResult Build(
CancellationToken ct = default
)
{
// POC: does this feel like the right place? I am wondering if this should be called from within send/rcv?
// begin the unit of work
using var uow = _unitOfWorkFactory.Resolve<IRootToSpeckleConverter>();
var converter = uow.Service;
// TODO: add a warning if Geographic CRS is set
// "Data has been sent in the units 'degrees'. It is advisable to set the project CRS to Projected type (e.g. EPSG:32631) to be able to receive geometry correctly in CAD/BIM software"

int count = 0;

Expand All @@ -60,7 +68,23 @@ public RootObjectBuilderResult Build(
}
else
{
converted = converter.Convert(mapMember);
converted = _rootToSpeckleConverter.Convert(mapMember);

// get Active CRS (for writing geometry coords)
var spatialRef = _contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference;
converted["crs"] = new CRS
{
wkt = spatialRef.Wkt,
name = spatialRef.Name,
offset_y = System.Convert.ToSingle(_contextStack.Current.Document.ActiveCRSoffsetRotation.LatOffset),
offset_x = System.Convert.ToSingle(_contextStack.Current.Document.ActiveCRSoffsetRotation.LonOffset),
rotation = System.Convert.ToSingle(_contextStack.Current.Document.ActiveCRSoffsetRotation.TrueNorthRadians),
units_native = _contextStack.Current.Document.ActiveCRSoffsetRotation.SpeckleUnitString,
};

// other properties
converted["name"] = mapMember.Name;
converted["units"] = _contextStack.Current.Document.ActiveCRSoffsetRotation.SpeckleUnitString;
converted.applicationId = applicationId;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -19,25 +19,25 @@ namespace Speckle.Connectors.Rhino7.Operations.Send;
/// </summary>
public class RhinoRootObjectBuilder : IRootObjectBuilder<RhinoObject>
{
private readonly IUnitOfWorkFactory _unitOfWorkFactory;
private readonly IRootToSpeckleConverter _rootToSpeckleConverter;
private readonly ISendConversionCache _sendConversionCache;
private readonly RhinoInstanceObjectsManager _instanceObjectsManager;
private readonly IConversionContextStack<RhinoDoc, UnitSystem> _contextStack;
private readonly RhinoLayerManager _layerManager;

public RhinoRootObjectBuilder(
IUnitOfWorkFactory unitOfWorkFactory,
ISendConversionCache sendConversionCache,
IConversionContextStack<RhinoDoc, UnitSystem> contextStack,
RhinoLayerManager layerManager,
RhinoInstanceObjectsManager instanceObjectsManager
RhinoInstanceObjectsManager instanceObjectsManager,
IRootToSpeckleConverter rootToSpeckleConverter
)
{
_unitOfWorkFactory = unitOfWorkFactory;
_sendConversionCache = sendConversionCache;
_contextStack = contextStack;
_layerManager = layerManager;
_instanceObjectsManager = instanceObjectsManager;
_rootToSpeckleConverter = rootToSpeckleConverter;
}

public RootObjectBuilderResult Build(
Expand All @@ -54,11 +54,6 @@ private RootObjectBuilderResult ConvertObjects(
CancellationToken cancellationToken = default
)
{
// POC: does this feel like the right place? I am wondering if this should be called from within send/rcv?
// begin the unit of work
using var uow = _unitOfWorkFactory.Resolve<IRootToSpeckleConverter>();
var converter = uow.Service;

var rootObjectCollection = new Collection { name = _contextStack.Current.Document.Name ?? "Unnamed document" };
int count = 0;

Expand Down Expand Up @@ -100,7 +95,7 @@ private RootObjectBuilderResult ConvertObjects(
}
else
{
converted = converter.Convert(rhinoObject);
converted = _rootToSpeckleConverter.Convert(rhinoObject);
converted.applicationId = applicationId;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
using ArcGIS.Desktop.Core;
using ArcGIS.Desktop.Framework.Threading.Tasks;
using ArcGIS.Desktop.Mapping;
using Speckle.Converters.ArcGIS3.Utils;
using Speckle.Converters.Common;

namespace Speckle.Converters.ArcGIS3;
Expand All @@ -13,12 +14,16 @@ public class ArcGISDocument
public Project Project { get; }
public Map Map { get; }
public Uri SpeckleDatabasePath { get; }
public CRSoffsetRotation ActiveCRSoffsetRotation { get; set; }

public ArcGISDocument()
{
Project = Project.Current;
Map = MapView.Active.Map;
SpeckleDatabasePath = EnsureOrAddSpeckleDatabase();
// CRS of either: incoming commit to be applied to all received objects, or CRS to convert all objects to, before sending
// created per Send/Receive operation, will be the same for all objects in the operation
ActiveCRSoffsetRotation = new CRSoffsetRotation(MapView.Active.Map);
}

private const string FGDB_NAME = "Speckle.gdb";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ private static IReadOnlyDictionary<int, string> Create()

public string ConvertOrThrow(Unit hostUnit)
{
// allow to send data in degrees (RootObjBuilder will send a warning)
if (hostUnit.UnitType == UnitType.Angular && hostUnit.FactoryCode == 9102)
{
return Units.Meters;
}

int linearUnit = LinearUnit.CreateLinearUnit(hostUnit.Wkt).FactoryCode;

if (s_unitMapping.TryGetValue(linearUnit, out string? value))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,25 @@ public FeatureClass Convert(VectorLayer target)
{
wktString = target.crs.wkt;
}
// ATM, GIS commit CRS is stored per layer, but should be moved to the Root level too, and created once per Receive
ACG.SpatialReference spatialRef = ACG.SpatialReferenceBuilder.CreateSpatialReference(wktString);

double trueNorthRadians = System.Convert.ToDouble(
(target.crs == null || target.crs?.rotation == null) ? 0 : target.crs.rotation
);
double latOffset = System.Convert.ToDouble(
(target.crs == null || target.crs?.offset_y == null) ? 0 : target.crs.offset_y
);
double lonOffset = System.Convert.ToDouble(
(target.crs == null || target.crs?.offset_x == null) ? 0 : target.crs.offset_x
);
_contextStack.Current.Document.ActiveCRSoffsetRotation = new CRSoffsetRotation(
spatialRef,
latOffset,
lonOffset,
trueNorthRadians
);

// create Fields
List<FieldDescription> fields = _fieldsUtils.GetFieldsFromSpeckleLayer(target);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,8 @@ public ACG.Multipatch Convert(List<SOG.Mesh> target)
{
throw new SpeckleConversionException("Feature contains no geometries");
}
ACG.MultipatchBuilderEx multipatchPart = new(_contextStack.Current.Document.Map.SpatialReference);
ACG.MultipatchBuilderEx multipatchPart =
new(_contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference);
foreach (SOG.Mesh part in target)
{
part.TriangulateMesh();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
using Speckle.Converters.Common;
using Speckle.Converters.Common.Objects;
using Speckle.Core.Kits;
using Speckle.Core.Models;

namespace Speckle.Converters.ArcGIS3.ToHost.Raw;
Expand All @@ -18,12 +17,14 @@ public PointToHostConverter(IConversionContextStack<ArcGISDocument, ACG.Unit> co

public ACG.MapPoint Convert(SOG.Point target)
{
double scaleFactor = Units.GetConversionFactor(target.units, _contextStack.Current.SpeckleUnits);
SOG.Point scaledMovedRotatedPoint = _contextStack.Current.Document.ActiveCRSoffsetRotation.OffsetRotateOnReceive(
target
);
return new ACG.MapPointBuilderEx(
target.x * scaleFactor,
target.y * scaleFactor,
target.z * scaleFactor,
_contextStack.Current.Document.Map.SpatialReference
scaledMovedRotatedPoint.x,
scaledMovedRotatedPoint.y,
scaledMovedRotatedPoint.z,
_contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference
).ToGeometry();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,13 +35,13 @@ public ACG.Polyline Convert(SOG.Arc target)
fromPt,
toPt,
new ACG.Coordinate2D(midPt),
_contextStack.Current.Document.Map.SpatialReference
_contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference
);

return new ACG.PolylineBuilderEx(
segment,
ACG.AttributeFlags.HasZ,
_contextStack.Current.Document.Map.SpatialReference
_contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference
).ToGeometry();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -46,13 +46,13 @@ public ACG.Polyline Convert(SOG.Circle target)
new ACG.Coordinate2D(centerPt.X, centerPt.Y),
(double)target.radius * scaleFactor,
ACG.ArcOrientation.ArcClockwise,
_contextStack.Current.Document.Map.SpatialReference
_contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference
);

return new ACG.PolylineBuilderEx(
circleSegment,
ACG.AttributeFlags.HasZ,
_contextStack.Current.Document.Map.SpatialReference
_contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference
).ToGeometry();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,9 @@ public ACG.Polyline Convert(SOG.Ellipse target)
double scaleFactor = Units.GetConversionFactor(target.units, _contextStack.Current.SpeckleUnits);

// set default values
double angle = Math.Atan2(target.plane.xdir.y, target.plane.xdir.x);
double angle =
Math.Atan2(target.plane.xdir.y, target.plane.xdir.x)
+ _contextStack.Current.Document.ActiveCRSoffsetRotation.TrueNorthRadians;
double majorAxisRadius = (double)target.firstRadius;
double minorAxisRatio = (double)target.secondRadius / majorAxisRadius;

Expand All @@ -61,13 +63,13 @@ public ACG.Polyline Convert(SOG.Ellipse target)
majorAxisRadius * scaleFactor,
minorAxisRatio,
ACG.ArcOrientation.ArcCounterClockwise,
_contextStack.Current.Document.Map.SpatialReference
_contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference
);

return new ACG.PolylineBuilderEx(
segment,
ACG.AttributeFlags.HasZ,
_contextStack.Current.Document.Map.SpatialReference
_contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference
).ToGeometry();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public ACG.Polyline Convert(SOG.Line target)
return new ACG.PolylineBuilderEx(
points,
ACG.AttributeFlags.HasZ,
_contextStack.Current.Document.Map.SpatialReference
_contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference
).ToGeometry();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public ACG.Polyline Convert(SOG.Polycurve target)
return new ACG.PolylineBuilderEx(
segments,
ACG.AttributeFlags.HasZ,
_contextStack.Current.Document.Map.SpatialReference
_contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference
).ToGeometry();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ public ACG.Polyline Convert(SOG.Polyline target)
return new ACG.PolylineBuilderEx(
points,
ACG.AttributeFlags.HasZ,
_contextStack.Current.Document.Map.SpatialReference
_contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference
).ToGeometry();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ public SOG.Box Convert(Envelope target)
target.XMin,
target.YMin,
target.ZMin,
_contextStack.Current.Document.Map.SpatialReference
_contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference
).ToGeometry();
MapPoint pointMax = new MapPointBuilderEx(
target.XMax,
target.YMax,
target.ZMax,
_contextStack.Current.Document.Map.SpatialReference
_contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference
).ToGeometry();
SOG.Point minPtSpeckle = _pointConverter.Convert(pointMin);
SOG.Point maxPtSpeckle = _pointConverter.Convert(pointMax);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,21 +17,34 @@ public SOG.Point Convert(MapPoint target)
{
try
{
// reproject to Active CRS
if (
GeometryEngine.Instance.Project(target, _contextStack.Current.Document.Map.SpatialReference)
GeometryEngine.Instance.Project(target, _contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference)
is not MapPoint reprojectedPt
)
{
throw new SpeckleConversionException(
$"Conversion to Spatial Reference {_contextStack.Current.Document.Map.SpatialReference.Name} failed"
$"Conversion to Spatial Reference {_contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference.Name} failed"
);
}
return new(reprojectedPt.X, reprojectedPt.Y, reprojectedPt.Z, _contextStack.Current.SpeckleUnits);

// convert to Speckle Pt
SOG.Point reprojectedSpecklePt =
new(
reprojectedPt.X,
reprojectedPt.Y,
reprojectedPt.Z,
_contextStack.Current.Document.ActiveCRSoffsetRotation.SpeckleUnitString
);
SOG.Point scaledMovedRotatedPoint = _contextStack.Current.Document.ActiveCRSoffsetRotation.OffsetRotateOnSend(
reprojectedSpecklePt
);
return scaledMovedRotatedPoint;
}
catch (ArgumentException ex)
{
throw new SpeckleConversionException(
$"Conversion to Spatial Reference {_contextStack.Current.Document.Map.SpatialReference} failed",
$"Conversion to Spatial Reference {_contextStack.Current.Document.ActiveCRSoffsetRotation.SpatialReference.Name} failed",
ex
);
}
Expand Down
Loading
Loading