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

CNX-9753: Add assembly and subassembly objects to Corridors #3475

Merged
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 @@ -30,6 +30,7 @@
using SpiralType = Objects.Geometry.SpiralType;
using Station = Objects.BuiltElements.Station;
using Structure = Objects.BuiltElements.Structure;
using Vector = Objects.Geometry.Vector;
using Speckle.Core.Logging;

namespace Objects.Converter.AutocadCivil;
Expand Down Expand Up @@ -640,7 +641,7 @@ private Line ProfileGenericToSpeckle(double startStation, double startElevation,
}

// featurelines
public Featureline FeatureLineToSpeckle(CivilDB.FeatureLine featureline)
public Featureline FeaturelineToSpeckle(CivilDB.FeatureLine featureline)
{
// get all points
var points = new List<Point>();
Expand All @@ -666,25 +667,18 @@ public Featureline FeatureLineToSpeckle(CivilDB.FeatureLine featureline)
piPoints.Add(allPoints.IndexOf(piPoint));
}

/*
// get bulges at pi point indices
int count = (featureline.Closed) ? featureline.PointsCount : featureline.PointsCount - 1;
List<double> bulges = new List<double>();
for (int i = 0; i < count; i++) bulges.Add(featureline.GetBulge(i));
var piBulges = new List<double>();
foreach (var index in indices) piBulges.Add(bulges[index]);
*/

// get displayvalue
var polyline = PolylineToSpeckle(new Polyline3d(Poly3dType.SimplePoly, intersectionPoints, false));

// featureline
Featureline speckleFeatureline = new()
{
points = points,
curve = CurveToSpeckle(featureline.BaseCurve, ModelUnits),
units = ModelUnits,
displayValue = new List<Polyline>() { polyline }
};

AddNameAndDescriptionProperty(featureline.Name, featureline.Description, speckleFeatureline);
speckleFeatureline["@piPoints"] = piPoints;
speckleFeatureline["@elevationPoints"] = ePoints;
Expand Down Expand Up @@ -1035,7 +1029,7 @@ private List<CivilDataField> PartDataRecordToSpeckle(PartDataRecord partData)

foreach (PartDataField partField in partData.GetAllDataFields())
{
CivilDataField field = new(partField.Name, partField.DataType.ToString(), partField.Units.ToString(), partField.Context.ToString(), partField.Value);
CivilDataField field = new(partField.Name, partField.DataType.ToString(), partField.Value, partField.Units.ToString(),partField.Context.ToString(), null);
fields.Add(field);
}

Expand Down Expand Up @@ -1128,13 +1122,154 @@ public Pipe PipeToSpeckle(PressurePipe pipe)

// corridors
// this is composed of assemblies, alignments, and profiles, use point codes to generate featurelines (which will have the 3d curve)

private CivilDataField AppliedSubassemblyParamToSpeckle(IAppliedSubassemblyParam param)
{
CivilDataField baseParam = new(param.KeyName, param.ValueType.Name, param.ValueAsObject, null, null, param.DisplayName);
return baseParam;
}

private CivilAppliedSubassembly AppliedSubassemblyToSpeckle(AppliedSubassembly appliedSubassembly)
{
// retrieve subassembly name
Subassembly subassembly = Trans.GetObject(appliedSubassembly.SubassemblyId, OpenMode.ForRead) as Subassembly;

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Get another property from the subassembly
string SubassemblyMacroOrClassName = subassembly.GeometryGenerator.MacroOrClassName

https://help.autodesk.com/view/CIV3D/2024/ENU/?guid=d78fdeb6-75cc-dd5a-24db-5c67dc4e5f61

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This one let's save for another issue to add subassembly objects, as this property should be on a new Subassembly class instead of the AppliedSubassembly class

// get the calculated shapes
List<CivilCalculatedShape> speckleShapes = new();
foreach (CalculatedShape shape in appliedSubassembly.Shapes)
{
CivilCalculatedShape speckleShape = CalculatedShapeToSpeckle(shape);
speckleShapes.Add(speckleShape);
}

Point soePoint = PointToSpeckle(appliedSubassembly.OriginStationOffsetElevationToBaseline);
List<CivilDataField> speckleParameters = appliedSubassembly.Parameters.Select(p => AppliedSubassemblyParamToSpeckle(p)).ToList();

CivilAppliedSubassembly speckleAppliedSubassembly = new(appliedSubassembly.SubassemblyId.ToString(), subassembly.Name, speckleShapes, soePoint, speckleParameters);
return speckleAppliedSubassembly;
}

private CivilAppliedAssembly AppliedAssemblyToSpeckle(AppliedAssembly appliedAssembly)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add in a station parameter
private CivilAppliedAssembly AppliedAssemblyToSpeckle(AppliedAssembly appliedAssembly, double station)

