Skip to content

Commit

Permalink
feat(objects/revit): organization classes (#1402)
Browse files Browse the repository at this point in the history
* feat(objects): container and model classes

* setting proposal (#1323)

* fix(objects): cleanup on the model objs

* feat(objects): add another transform constructor

* feat(revit): use `Model` and `ModelInfo` on send

Co-authored-by: Claire Kuang <[email protected]>
Co-authored-by: Alan Rynne <[email protected]>
  • Loading branch information
3 people authored Jul 19, 2022
1 parent 65ea643 commit 1edc546
Show file tree
Hide file tree
Showing 8 changed files with 293 additions and 20 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ public override async Task<string> SendStream(StreamState state, ProgressViewMod

converter.SetContextObjects(selectedObjects.Select(x => new ApplicationPlaceholderObject { applicationId = x.UniqueId }).ToList());

var commitObject = new Base();
var commitObject = converter.ConvertToSpeckle(CurrentDoc.Document) ?? new Base();

var conversionProgressDict = new ConcurrentDictionary<string, int>();
conversionProgressDict["Conversion"] = 0;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,9 @@ public Base ConvertToSpeckle(object @object)
Base returnObject = null;
switch (@object)
{
case DB.Document o:
returnObject = ModelToSpeckle(o);
break;
case DB.DetailCurve o:
returnObject = DetailCurveToSpeckle(o);
break;
Expand Down Expand Up @@ -270,8 +273,15 @@ public Base ConvertToSpeckle(object @object)
&& returnObject["renderMaterial"] == null
&& returnObject["displayValue"] == null)
{
var material = GetElementRenderMaterial(@object as DB.Element);
returnObject["renderMaterial"] = material;
try
{
var material = GetElementRenderMaterial(@object as DB.Element);
returnObject["renderMaterial"] = material;
}
catch ( Exception e )
{
// passing for stuff without a material (eg converting the current document to get the `Model` and `Info` objects)
}
}

//NOTE: adds the quantities of all materials to an element
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
<Compile Include="$(MSBuildThisFileDirectory)Partial Classes\ConvertDirectTeklaMeshElements.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Partial Classes\ConvertMaterial.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Partial Classes\ConvertMaterialQuantities.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Partial Classes\ConvertModel.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Partial Classes\ConvertRebar.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Partial Classes\ConvertBrace.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Partial Classes\ConvertBlock.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
using System;
using System.Collections.Generic;
using DB = Autodesk.Revit.DB;
using Objects.Organization;
using Objects.Other;
using Speckle.Core.Models;

namespace Objects.Converter.Revit
{
public partial class ConverterRevit
{
/// <summary>
/// Returns a <see cref="Model"/> object containing <see cref="Objects.BuiltElements.Revit.ProjectInfo"/> and location
/// information. This is intended to be used as the root commit object when sending to Speckle.
/// </summary>
/// <param name="doc">the currently active document</param>
/// <param name="sendProjectInfo">true if project info should be added</param>
/// <returns></returns>
public Base ModelToSpeckle(DB.Document doc, bool sendProjectInfo = true)
{
var model = new Model();
// TODO: setting for whether or not to include project info
if ( sendProjectInfo )
{
var info = ProjectInfoToSpeckle(doc.ProjectInformation);
info.latitude = doc.SiteLocation.Latitude;
info.longitude = doc.SiteLocation.Longitude;
info.siteName = doc.SiteLocation.PlaceName;
info.locations = ProjectLocationsToSpeckle(doc.ProjectLocations);
model.info = info;
}

Report.Log($"Created Model Object");

return model;
}

/// <summary>
/// Converts the Revit document's <see cref="DB.ProjectLocationSet"/> into a list of bases including the <see cref="Objects.Other.Transform"/>,
/// name, and true north angle (in radians)
/// </summary>
/// <param name="locations"></param>
/// <returns></returns>
public List<Base> ProjectLocationsToSpeckle(DB.ProjectLocationSet locations)
{
// TODO: do we need a location obj?
var spcklLocations = new List<Base>();
foreach ( DB.ProjectLocation location in locations )
{
var position = location.GetProjectPosition(DB.XYZ.Zero);
var revitTransform = DB.Transform.CreateRotation(DB.XYZ.BasisZ, position.Angle);

var spcklLoc = new Base() { applicationId = location.UniqueId };
spcklLoc[ "transform" ] = new Transform(
new[ ] { revitTransform.BasisX[ 0 ], revitTransform.BasisX[ 1 ], revitTransform.BasisX[ 2 ] },
new[ ] { revitTransform.BasisY[ 0 ], revitTransform.BasisY[ 1 ], revitTransform.BasisY[ 2 ] },
new[ ] { revitTransform.BasisZ[ 0 ], revitTransform.BasisZ[ 1 ], revitTransform.BasisZ[ 2 ] },
new[ ] { ScaleToSpeckle(position.EastWest), ScaleToSpeckle(position.NorthSouth), ScaleToSpeckle(position.Elevation) },
ModelUnits);
spcklLoc[ "name" ] = location.Name;
spcklLoc[ "trueNorth" ] = position.Angle;
spcklLocations.Add(spcklLoc);
}

return spcklLocations;
}
}
}
9 changes: 2 additions & 7 deletions Objects/Objects/BuiltElements/Revit/ProjectInfo.cs
Original file line number Diff line number Diff line change
@@ -1,21 +1,16 @@
using Speckle.Core.Kits;
using Speckle.Core.Models;
using System.Collections.Generic;
using Objects.Organization;

namespace Objects.BuiltElements.Revit
{
public class ProjectInfo : Base
public class ProjectInfo : BIMModelInfo
{
public string address { get; set; }
public string author { get; set; }
public string buildingName { get; set; }
public string clientName { get; set; }
public string issueDate { get; set; }
public string name { get; set; }
public string number { get; set; }
public string organizationDescription { get; set; }
public string organizationName { get; set; }
public string status { get; set; }

}

Expand Down
50 changes: 50 additions & 0 deletions Objects/Objects/Organization/Container.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
using System.Collections.Generic;
using Speckle.Core.Models;

namespace Objects.Organization
{
/// <summary>
/// A simple container for organising objects within a model and preserving object hierarchy.
/// A container is defined by a unique <see cref="name"/> and its list of contained <see cref="elements"/>.
/// The <see cref="elements"/> can include an unrestricted number of <see cref="Base"/> objects including additional nested <see cref="Container"/>s.
/// </summary>
/// <remarks>
/// A <see cref="Container"/> correlates to eg Rhino and AutoCad Layers or Blender Collections.
/// While it is possible for an object to belong to multiple containers, most applications will not support this and
/// on receive the object will be assigned the the first container it is encountered in.
/// </remarks>
public class Container : Base
{
/// <summary>
/// The name of the container.
/// This should be unique within the commit.
/// </summary>
/// TODO: standardise this behaviour across connectors
/// <remarks>On receive, this will be prepended with the id of the stream as to not overwrite existing containers in the file.</remarks>
public string name { get; set; }

/// <summary>
/// The elements contained in this <see cref="Container"/>. This can include any <see cref="Base"/> object including
/// additional nested <see cref="Container"/>s.
/// </summary>
/// <remarks>
/// Most applications will expect all contained elements to have displayable geometry or to be another <see cref="Container"/>.
/// This means that purely data <see cref="Base"/> objects may be lost on receive.
/// </remarks>
[DetachProperty]
public List<Base> elements { get; set; }

public Container() {}

/// <summary>
/// Constructor for a basic container.
/// </summary>
/// <param name="name">The unique name of this container</param>
/// <param name="elements">Any contained <see cref="Base"/> objects</param>
public Container(string name, List<Base> elements = null)
{
this.name = name;
this.elements = elements;
}
}
}
121 changes: 121 additions & 0 deletions Objects/Objects/Organization/Model.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
using System.Collections.Generic;
using Objects.Other;
using Speckle.Core.Models;

namespace Objects.Organization
{
/// <summary>
/// Represents a model from an authoring application and can be used as the root commit object when sending.
/// It contains <see cref="ModelInfo"/> and <see cref="Setting"/> objects
/// </summary>
public class Model : Base
{
/// <summary>
/// General model-wide information stored in a <see cref="ModelInfo"/> object.
/// This may include anything from simply a project / file name to specific location information (eg with <see cref="BIMModelInfo"/>)
/// </summary>
public ModelInfo info { get; set; }


public List<Setting> settings { get; set; }

public Model()
{
}

public Model(ModelInfo info, List<Setting> settings = null)
{
this.info = info;
this.settings = settings;
}
}

/// <summary>
/// Basic model info class to be attached to the <see cref="Model.info"/> field on a <see cref="Model"/> object.
/// It contains general information about the model and can be extended or subclassed to include more application-specific
/// information.
/// </summary>
public class ModelInfo : Base
{
/// <summary>
/// The name of the model.
/// </summary>
public string name { get; set; }

/// <summary>
/// The identifying number of the model.
/// </summary>
public string number { get; set; }

public ModelInfo()
{
}

// TODO: not sure about adding a typed `elements` list here? prob should let ppl add whatever named categories here?
}

// TODO: not quite sure about this name?
/// <summary>
/// Extended <see cref="ModelInfo"/> to be attached to the <see cref="Model.info"/> field on a <see cref="Model"/> object.
/// This contains additional properties applicable to AEC projects.
/// </summary>
public class BIMModelInfo : ModelInfo
{
/// <summary>
/// The name of the client
/// </summary>
public string clientName { get; set; }

/// <summary>
/// The name of the building
/// </summary>
public string buildingName { get; set; }

/// <summary>
/// The status or phase of the model.
/// </summary>
public string status { get; set; }

/// <summary>
/// The address of the model.
/// </summary>
public string address { get; set; }

/// <summary>
/// The name of the site location as a string.
/// </summary>
public string siteName { get; set; }

/// <summary>
/// The latitude of the site location in radians.
/// </summary>
public double latitude { get; set; }

/// <summary>
/// The longitude of the site location in radians.
/// </summary>
public double longitude { get; set; }

/// <summary>
/// A list of origin locations within this model as a list of <see cref="Transform"/>s
/// </summary>
public List<Base> locations { get; set; }

public BIMModelInfo()
{
}
}

public class Setting : Base
{
/// <summary>
/// The name of the setting
/// </summary>
public string name { get; set; }

/// <summary>
/// The objects selected in the setting
/// </summary>
public List<Base> selection { get; set; }
}
}
Loading

0 comments on commit 1edc546

Please sign in to comment.