{
// get the applied subassemblies
List<CivilAppliedSubassembly> speckleSubassemblies = new();
foreach (AppliedSubassembly appliedSubassembly in appliedAssembly.GetAppliedSubassemblies())
{
CivilAppliedSubassembly speckleSubassembly = AppliedSubassemblyToSpeckle(appliedSubassembly);
speckleSubassemblies.Add(speckleSubassembly);
}

CivilAppliedAssembly speckleAppliedAssembly = new(speckleSubassemblies, appliedAssembly.AdjustedElevation, ModelUnits);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pass the station into the function that creates the SPeckle AppliedAssembly:
CivilAppliedAssembly speckleAppliedAssembly = new(speckleSubassemblies, appliedAssembly.AdjustedElevation, ModelUnits, double station);

return speckleAppliedAssembly;
}

private CivilBaselineRegion BaselineRegionToSpeckle(BaselineRegion region)
{
// get the region assembly
Assembly assembly = Trans.GetObject(region.AssemblyId, OpenMode.ForRead) as Assembly;

// get the applied assemblies by station
List<CivilAppliedAssembly> speckleAppliedAssemblies = new();
double[] sortedStations = region.SortedStations();
for (int i = 0; i < sortedStations.Length; i++)
{
double station = sortedStations[i];
CivilAppliedAssembly speckleAssembly = AppliedAssemblyToSpeckle(region.AppliedAssemblies[i]);
speckleAssembly["station"] = station;
speckleAppliedAssemblies.Add(speckleAssembly);
}

// create the speckle region
CivilBaselineRegion speckleRegion = new(region.Name, region.StartStation, region.EndStation, assembly.Id.ToString(), assembly.Name, speckleAppliedAssemblies);
return speckleRegion;
}

private CivilCalculatedShape CalculatedShapeToSpeckle(CalculatedShape shape)
{
List<string> codes = shape.CorridorCodes.ToList();
List<CivilCalculatedLink> speckleLinks = new();
foreach (CalculatedLink link in shape.CalculatedLinks)
{
CivilCalculatedLink speckleLink = CalculatedLinkToSpeckle(link);
speckleLinks.Add(speckleLink);
}

CivilCalculatedShape speckleCalculatedShape = new(codes, speckleLinks, shape.Area, ModelUnits);
return speckleCalculatedShape;
}

private CivilCalculatedLink CalculatedLinkToSpeckle(CalculatedLink link)
{
List<string> codes = link.CorridorCodes.ToList();
List<CivilCalculatedPoint> specklePoints = new();
foreach (CalculatedPoint point in link.CalculatedPoints)
{
CivilCalculatedPoint specklePoint = CalculatedPointToSpeckle(point);
specklePoints.Add(specklePoint);
}

CivilCalculatedLink speckleLink = new(codes, specklePoints);
return speckleLink;
}

private CivilCalculatedPoint CalculatedPointToSpeckle(CalculatedPoint point)
{
Point specklePoint = PointToSpeckle(point.XYZ);
List<string> codes = point.CorridorCodes.ToList();
Vector normalBaseline = VectorToSpeckle(point.NormalToBaseline);
Vector normalSubAssembly = VectorToSpeckle(point.NormalToSubassembly);
clairekuang marked this conversation as resolved.
Show resolved Hide resolved
Point soePoint = PointToSpeckle(point.StationOffsetElevationToBaseline);
CivilCalculatedPoint speckleCalculatedPoint = new(specklePoint, codes, normalBaseline, normalSubAssembly, soePoint);
return speckleCalculatedPoint;
}

private CivilBaseline BaselineToSpeckle(CivilDB.Baseline baseline)
{
CivilBaseline speckleBaseline = null;

// get the speckle regions
List<CivilBaselineRegion> speckleRegions = new();
foreach (BaselineRegion region in baseline.BaselineRegions)
{
CivilBaselineRegion speckleRegion = BaselineRegionToSpeckle(region);
speckleRegions.Add(speckleRegion);
}

// get profile and alignment if nonfeaturelinebased
// for featureline based corridors, accessing AlignmentId and ProfileId will return NULL
// and throw an exception ""This operation on feature line based baseline is invalid".
if (!baseline.IsFeatureLineBased())
{
// get the speckle alignment
var alignment = Trans.GetObject(baseline.AlignmentId, OpenMode.ForRead) as CivilDB.Alignment;
CivilAlignment speckleAlignment = AlignmentToSpeckle(alignment);

// get the speckle profile
var profile = Trans.GetObject(baseline.ProfileId, OpenMode.ForRead) as CivilDB.Profile;
CivilProfile speckleProfile = ProfileToSpeckle(profile);

speckleBaseline = new(baseline.Name, speckleRegions, baseline.SortedStations().ToList(), baseline.StartStation, baseline.EndStation, speckleAlignment, speckleProfile);
}
else
{
// get the baseline featureline
var featureline = Trans.GetObject(baseline.FeatureLineId, OpenMode.ForRead) as CivilDB.FeatureLine;
Featureline speckleFeatureline = FeaturelineToSpeckle(featureline);

speckleBaseline = new(baseline.Name, speckleRegions, baseline.SortedStations().ToList(), baseline.StartStation, baseline.EndStation, speckleFeatureline);
}

return speckleBaseline;
}

public Base CorridorToSpeckle(Corridor corridor)
{
List<Alignment> alignments = new();
List<Profile> profiles = new();
List<Featureline> featurelines = new();
foreach (Baseline baseline in corridor.Baselines)
List<CivilBaseline> baselines = new();
foreach (CivilDB.Baseline baseline in corridor.Baselines)
{
CivilBaseline speckleBaseline = BaselineToSpeckle(baseline);
baselines.Add(speckleBaseline);

// get the collection of featurelines for this baseline
foreach (FeatureLineCollection mainFeaturelineCollection in baseline.MainBaselineFeatureLines.FeatureLineCollectionMap) // main featurelines
Expand All @@ -1155,32 +1290,6 @@ public Base CorridorToSpeckle(Corridor corridor)
}
}
}

// get alignment and profile if relevant
// for featureline based corridors, accessing AlignmentId and ProfileId will return NULL
// and throw an exception ""This operation on feature line based baseline is invalid".
if (!baseline.IsFeatureLineBased())
{
if (baseline.AlignmentId is ObjectId alignmentId)
{
var alignment = Trans.GetObject(alignmentId, OpenMode.ForRead) as CivilDB.Alignment;
var convertedAlignment = AlignmentToSpeckle(alignment);
if (convertedAlignment != null)
{
alignments.Add(convertedAlignment);
}
}

if (baseline.ProfileId is ObjectId profileId)
{
var profile = Trans.GetObject(profileId, OpenMode.ForRead) as CivilDB.Profile;
var convertedProfile = ProfileToSpeckle(profile);
if (convertedProfile != null)
{
profiles.Add(convertedProfile);
}
}
}
}

// get corridor surfaces
Expand All @@ -1202,9 +1311,8 @@ public Base CorridorToSpeckle(Corridor corridor)
}

var corridorBase = new Base();
corridorBase["@alignments"] = alignments;
corridorBase["@profiles"] = profiles;
corridorBase["@featurelines"] = featurelines;
corridorBase["@baselines"] = baselines;
AddNameAndDescriptionProperty(corridor.Name, corridor.Description, corridorBase);
corridorBase["units"] = ModelUnits;
if (surfaces.Count > 0)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ public Base ConvertToSpeckle(object @object)
@base = CorridorToSpeckle(o);
break;
case CivilDB.FeatureLine o:
@base = FeatureLineToSpeckle(o);
@base = FeaturelineToSpeckle(o);
break;
case CivilDB.Structure o:
@base = StructureToSpeckle(o);
Expand Down
88 changes: 88 additions & 0 deletions Objects/Objects/BuiltElements/Baseline.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
using Speckle.Core.Models;
using Speckle.Newtonsoft.Json;

namespace Objects.BuiltElements;

public abstract class Baseline : Base
{
protected Baseline() { }

protected Baseline(string name, bool isFeaturelineBased)
{
this.name = name;
this.isFeaturelineBased = isFeaturelineBased;
}

/// <summary>
/// The name of this baseline
/// </summary>
public string name { get; set; }

/// <summary>
/// The horizontal component of this baseline
/// </summary>
public abstract Alignment? alignment { get; internal set; }

/// <summary>
/// The vertical component of this baseline
/// </summary>
public abstract Profile? profile { get; internal set; }

[DetachProperty]
public Featureline? featureline { get; internal set; }

public bool isFeaturelineBased { get; set; }
}

/// <summary>
/// Generic instance class
/// </summary>
public abstract class Baseline<TA, TP> : Baseline
where TA : Alignment
where TP : Profile
{
protected Baseline(string name, TA alignment, TP profile, Featureline? featureline, bool isFeaturelineBased)
: base(name, isFeaturelineBased)
{
this.name = name;
typedAlignment = alignment;
typedProfile = profile;
this.featureline = featureline;
this.isFeaturelineBased = isFeaturelineBased;
}

protected Baseline()
: base(string.Empty, false) { }

[JsonIgnore]
public TA typedAlignment { get; set; }

[JsonIgnore]
public TP typedProfile { get; set; }

[DetachProperty]
public override Alignment? alignment
{
get => typedAlignment;
internal set
{
if (value is TA typeA)
{
typedAlignment = typeA;
}
}
}

[DetachProperty]
public override Profile? profile
{
get => typedProfile;
internal set
{
if (value is TP typeP)
{
typedProfile = typeP;
}
}
}
}
26 changes: 26 additions & 0 deletions Objects/Objects/BuiltElements/Civil/CivilAppliedAssembly.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
using System.Collections.Generic;
using Speckle.Core.Models;

namespace Objects.BuiltElements.Civil;

public class CivilAppliedAssembly : Base
{
public CivilAppliedAssembly() { }

public CivilAppliedAssembly(
List<CivilAppliedSubassembly> appliedSubassemblies,
double adjustedElevation,
string units
)
{
this.appliedSubassemblies = appliedSubassemblies;
this.adjustedElevation = adjustedElevation;
this.units = units;
}

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add property to store the station of this AppliedAssembly and include in the constructor so the value can be set
public double station { get; set; }

public List<CivilAppliedSubassembly> appliedSubassemblies { get; set; }

public double adjustedElevation { get; set; }

public string units { get; set; }
}
Loading