diff --git a/.circleci/scripts/config-template.yml b/.circleci/scripts/config-template.yml index 15f6b5918f..115a0539ee 100644 --- a/.circleci/scripts/config-template.yml +++ b/.circleci/scripts/config-template.yml @@ -341,6 +341,28 @@ jobs: # Each project will have individual jobs for each specific task it has to msbuild << parameters.slnname >>/<< parameters.slnname >>.sln /r /p:Configuration='<< parameters.build-config >>' /p:IsDesktopBuild=false /p:Version=$SEMVER /p:FileVersion=$VERSION environment: WORKFLOW_NUM: << pipeline.number >> + - unless: + condition: << parameters.build-with-mono >> + steps: + - run: + name: Publish x64 and arm64 + command: | + TAG=$(if [ "${CIRCLE_TAG}" ]; then echo $CIRCLE_TAG; else echo "2.0.999"; fi;) + SEMVER=$(echo "$TAG" | sed -e 's/\/[a-zA-Z-]*//') + VER=$(echo "$SEMVER" | sed -e 's/-.*//') + VERSION=$(echo $VER.$WORKFLOW_NUM) + $HOME/.dotnet/dotnet publish << parameters.slnname >>/<< parameters.projname >>/<< parameters.projname >>.csproj -c Release -r osx-arm64 --self-contained /p:IsDesktopBuild=false /p:Version=$SEMVER /p:FileVersion=$VERSION + $HOME/.dotnet/dotnet publish << parameters.slnname >>/<< parameters.projname >>/<< parameters.projname >>.csproj -c Release -r osx-x64 --self-contained /p:IsDesktopBuild=false /p:Version=$SEMVER /p:FileVersion=$VERSION + environment: + WORKFLOW_NUM: << pipeline.number >> + # Create installer + - run: + name: Exit if External PR + command: if [ "$CIRCLE_PR_REPONAME" ]; then circleci-agent step halt; fi + # Zip files for installer + - when: + condition: << parameters.build-with-mono >> + steps: # Compress build files - run: name: Zip Objects Kit files @@ -362,34 +384,25 @@ jobs: # Each project will have individual jobs for each specific task it has to condition: << parameters.build-with-mono >> steps: - run: - name: Publish x64 and arm64 + name: Create app bundles command: | - TAG=$(if [ "${CIRCLE_TAG}" ]; then echo $CIRCLE_TAG; else echo "2.0.999"; fi;) - SEMVER=$(echo "$TAG" | sed -e 's/\/[a-zA-Z-]*//') - VER=$(echo "$SEMVER" | sed -e 's/-.*//') - VERSION=$(echo $VER.$WORKFLOW_NUM) - $HOME/.dotnet/dotnet publish << parameters.slnname >>/<< parameters.projname >>/<< parameters.projname >>.csproj -c Release -r osx-arm64 --self-contained /p:IsDesktopBuild=false /p:Version=$SEMVER /p:FileVersion=$VERSION - $HOME/.dotnet/dotnet publish << parameters.slnname >>/<< parameters.projname >>/<< parameters.projname >>.csproj -c Release -r osx-x64 --self-contained /p:IsDesktopBuild=false /p:Version=$SEMVER /p:FileVersion=$VERSION - environment: - WORKFLOW_NUM: << pipeline.number >> + sh ./speckle-sharp-ci-tools/Mac/AppBundle/bundle.sh ./<< parameters.slnname >>/<< parameters.slnname >>/bin/Release/net6.0/osx-arm64/publish/ ./<< parameters.slnname >>/<< parameters.slnname >>/Info.plist ./<< parameters.slnname >>/<< parameters.slnname >>/Assets/icon-mac.icns ./<< parameters.slnname >>/<< parameters.slnname >>/bin/Release/net6.0/osx-arm64/<< parameters.slnname >> + sh ./speckle-sharp-ci-tools/Mac/AppBundle/bundle.sh ./<< parameters.slnname >>/<< parameters.slnname >>/bin/Release/net6.0/osx-x64/publish/ ./<< parameters.slnname >>/<< parameters.slnname >>/Info.plist ./<< parameters.slnname >>/<< parameters.slnname >>/Assets/icon-mac.icns ./<< parameters.slnname >>/<< parameters.slnname >>/bin/Release/net6.0/osx-x64/<< parameters.slnname >> - run: name: Zip Connector files command: | - cd "<< parameters.slnname >>/<< parameters.slnname >>/bin/Release/net6.0/osx-arm64/publish" - zip -r << parameters.slug >>-mac-arm64.zip "./" - cd "../../osx-x64/publish" - zip -r << parameters.slug >>-mac-x64.zip "./" + cd "<< parameters.slnname >>/<< parameters.slnname >>/bin/Release/net6.0/osx-arm64/" + zip -r << parameters.slug >>-mac-arm64.zip "./<< parameters.slnname >>.app" + cd "../osx-x64/" + zip -r << parameters.slug >>-mac-x64.zip "./<< parameters.slnname >>.app" # Copy installer files - run: name: Copy files to installer command: | mkdir -p speckle-sharp-ci-tools/Mac/<< parameters.installername >>/.installationFiles/ - cp << parameters.slnname >>/<< parameters.slnname >>/bin/Release/net6.0/osx-arm64/publish/<< parameters.slug >>-mac-arm64.zip speckle-sharp-ci-tools/Mac/<>/.installationFiles - cp << parameters.slnname >>/<< parameters.slnname >>/bin/Release/net6.0/osx-x64/publish/<< parameters.slug >>-mac-x64.zip speckle-sharp-ci-tools/Mac/<>/.installationFiles - # Create installer - - run: - name: Exit if External PR - command: if [ "$CIRCLE_PR_REPONAME" ]; then circleci-agent step halt; fi + cp << parameters.slnname >>/<< parameters.slnname >>/bin/Release/net6.0/osx-arm64/<< parameters.slug >>-mac-arm64.zip speckle-sharp-ci-tools/Mac/<>/.installationFiles + cp << parameters.slnname >>/<< parameters.slnname >>/bin/Release/net6.0/osx-x64/<< parameters.slug >>-mac-x64.zip speckle-sharp-ci-tools/Mac/<>/.installationFiles + - run: name: Build Mac installer command: ~/.dotnet/dotnet publish speckle-sharp-ci-tools/Mac/<>/<>.sln -r osx-x64 -c Release diff --git a/Automate/Speckle.Automate.Sdk/AutomationContext.cs b/Automate/Speckle.Automate.Sdk/AutomationContext.cs index fef232187b..5844df540a 100644 --- a/Automate/Speckle.Automate.Sdk/AutomationContext.cs +++ b/Automate/Speckle.Automate.Sdk/AutomationContext.cs @@ -317,6 +317,8 @@ private void MarkRun(AutomationStatus status, string? statusMessage) public void MarkRunFailed(string statusMessage) => MarkRun(AutomationStatus.Failed, statusMessage); + public void MarkRunException(string? statusMessage) => MarkRun(AutomationStatus.Exception, statusMessage); + public void MarkRunSuccess(string? statusMessage) => MarkRun(AutomationStatus.Succeeded, statusMessage); /// diff --git a/Automate/Speckle.Automate.Sdk/Runner.cs b/Automate/Speckle.Automate.Sdk/Runner.cs index 62b9297c72..43f50c0cc6 100644 --- a/Automate/Speckle.Automate.Sdk/Runner.cs +++ b/Automate/Speckle.Automate.Sdk/Runner.cs @@ -41,7 +41,7 @@ TInput inputs catch (Exception ex) when (!ex.IsFatal()) { Console.WriteLine(ex.ToString()); - automationContext.MarkRunFailed("Function error. Check the automation run logs for details."); + automationContext.MarkRunException("Function error. Check the automation run logs for details."); } finally { @@ -59,16 +59,14 @@ public static async Task RunFunction( Func automateFunction, AutomationRunData automationRunData, string speckleToken - ) - { - return await RunFunction( + ) => + await RunFunction( async (context, _) => await automateFunction(context).ConfigureAwait(false), automationRunData, speckleToken, new Fake() ) .ConfigureAwait(false); - } private struct Fake { } @@ -100,14 +98,25 @@ public static async Task Main(string[] args, Func pathArg = new(name: "Input Path", description: "A file path to retrieve function inputs"); RootCommand rootCommand = new(); + // a stupid hack to be able to exit with a specific integer exit code + // read more at https://github.com/dotnet/command-line-api/issues/1570 + var exitCode = 0; + rootCommand.AddArgument(pathArg); rootCommand.SetHandler( async inputPath => { FunctionRunData data = FunctionRunDataParser.FromPath(inputPath); - await RunFunction(automateFunction, data.AutomationRunData, data.SpeckleToken, data.FunctionInputs) + var context = await RunFunction( + automateFunction, + data.AutomationRunData, + data.SpeckleToken, + data.FunctionInputs + ) .ConfigureAwait(false); + + exitCode = context.RunStatus == "EXCEPTION" ? 1 : 0; }, pathArg ); @@ -118,7 +127,7 @@ await RunFunction(automateFunction, data.AutomationRunData, data.SpeckleToken, d Command generateSchemaCommand = new("generate-schema", "Generate JSON schema for the function inputs"); generateSchemaCommand.AddArgument(schemaFilePathArg); generateSchemaCommand.SetHandler( - (schemaFilePath) => + schemaFilePath => { JSchemaGenerator generator = new() { ContractResolver = new CamelCasePropertyNamesContractResolver() }; generator.GenerationProviders.Add(new SpeckleSecretProvider()); @@ -134,7 +143,7 @@ await RunFunction(automateFunction, data.AutomationRunData, data.SpeckleToken, d // if we've gotten this far, the execution should technically be completed as expected // thus exiting with 0 is the semantically correct thing to do - return 0; + return exitCode; } } diff --git a/Automate/Speckle.Automate.Sdk/Schema/AutomationRunData.cs b/Automate/Speckle.Automate.Sdk/Schema/AutomationRunData.cs index 755d833003..08997f7a73 100644 --- a/Automate/Speckle.Automate.Sdk/Schema/AutomationRunData.cs +++ b/Automate/Speckle.Automate.Sdk/Schema/AutomationRunData.cs @@ -12,5 +12,5 @@ public struct AutomationRunData public string AutomationId { get; set; } public string AutomationRunId { get; set; } public string FunctionRunId { get; set; } - public List Triggers { get; set; } + public List Triggers { get; set; } } diff --git a/Automate/Speckle.Automate.Sdk/Schema/AutomationStatus.cs b/Automate/Speckle.Automate.Sdk/Schema/AutomationStatus.cs index b23ba0feaf..b7b34b66f1 100644 --- a/Automate/Speckle.Automate.Sdk/Schema/AutomationStatus.cs +++ b/Automate/Speckle.Automate.Sdk/Schema/AutomationStatus.cs @@ -8,5 +8,6 @@ public enum AutomationStatus Initializing, Running, Failed, - Succeeded + Succeeded, + Exception } diff --git a/Automate/Speckle.Automate.Sdk/Schema/AutomationStatusMapping.cs b/Automate/Speckle.Automate.Sdk/Schema/AutomationStatusMapping.cs index fe3f6d9f33..a7996bbeee 100644 --- a/Automate/Speckle.Automate.Sdk/Schema/AutomationStatusMapping.cs +++ b/Automate/Speckle.Automate.Sdk/Schema/AutomationStatusMapping.cs @@ -6,6 +6,7 @@ public abstract class AutomationStatusMapping private const string RUNNING = "RUNNING"; private const string FAILED = "FAILED"; private const string SUCCEEDED = "SUCCEEDED"; + private const string EXCEPTION = "EXCEPTION"; public static string Get(AutomationStatus status) => status switch @@ -14,6 +15,7 @@ public static string Get(AutomationStatus status) => AutomationStatus.Failed => FAILED, AutomationStatus.Succeeded => SUCCEEDED, AutomationStatus.Initializing => INITIALIZING, + AutomationStatus.Exception => EXCEPTION, _ => throw new ArgumentOutOfRangeException($"Not valid value for enum {status}") }; } diff --git a/Automate/Speckle.Automate.Sdk/Schema/Triggers/VersionCreationTrigger.cs b/Automate/Speckle.Automate.Sdk/Schema/Triggers/VersionCreationTrigger.cs index dd5f649bf1..477df4b10b 100644 --- a/Automate/Speckle.Automate.Sdk/Schema/Triggers/VersionCreationTrigger.cs +++ b/Automate/Speckle.Automate.Sdk/Schema/Triggers/VersionCreationTrigger.cs @@ -10,7 +10,7 @@ public class VersionCreationTrigger : AutomationRunTriggerBase public VersionCreationTrigger(string modelId, string versionId) { TriggerType = "versionCreation"; - Payload = new VersionCreationTriggerPayload() { ModelId = modelId, VersionId = versionId }; + Payload = new VersionCreationTriggerPayload { ModelId = modelId, VersionId = versionId }; } } diff --git a/Automate/Speckle.Automate.Sdk/Test/TestAutomateUtils.cs b/Automate/Speckle.Automate.Sdk/Test/TestAutomateUtils.cs index f28596bc88..21e6f83d2a 100644 --- a/Automate/Speckle.Automate.Sdk/Test/TestAutomateUtils.cs +++ b/Automate/Speckle.Automate.Sdk/Test/TestAutomateUtils.cs @@ -52,10 +52,7 @@ mutation Mutation($projectId: ID!, $automationId: ID!) { AutomationId = TestAutomateEnvironment.GetSpeckleAutomationId(), AutomationRunId = runData["automationRunId"], FunctionRunId = runData["functionRunId"], - Triggers = new List() - { - new VersionCreationTrigger(modelId: modelId, versionId: versionId) - } + Triggers = new List { new(modelId: modelId, versionId: versionId) } }; return data; diff --git a/Automate/Tests/Speckle.Automate.Sdk.Tests.Integration/SpeckleAutomate.cs b/Automate/Tests/Speckle.Automate.Sdk.Tests.Integration/SpeckleAutomate.cs index 5486a78cd9..7fc0517136 100644 --- a/Automate/Tests/Speckle.Automate.Sdk.Tests.Integration/SpeckleAutomate.cs +++ b/Automate/Tests/Speckle.Automate.Sdk.Tests.Integration/SpeckleAutomate.cs @@ -46,7 +46,7 @@ private async Task AutomationRunData(Base testObject) string functionRelease = Utils.RandomString(10); string functionRunId = Utils.RandomString(10); - var triggers = new List() { new VersionCreationTrigger(modelId, versionId) }; + var triggers = new List { new(modelId, versionId) }; return new AutomationRunData { @@ -59,7 +59,7 @@ private async Task AutomationRunData(Base testObject) }; } - private VersionCreationTrigger GetVersionCreationTrigger(List triggers) + private VersionCreationTrigger GetVersionCreationTrigger(List triggers) { if (triggers.FirstOrDefault() is not VersionCreationTrigger trigger) { diff --git a/ConnectorArchicad/AddOn/Sources/AddOn/AddOnMain.cpp b/ConnectorArchicad/AddOn/Sources/AddOn/AddOnMain.cpp index 532f056af6..1fd3ac1daa 100644 --- a/ConnectorArchicad/AddOn/Sources/AddOn/AddOnMain.cpp +++ b/ConnectorArchicad/AddOn/Sources/AddOn/AddOnMain.cpp @@ -18,6 +18,7 @@ #include "Commands/GetElementBaseData.hpp" #include "Commands/GetGridElementData.hpp" #include "Commands/GetObjectData.hpp" +#include "Commands/GetOpeningData.hpp" #include "Commands/GetSlabData.hpp" #include "Commands/GetRoofData.hpp" #include "Commands/GetShellData.hpp" @@ -31,6 +32,7 @@ #include "Commands/CreateColumn.hpp" #include "Commands/CreateGridElement.hpp" #include "Commands/CreateObject.hpp" +#include "Commands/CreateOpening.hpp" #include "Commands/CreateRoof.hpp" #include "Commands/CreateSkylight.hpp" #include "Commands/CreateSlab.hpp" @@ -90,46 +92,41 @@ class AvaloniaProcessManager { private: GS::UniString GetPlatformSpecificExecutablePath () { -#if defined (macintosh) - static const char* FileName = "ConnectorArchicad"; -#else - static const char* FileName = "ConnectorArchicad.exe"; -#endif - static const char* FolderNameCommon = "Common"; - static const char* FolderName = "ConnectorArchicad"; - IO::Location ownFileLoc; auto err = ACAPI_GetOwnLocation (&ownFileLoc); if (err != NoError) { return ""; } +#if defined (macintosh) + static const char* ProductionConnector = "../../../Common/ConnectorArchicad/ConnectorArchicad.app/Contents/MacOS/ConnectorArchicad"; +#else + static const char* ProductionConnector = "../../../Common/ConnectorArchicad/ConnectorArchicad.exe"; +#endif + IO::Location location (ownFileLoc); - location.DeleteLastLocalName (); - location.DeleteLastLocalName (); - location.DeleteLastLocalName (); - location.AppendToLocal (IO::Name (FolderNameCommon)); - location.AppendToLocal (IO::Name (FolderName)); - location.AppendToLocal (IO::Name (FileName)); + location.AppendToLocal (IO::RelativeLocation (ProductionConnector)); bool exist (false); err = IO::fileSystem.Contains (location, &exist); if (err != NoError || !exist) { location = ownFileLoc; - location.DeleteLastLocalName (); - location.DeleteLastLocalName (); - location.DeleteLastLocalName (); - location.DeleteLastLocalName (); - location.AppendToLocal (IO::Name (FolderName)); - location.AppendToLocal (IO::Name ("bin")); +#if defined (macintosh) #ifdef DEBUG - location.AppendToLocal (IO::Name ("Debug")); + static const char* DevelopmentConnector = "../../../../ConnectorArchicad/bin/Debug/net6.0/ConnectorArchicad"; #else - location.AppendToLocal (IO::Name ("Release")); + static const char* DevelopmentConnector = "../../../../ConnectorArchicad/bin/Release/net6.0/ConnectorArchicad"; #endif - location.AppendToLocal (IO::Name ("net6.0")); - location.AppendToLocal (IO::Name (FileName)); +#else +#ifdef DEBUG + static const char* DevelopmentConnector = "../../../../ConnectorArchicad/bin/Debug/net6.0/ConnectorArchicad.exe"; +#else + static const char* DevelopmentConnector = "../../../../ConnectorArchicad/bin/Release/net6.0/ConnectorArchicad.exe"; +#endif +#endif + + location.AppendToLocal (IO::RelativeLocation (DevelopmentConnector)); } GS::UniString executableStr; @@ -200,6 +197,7 @@ static GSErrCode RegisterAddOnCommands () CHECKERROR (ACAPI_AddOnAddOnCommunication_InstallAddOnCommandHandler (NewOwned ())); CHECKERROR (ACAPI_AddOnAddOnCommunication_InstallAddOnCommandHandler (NewOwned ())); CHECKERROR (ACAPI_AddOnAddOnCommunication_InstallAddOnCommandHandler (NewOwned ())); + CHECKERROR (ACAPI_AddOnAddOnCommunication_InstallAddOnCommandHandler (NewOwned ())); CHECKERROR (ACAPI_AddOnAddOnCommunication_InstallAddOnCommandHandler (NewOwned ())); CHECKERROR (ACAPI_AddOnAddOnCommunication_InstallAddOnCommandHandler (NewOwned ())); CHECKERROR (ACAPI_AddOnAddOnCommunication_InstallAddOnCommandHandler (NewOwned ())); @@ -213,6 +211,7 @@ static GSErrCode RegisterAddOnCommands () CHECKERROR (ACAPI_AddOnAddOnCommunication_InstallAddOnCommandHandler (NewOwned ())); CHECKERROR (ACAPI_AddOnAddOnCommunication_InstallAddOnCommandHandler (NewOwned ())); CHECKERROR (ACAPI_AddOnAddOnCommunication_InstallAddOnCommandHandler (NewOwned ())); + CHECKERROR (ACAPI_AddOnAddOnCommunication_InstallAddOnCommandHandler (NewOwned ())); CHECKERROR (ACAPI_AddOnAddOnCommunication_InstallAddOnCommandHandler (NewOwned ())); CHECKERROR (ACAPI_AddOnAddOnCommunication_InstallAddOnCommandHandler (NewOwned ())); CHECKERROR (ACAPI_AddOnAddOnCommunication_InstallAddOnCommandHandler (NewOwned ())); diff --git a/ConnectorArchicad/AddOn/Sources/AddOn/Commands/CreateOpening.cpp b/ConnectorArchicad/AddOn/Sources/AddOn/Commands/CreateOpening.cpp new file mode 100644 index 0000000000..7db770d5e1 --- /dev/null +++ b/ConnectorArchicad/AddOn/Sources/AddOn/Commands/CreateOpening.cpp @@ -0,0 +1,373 @@ +#include "CreateOpening.hpp" +#include "ResourceIds.hpp" +#include "ObjectState.hpp" +#include "Utility.hpp" +#include "Objects/Point.hpp" +#include "Objects/Vector.hpp" +#include "RealNumber.h" +#include "DGModule.hpp" +#include "LibpartImportManager.hpp" +#include "APIHelper.hpp" +#include "FieldNames.hpp" +#include "OnExit.hpp" +#include "ExchangeManager.hpp" +#include "TypeNameTables.hpp" +#include "Database.hpp" +#include "BM.hpp" + + +using namespace FieldNames; + + +namespace AddOnCommands +{ + + +GS::String CreateOpening::GetFieldName () const +{ + return FieldNames::Openings; +} + + +GS::UniString CreateOpening::GetUndoableCommandName () const +{ + return "CreateSpeckleOpening"; +} + + +GS::ErrCode CreateOpening::GetElementFromObjectState (const GS::ObjectState& os, + API_Element& element, + API_Element& elementMask, + API_ElementMemo& memo, + GS::UInt64& /*memoMask*/, + API_SubElement** /*marker*/, + AttributeManager& /*attributeManager*/, + LibpartImportManager& /*libpartImportManager*/, + GS::Array& log) const +{ + GS::ErrCode err = NoError; + + Utility::SetElementType (element.header, API_OpeningID); + + err = Utility::GetBaseElementData (element, &memo, nullptr, log); + if (err != NoError) + return err; + + err = GetElementBaseFromObjectState (os, element, elementMask); + if (err != NoError) + return err; + + if (!CheckEnvironment (os, element)) + return Error; + + if (os.Contains (Opening::FloorPlanDisplayMode)) { + GS::UniString floorPlanDisplayModeName; + os.Get (Opening::FloorPlanDisplayMode, floorPlanDisplayModeName); + + GS::Optional type = openingFloorPlanDisplayModeNames.FindValue (floorPlanDisplayModeName); + if (type.HasValue ()) { + element.opening.floorPlanParameters.floorPlanDisplayMode = type.Get (); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.floorPlanDisplayMode); + } + } + + if (os.Contains (Opening::ConnectionMode)) { + GS::UniString connectionModeName; + os.Get (Opening::ConnectionMode, connectionModeName); + + GS::Optional type = openingFloorPlanConnectionModeNames.FindValue (connectionModeName); + if (type.HasValue ()) { + element.opening.floorPlanParameters.connectionMode = type.Get (); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.connectionMode); + } + } + + if (os.Contains (Opening::CutSurfacesUseLineOfCutElements)) { + os.Get (Opening::CutSurfacesUseLineOfCutElements, element.opening.floorPlanParameters.cutSurfacesParameters.useLineOfCutElements); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.cutSurfacesParameters.useLineOfCutElements); + } + + if (os.Contains (Opening::CutSurfacesLinePenIndex)) { + os.Get (Opening::CutSurfacesLinePenIndex, element.opening.floorPlanParameters.cutSurfacesParameters.linePenIndex); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.cutSurfacesParameters.linePenIndex); + } + + GS::UniString attributeName; + if (os.Contains (Opening::CutSurfacesLineIndex)) { + + os.Get (Opening::CutSurfacesLineIndex, attributeName); + + if (!attributeName.IsEmpty ()) { + API_Attribute attrib; + BNZeroMemory (&attrib, sizeof (API_Attribute)); + attrib.header.typeID = API_LinetypeID; + CHCopyC (attributeName.ToCStr (), attrib.header.name); + + if (NoError == ACAPI_Attribute_Get (&attrib)) { + element.opening.floorPlanParameters.cutSurfacesParameters.lineIndex = attrib.header.index; + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.cutSurfacesParameters.lineIndex); + } + } + } + + if (os.Contains (Opening::OutlinesStyle)) { + GS::UniString outlinesStyleName; + os.Get (Opening::OutlinesStyle, outlinesStyleName); + + GS::Optional type = openingOutlinesStyleNames.FindValue (outlinesStyleName); + if (type.HasValue ()) { + element.opening.floorPlanParameters.outlinesParameters.outlinesStyle = type.Get (); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.outlinesParameters.outlinesStyle); + } + } + + if (os.Contains (Opening::OutlinesUseLineOfCutElements)) { + os.Get (Opening::OutlinesUseLineOfCutElements, element.opening.floorPlanParameters.outlinesParameters.useLineOfCutElements); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.outlinesParameters.useLineOfCutElements); + } + + if (os.Contains (Opening::OutlinesUncutLineIndex)) { + + os.Get (Opening::OutlinesUncutLineIndex, attributeName); + + if (!attributeName.IsEmpty ()) { + API_Attribute attrib; + BNZeroMemory (&attrib, sizeof (API_Attribute)); + attrib.header.typeID = API_LinetypeID; + CHCopyC (attributeName.ToCStr (), attrib.header.name); + + if (NoError == ACAPI_Attribute_Get (&attrib)) { + element.opening.floorPlanParameters.outlinesParameters.uncutLineIndex = attrib.header.index; + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.outlinesParameters.uncutLineIndex); + } + } + } + + if (os.Contains (Opening::OutlinesOverheadLineIndex)) { + + os.Get (Opening::OutlinesOverheadLineIndex, attributeName); + + if (!attributeName.IsEmpty ()) { + API_Attribute attrib; + BNZeroMemory (&attrib, sizeof (API_Attribute)); + attrib.header.typeID = API_LinetypeID; + CHCopyC (attributeName.ToCStr (), attrib.header.name); + + if (NoError == ACAPI_Attribute_Get (&attrib)) { + element.opening.floorPlanParameters.outlinesParameters.overheadLineIndex = attrib.header.index; + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.outlinesParameters.overheadLineIndex); + } + } + } + + if (os.Contains (Opening::OutlinesOverheadLinePenIndex)) { + os.Get (Opening::OutlinesOverheadLinePenIndex, element.opening.floorPlanParameters.outlinesParameters.overheadLinePenIndex); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.outlinesParameters.overheadLinePenIndex); + } + + if (os.Contains (Opening::UseCoverFills)) { + os.Get (Opening::UseCoverFills, element.opening.floorPlanParameters.coverFillsParameters.useCoverFills); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.coverFillsParameters.useCoverFills); + } + + if (os.Contains (Opening::UseFillsOfCutElements)) { + os.Get (Opening::UseFillsOfCutElements, element.opening.floorPlanParameters.coverFillsParameters.useFillsOfCutElements); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.coverFillsParameters.useFillsOfCutElements); + } + + if (os.Contains (Opening::CoverFillIndex)) { + + os.Get (Opening::CoverFillIndex, attributeName); + + if (!attributeName.IsEmpty ()) { + API_Attribute attrib; + BNZeroMemory (&attrib, sizeof (API_Attribute)); + attrib.header.typeID = API_FilltypeID; + CHCopyC (attributeName.ToCStr (), attrib.header.name); + + if (NoError == ACAPI_Attribute_Get (&attrib)) { + element.opening.floorPlanParameters.coverFillsParameters.coverFillIndex = attrib.header.index; + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.coverFillsParameters.coverFillIndex); + } + } + } + + if (os.Contains (Opening::CoverFillPenIndex)) { + os.Get (Opening::CoverFillPenIndex, element.opening.floorPlanParameters.coverFillsParameters.coverFillPenIndex); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.coverFillsParameters.coverFillPenIndex); + } + + if (os.Contains (Opening::CoverFillBackgroundPenIndex)) { + os.Get (Opening::CoverFillBackgroundPenIndex, element.opening.floorPlanParameters.coverFillsParameters.coverFillBackgroundPenIndex); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.coverFillsParameters.coverFillBackgroundPenIndex); + } + + if (os.Contains (Opening::CoverFillOrientation)) { + os.Get (Opening::CoverFillOrientation, element.opening.floorPlanParameters.coverFillsParameters.coverFillOrientation); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.coverFillsParameters.coverFillOrientation); + } + + if (os.Contains (Opening::CoverFillTransformationOrigoX)) { + os.Get (Opening::CoverFillTransformationOrigoX, element.opening.floorPlanParameters.coverFillTransformation.origo.x); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.coverFillTransformation.origo.x); + } + + if (os.Contains (Opening::CoverFillTransformationOrigoY)) { + os.Get (Opening::CoverFillTransformationOrigoY, element.opening.floorPlanParameters.coverFillTransformation.origo.y); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.coverFillTransformation.origo.y); + } + + if (os.Contains (Opening::CoverFillTransformationXAxisX)) { + os.Get (Opening::CoverFillTransformationXAxisX, element.opening.floorPlanParameters.coverFillTransformation.xAxis.x); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.coverFillTransformation.xAxis.x); + } + + if (os.Contains (Opening::CoverFillTransformationXAxisY)) { + os.Get (Opening::CoverFillTransformationXAxisY, element.opening.floorPlanParameters.coverFillTransformation.xAxis.y); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.coverFillTransformation.xAxis.y); + } + + if (os.Contains (Opening::CoverFillTransformationYAxisX)) { + os.Get (Opening::CoverFillTransformationYAxisX, element.opening.floorPlanParameters.coverFillTransformation.yAxis.x); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.coverFillTransformation.yAxis.x); + } + + if (os.Contains (Opening::CoverFillTransformationYAxisY)) { + os.Get (Opening::CoverFillTransformationYAxisY, element.opening.floorPlanParameters.coverFillTransformation.yAxis.y); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.coverFillTransformation.yAxis.y); + } + + if (os.Contains (Opening::ShowReferenceAxis)) { + os.Get (Opening::ShowReferenceAxis, element.opening.floorPlanParameters.referenceAxisParameters.showReferenceAxis); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.referenceAxisParameters.showReferenceAxis); + } + + if (os.Contains (Opening::ReferenceAxisPenIndex)) { + os.Get (Opening::ReferenceAxisPenIndex, element.opening.floorPlanParameters.referenceAxisParameters.referenceAxisPenIndex); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.referenceAxisParameters.referenceAxisPenIndex); + } + + if (os.Contains (Opening::ReferenceAxisLineTypeIndex)) { + + os.Get (Opening::ReferenceAxisLineTypeIndex, attributeName); + + if (!attributeName.IsEmpty ()) { + API_Attribute attrib; + BNZeroMemory (&attrib, sizeof (API_Attribute)); + attrib.header.typeID = API_LinetypeID; + CHCopyC (attributeName.ToCStr (), attrib.header.name); + + if (NoError == ACAPI_Attribute_Get (&attrib)) { + element.opening.floorPlanParameters.referenceAxisParameters.referenceAxisLineTypeIndex = attrib.header.index; + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.referenceAxisParameters.referenceAxisLineTypeIndex); + } + } + } + + if (os.Contains (Opening::ReferenceAxisOverhang)) { + os.Get (Opening::ReferenceAxisOverhang, element.opening.floorPlanParameters.referenceAxisParameters.referenceAxisOverhang); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, floorPlanParameters.referenceAxisParameters.referenceAxisOverhang); + } + + Objects::Point3D basePoint; + if (os.Contains (Opening::ExtrusionGeometryBasePoint)) { + os.Get (Opening::ExtrusionGeometryBasePoint, basePoint); + element.opening.extrusionGeometryData.frame.basePoint = basePoint.ToAPI_Coord3D (); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, extrusionGeometryData.frame.basePoint); + } + + Objects::Vector3D axisX; + if (os.Contains (Opening::ExtrusionGeometryXAxis)) { + os.Get (Opening::ExtrusionGeometryXAxis, axisX); + element.opening.extrusionGeometryData.frame.axisX = axisX.ToAPI_Vector3D (); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, extrusionGeometryData.frame.axisX); + } + + Objects::Vector3D axisY; + if (os.Contains (Opening::ExtrusionGeometryYAxis)) { + os.Get (Opening::ExtrusionGeometryYAxis, axisY); + element.opening.extrusionGeometryData.frame.axisY = axisY.ToAPI_Vector3D (); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, extrusionGeometryData.frame.axisY); + } + + Objects::Vector3D axisZ; + if (os.Contains (Opening::ExtrusionGeometryZAxis)) { + os.Get (Opening::ExtrusionGeometryZAxis, axisZ); + element.opening.extrusionGeometryData.frame.axisZ = axisZ.ToAPI_Vector3D (); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, extrusionGeometryData.frame.axisZ); + } + + if (os.Contains (Opening::BasePolygonType)) { + GS::UniString basePolygonTypeName; + os.Get (Opening::BasePolygonType, basePolygonTypeName); + + GS::Optional type = openingBasePolygonTypeNames.FindValue (basePolygonTypeName); + if (type.HasValue ()) { + element.opening.extrusionGeometryData.parameters.basePolygonType = type.Get (); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, extrusionGeometryData.parameters.basePolygonType); + } + } + + if (os.Contains (Opening::Width)) { + os.Get (Opening::Width, element.opening.extrusionGeometryData.parameters.width); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, extrusionGeometryData.parameters.width); + + element.opening.extrusionGeometryData.parameters.linkedStatus = API_OpeningNotLinked; + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, extrusionGeometryData.parameters.linkedStatus); + } + + if (os.Contains (Opening::Height)) { + os.Get (Opening::Height, element.opening.extrusionGeometryData.parameters.height); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, extrusionGeometryData.parameters.height); + + element.opening.extrusionGeometryData.parameters.linkedStatus = API_OpeningNotLinked; + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, extrusionGeometryData.parameters.linkedStatus); + } + + if (os.Contains (Opening::Constraint)) { + os.Get (Opening::Constraint, element.opening.extrusionGeometryData.parameters.constraint); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, extrusionGeometryData.parameters.constraint); + } + + if (os.Contains (Opening::AnchorIndex)) { + os.Get (Opening::AnchorIndex, element.opening.extrusionGeometryData.parameters.anchor); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, extrusionGeometryData.parameters.anchor); + } + + if (os.Contains (Opening::AnchorAltitude)) { + os.Get (Opening::AnchorAltitude, element.opening.extrusionGeometryData.parameters.anchorAltitude); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, extrusionGeometryData.parameters.anchorAltitude); + } + + if (os.Contains (Opening::LimitType)) { + GS::UniString limitTypeName; + os.Get (Opening::LimitType, limitTypeName); + + GS::Optional type = openingLimitTypeNames.FindValue (limitTypeName); + if (type.HasValue ()) { + element.opening.extrusionGeometryData.parameters.limitType = type.Get (); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, extrusionGeometryData.parameters.limitType); + } + } + + if (os.Contains (Opening::ExtrusionStartOffSet)) { + os.Get (Opening::ExtrusionStartOffSet, element.opening.extrusionGeometryData.parameters.extrusionStartOffset); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, extrusionGeometryData.parameters.extrusionStartOffset); + } + + if (os.Contains (Opening::FiniteBodyLength)) { + os.Get (Opening::FiniteBodyLength, element.opening.extrusionGeometryData.parameters.finiteBodyLength); + ACAPI_ELEMENT_MASK_SET (elementMask, API_OpeningType, extrusionGeometryData.parameters.finiteBodyLength); + } + + return err; +} + + +GS::String CreateOpening::GetName () const +{ + return CreateOpeningCommandName; +} + + +} \ No newline at end of file diff --git a/ConnectorArchicad/AddOn/Sources/AddOn/Commands/CreateOpening.hpp b/ConnectorArchicad/AddOn/Sources/AddOn/Commands/CreateOpening.hpp new file mode 100644 index 0000000000..8c9203b298 --- /dev/null +++ b/ConnectorArchicad/AddOn/Sources/AddOn/Commands/CreateOpening.hpp @@ -0,0 +1,33 @@ +#ifndef CREATE_OPENING_HPP +#define CREATE_OPENING_HPP + +#include "CreateOpeningBase.hpp" +#include "FieldNames.hpp" + + +namespace AddOnCommands { + + +class CreateOpening : public CreateOpeningBase { + GS::String GetFieldName () const override; + GS::UniString GetUndoableCommandName () const override; + + GSErrCode GetElementFromObjectState (const GS::ObjectState& os, + API_Element& element, + API_Element& elementMask, + API_ElementMemo& memo, + GS::UInt64& memoMask, + API_SubElement** marker, + AttributeManager& attributeManager, + LibpartImportManager& libpartImportManager, + GS::Array& log) const override; + +public: + virtual GS::String GetName () const override; +}; + + +} + + +#endif // !CREATE_OPENING_HPP \ No newline at end of file diff --git a/ConnectorArchicad/AddOn/Sources/AddOn/Commands/CreateOpeningBase.cpp b/ConnectorArchicad/AddOn/Sources/AddOn/Commands/CreateOpeningBase.cpp index d9582c709a..4c91bc8095 100644 --- a/ConnectorArchicad/AddOn/Sources/AddOn/Commands/CreateOpeningBase.cpp +++ b/ConnectorArchicad/AddOn/Sources/AddOn/Commands/CreateOpeningBase.cpp @@ -29,7 +29,8 @@ bool CreateOpeningBase::CheckEnvironment (const GS::ObjectState& os, API_Element bool isParentWall = Utility::GetElementType (parentArchicadId) == API_WallID; bool isParentRoof = Utility::GetElementType (parentArchicadId) == API_RoofID; bool isParentShell = Utility::GetElementType (parentArchicadId) == API_ShellID; - if (!(parentExists && (isParentWall || isParentRoof || isParentShell))) { + bool isParentSlab = Utility::GetElementType (parentArchicadId) == API_SlabID; + if (!(parentExists && (isParentWall || isParentRoof || isParentShell || isParentSlab))) { return false; } @@ -45,6 +46,8 @@ bool CreateOpeningBase::CheckEnvironment (const GS::ObjectState& os, API_Element Utility::SetElementType (elem.header, API_RoofID); } else if (isParentShell) { Utility::SetElementType (elem.header, API_ShellID); + } else if (isParentSlab) { + Utility::SetElementType (elem.header, API_SlabID); } elem.header.guid = parentArchicadId; @@ -61,6 +64,10 @@ bool CreateOpeningBase::CheckEnvironment (const GS::ObjectState& os, API_Element element.window.owner = parentArchicadId; } else if (elementType == API_SkylightID) { element.skylight.owner = parentArchicadId; + } else if (elementType == API_OpeningID) { + element.opening.owner = parentArchicadId; + } else if (elementType == API_SlabID) { + element.opening.owner = parentArchicadId; } return true; diff --git a/ConnectorArchicad/AddOn/Sources/AddOn/Commands/GetDoorData.hpp b/ConnectorArchicad/AddOn/Sources/AddOn/Commands/GetDoorData.hpp index 317ad154f1..a5a69c739b 100644 --- a/ConnectorArchicad/AddOn/Sources/AddOn/Commands/GetDoorData.hpp +++ b/ConnectorArchicad/AddOn/Sources/AddOn/Commands/GetDoorData.hpp @@ -1,5 +1,5 @@ -#ifndef GET_OPENING_DATA_HPP -#define GET_OPENING_DATA_HPP +#ifndef GET_DOOR_DATA_HPP +#define GET_DOOR_DATA_HPP #include "GetDataCommand.hpp" diff --git a/ConnectorArchicad/AddOn/Sources/AddOn/Commands/GetOpeningData.cpp b/ConnectorArchicad/AddOn/Sources/AddOn/Commands/GetOpeningData.cpp new file mode 100644 index 0000000000..54e4f1691f --- /dev/null +++ b/ConnectorArchicad/AddOn/Sources/AddOn/Commands/GetOpeningData.cpp @@ -0,0 +1,156 @@ +#include "GetOpeningData.hpp" +#include "ResourceIds.hpp" +#include "ObjectState.hpp" +#include "Utility.hpp" +#include "Objects/Point.hpp" +#include "Objects/Vector.hpp" +#include "RealNumber.h" +#include "FieldNames.hpp" +#include "TypeNameTables.hpp" +using namespace FieldNames; + + +namespace AddOnCommands { + + +GS::String GetOpeningData::GetFieldName () const +{ + return Openings; +} + + +API_ElemTypeID GetOpeningData::GetElemTypeID () const +{ + return API_OpeningID; +} + + +GS::ErrCode GetOpeningData::SerializeElementType (const API_Element& element, + const API_ElementMemo& /*memo*/, + GS::ObjectState& os) const +{ + os.Add (ElementBase::ParentElementId, APIGuidToString (element.opening.owner)); + + API_Attribute attrib; + + // Opening Floor Parameters + os.Add (Opening::FloorPlanDisplayMode, openingFloorPlanDisplayModeNames.Get (element.opening.floorPlanParameters.floorPlanDisplayMode)); + os.Add (Opening::ConnectionMode, openingFloorPlanConnectionModeNames.Get (element.opening.floorPlanParameters.connectionMode)); + + // Opening Floor Plan Parameters - Cut Surfaces + os.Add (Opening::CutSurfacesUseLineOfCutElements, element.opening.floorPlanParameters.cutSurfacesParameters.useLineOfCutElements); + os.Add (Opening::CutSurfacesLinePenIndex, element.opening.floorPlanParameters.cutSurfacesParameters.linePenIndex); + BNZeroMemory (&attrib, sizeof (API_Attribute)); + attrib.header.typeID = API_LinetypeID; + attrib.header.index = element.opening.floorPlanParameters.cutSurfacesParameters.lineIndex; + + if (NoError == ACAPI_Attribute_Get (&attrib)) { + os.Add (Opening::CutSurfacesLineIndex, GS::UniString{attrib.header.name}); + } + + // Opening Floor Plan Parameters - Outlines Parameters + os.Add (Opening::OutlinesStyle, openingOutlinesStyleNames.Get (element.opening.floorPlanParameters.outlinesParameters.outlinesStyle)); + os.Add (Opening::OutlinesUseLineOfCutElements, element.opening.floorPlanParameters.outlinesParameters.useLineOfCutElements); + + BNZeroMemory (&attrib, sizeof (API_Attribute)); + attrib.header.typeID = API_LinetypeID; + attrib.header.index = element.opening.floorPlanParameters.outlinesParameters.uncutLineIndex; + + if (NoError == ACAPI_Attribute_Get (&attrib)) { + os.Add (Opening::OutlinesUncutLineIndex, GS::UniString{attrib.header.name}); + } + + BNZeroMemory (&attrib, sizeof (API_Attribute)); + attrib.header.typeID = API_LinetypeID; + attrib.header.index = element.opening.floorPlanParameters.outlinesParameters.overheadLineIndex; + + if (NoError == ACAPI_Attribute_Get (&attrib)) { + os.Add (Opening::OutlinesOverheadLineIndex, GS::UniString{attrib.header.name}); + } + + BNZeroMemory (&attrib, sizeof (API_Attribute)); + attrib.header.typeID = API_LinetypeID; + attrib.header.index = element.opening.floorPlanParameters.outlinesParameters.uncutLineIndex; + + if (NoError == ACAPI_Attribute_Get (&attrib)) { + os.Add (Opening::OutlinesUncutLineIndex, GS::UniString{attrib.header.name}); + } + os.Add (Opening::OutlinesOverheadLinePenIndex, element.opening.floorPlanParameters.outlinesParameters.overheadLinePenIndex); + + // Opening Floor Plan Parameters - Cover Fills + os.Add (Opening::UseCoverFills, element.opening.floorPlanParameters.coverFillsParameters.useCoverFills); + if (element.opening.floorPlanParameters.coverFillsParameters.useCoverFills) { + os.Add (Opening::UseFillsOfCutElements, element.opening.floorPlanParameters.coverFillsParameters.useFillsOfCutElements); + + BNZeroMemory (&attrib, sizeof (API_Attribute)); + attrib.header.typeID = API_FilltypeID; + attrib.header.index = element.opening.floorPlanParameters.coverFillsParameters.coverFillIndex; + + if (NoError == ACAPI_Attribute_Get (&attrib)) { + os.Add (Opening::CoverFillIndex, GS::UniString{attrib.header.name}); + } + + os.Add (Opening::CoverFillPenIndex, element.opening.floorPlanParameters.coverFillsParameters.coverFillPenIndex); + os.Add (Opening::CoverFillBackgroundPenIndex, element.opening.floorPlanParameters.coverFillsParameters.coverFillBackgroundPenIndex); + os.Add (Opening::CoverFillOrientation, element.opening.floorPlanParameters.coverFillsParameters.coverFillOrientation); + } + + // Opening Floor Plan Parameters - Cover Fill Transformation + os.Add (Opening::CoverFillTransformationOrigoX, element.opening.floorPlanParameters.coverFillTransformation.origo.x); + os.Add (Opening::CoverFillTransformationOrigoY, element.opening.floorPlanParameters.coverFillTransformation.origo.y); + os.Add (Opening::CoverFillTransformationXAxisX, element.opening.floorPlanParameters.coverFillTransformation.xAxis.x); + os.Add (Opening::CoverFillTransformationXAxisY, element.opening.floorPlanParameters.coverFillTransformation.xAxis.y); + os.Add (Opening::CoverFillTransformationYAxisX, element.opening.floorPlanParameters.coverFillTransformation.yAxis.x); + os.Add (Opening::CoverFillTransformationYAxisY, element.opening.floorPlanParameters.coverFillTransformation.yAxis.y); + + // Opening Floor Plan Parameters - Reference Axis + os.Add (Opening::ShowReferenceAxis, element.opening.floorPlanParameters.referenceAxisParameters.showReferenceAxis); + if (element.opening.floorPlanParameters.referenceAxisParameters.showReferenceAxis) { + os.Add (Opening::ReferenceAxisPenIndex, element.opening.floorPlanParameters.referenceAxisParameters.referenceAxisPenIndex); + + BNZeroMemory (&attrib, sizeof (API_Attribute)); + attrib.header.typeID = API_LinetypeID; + attrib.header.index = element.opening.floorPlanParameters.referenceAxisParameters.referenceAxisLineTypeIndex; + + if (NoError == ACAPI_Attribute_Get (&attrib)) { + os.Add (Opening::ReferenceAxisLineTypeIndex, GS::UniString{attrib.header.name}); + } + + os.Add (Opening::ReferenceAxisOverhang, element.opening.floorPlanParameters.referenceAxisParameters.referenceAxisOverhang); + } + + // Extrusion Geometry + os.Add (Opening::ExtrusionGeometryBasePoint, Objects::Point3D (element.opening.extrusionGeometryData.frame.basePoint)); + os.Add (Opening::ExtrusionGeometryXAxis, Objects::Vector3D(element.opening.extrusionGeometryData.frame.axisX)); + os.Add (Opening::ExtrusionGeometryYAxis, Objects::Vector3D (element.opening.extrusionGeometryData.frame.axisY)); + os.Add (Opening::ExtrusionGeometryZAxis, Objects::Vector3D (element.opening.extrusionGeometryData.frame.axisZ)); + + // Extrusion Geometry - Opening Extrusion Parameters + os.Add (Opening::BasePolygonType, openingBasePolygonTypeNames.Get (element.opening.extrusionGeometryData.parameters.basePolygonType)); + os.Add (Opening::Width, element.opening.extrusionGeometryData.parameters.width); + os.Add (Opening::Height, element.opening.extrusionGeometryData.parameters.height); + os.Add (Opening::Constraint, element.opening.extrusionGeometryData.parameters.constraint); + os.Add (Opening::Anchor, openingAnchorNames.Get (element.opening.extrusionGeometryData.parameters.anchor)); + os.Add (Opening::AnchorIndex, (element.opening.extrusionGeometryData.parameters.anchor)); + os.Add (Opening::AnchorAltitude, element.opening.extrusionGeometryData.parameters.anchorAltitude); + os.Add (Opening::LimitType, openingLimitTypeNames.Get (element.opening.extrusionGeometryData.parameters.limitType)); + os.Add (Opening::ExtrusionStartOffSet, element.opening.extrusionGeometryData.parameters.extrusionStartOffset); + os.Add (Opening::FiniteBodyLength, element.opening.extrusionGeometryData.parameters.finiteBodyLength); + os.Add (Opening::LinkedStatus, openingLinkedStatusNames.Get (element.opening.extrusionGeometryData.parameters.linkedStatus)); + + // Extrusion Geometry - Custom Base Polygon + if (element.opening.extrusionGeometryData.parameters.basePolygonType == API_OpeningBasePolygonCustom) { + // Reserved for future use + } + + return NoError; +} + + +GS::String GetOpeningData::GetName () const +{ + return GetOpeningDataCommandName; +} + + +} // namespace AddOnCommands diff --git a/ConnectorArchicad/AddOn/Sources/AddOn/Commands/GetOpeningData.hpp b/ConnectorArchicad/AddOn/Sources/AddOn/Commands/GetOpeningData.hpp new file mode 100644 index 0000000000..0a30edd766 --- /dev/null +++ b/ConnectorArchicad/AddOn/Sources/AddOn/Commands/GetOpeningData.hpp @@ -0,0 +1,24 @@ +#ifndef GET_OPENING_DATA_HPP +#define GET_OPENING_DATA_HPP + +#include "GetDataCommand.hpp" + +namespace AddOnCommands { + + +class GetOpeningData : public GetDataCommand { + GS::String GetFieldName() const override; + API_ElemTypeID GetElemTypeID() const override; + GS::ErrCode SerializeElementType(const API_Element& elem, + const API_ElementMemo& memo, + GS::ObjectState& os) const override; + +public: + virtual GS::String GetName() const override; +}; + + +} + + +#endif // GET_OPENING_DATA_HPP \ No newline at end of file diff --git a/ConnectorArchicad/AddOn/Sources/AddOn/FieldNames.hpp b/ConnectorArchicad/AddOn/Sources/AddOn/FieldNames.hpp index 64c80772da..3b05a70287 100644 --- a/ConnectorArchicad/AddOn/Sources/AddOn/FieldNames.hpp +++ b/ConnectorArchicad/AddOn/Sources/AddOn/FieldNames.hpp @@ -83,6 +83,7 @@ static const char* Slabs = "slabs"; static const char* Walls = "walls"; static const char* Windows = "windows"; static const char* Zones = "zones"; +static const char* Openings = "openings"; static const char* Models = "models"; static const char* SubelementModels = "subelementModels"; @@ -474,6 +475,73 @@ static const char* pos = "pos"; static const char* transform = "transform"; } + +namespace Opening +{ +// Floor Plan Parameters +static const char* FloorPlanDisplayMode = "floorPlanDisplayMode"; +static const char* ConnectionMode = "connectionMode"; + +// Cut Surfaces Parameters +static const char* CutSurfacesUseLineOfCutElements = "cutsurfacesUseLineOfCutElements"; +static const char* CutSurfacesLinePenIndex = "cutsurfacesLinePenIndex"; +static const char* CutSurfacesLineIndex = "cutsurfacesLineIndex"; + +// Outlines Parameters +static const char* OutlinesStyle = "outlinesStyle"; +static const char* OutlinesUseLineOfCutElements = "outlinesUseLineOfCutElements"; // => Cut Surfaces Parameters-ben is megtalálható +static const char* OutlinesUncutLineIndex = "outlinesUncutLineIndex"; +static const char* OutlinesOverheadLineIndex = "outlinesOverheadLineIndex"; +static const char* OutlinesUncutLinePenIndex = "outlinesUncutLinePenIndex"; +static const char* OutlinesOverheadLinePenIndex = "outlinesOverheadLinePenIndex"; + +// Opening Cover Fills Parameters +static const char* UseCoverFills = "useCoverFills"; +static const char* UseFillsOfCutElements = "useFillsOfCutElements"; +static const char* CoverFillIndex = "coverFillIndex"; +static const char* CoverFillPenIndex = "coverFillPenIndex"; +static const char* CoverFillBackgroundPenIndex = "coverFillBackgroundPenIndex"; +static const char* CoverFillOrientation = "coverFillOrientation"; + +// Cover Fill Transformation Parameters +static const char* CoverFillTransformationOrigoX = "coverFillTransformationOrigoX"; +static const char* CoverFillTransformationOrigoY = "coverFillTransformationOrigoY"; +static const char* CoverFillTransformationOrigoZ = "coverFillTransformationOrigoZ"; +static const char* CoverFillTransformationXAxisX = "coverFillTransformationXAxisX"; +static const char* CoverFillTransformationXAxisY = "coverFillTransformationXAxisY"; +static const char* CoverFillTransformationXAxisZ = "coverFillTransformationXAxisZ"; +static const char* CoverFillTransformationYAxisX = "coverFillTransformationYAxisX"; +static const char* CoverFillTransformationYAxisY = "coverFillTransformationYAxisY"; +static const char* CoverFillTransformationYAxisZ = "coverFillTransformationYAxisZ"; + +// Reference Axis Parameters +static const char* ShowReferenceAxis = "showReferenceAxis"; +static const char* ReferenceAxisPenIndex = "referenceAxisPenIndex"; +static const char* ReferenceAxisLineTypeIndex = "referenceAxisLineTypeIndex"; +static const char* ReferenceAxisOverhang = "referenceAxisOverhang"; + +// Extrusion Geometry Parameters +static const char* ExtrusionGeometryBasePoint = "extrusionGeometryBasePoint"; +static const char* ExtrusionGeometryXAxis = "extrusionGeometryXAxis"; +static const char* ExtrusionGeometryYAxis = "extrusionGeometryYAxis"; +static const char* ExtrusionGeometryZAxis = "extrusionGeometryZAxis"; +static const char* BasePolygonType = "basePolygonType"; +static const char* Width = "width"; +static const char* Height = "height"; +static const char* Constraint = "constraint"; +static const char* Anchor = "anchor"; +static const char* AnchorIndex = "anchorIndex"; +static const char* AnchorAltitude = "anchorAltitude"; +static const char* LimitType = "limitType"; +static const char* ExtrusionStartOffSet = "extrusionStartOffSet"; +static const char* FiniteBodyLength = "finiteBodyLength"; +static const char* LinkedStatus = "linkedStatus"; +static const char* NCoords = "nCoords"; +static const char* NSubPolys = "nSubPolys"; +static const char* NArcs = "nArcs"; +} + + namespace GridElement { // Main diff --git a/ConnectorArchicad/AddOn/Sources/AddOn/ResourceIds.hpp b/ConnectorArchicad/AddOn/Sources/AddOn/ResourceIds.hpp index 147706b24e..3b71424e11 100644 --- a/ConnectorArchicad/AddOn/Sources/AddOn/ResourceIds.hpp +++ b/ConnectorArchicad/AddOn/Sources/AddOn/ResourceIds.hpp @@ -24,6 +24,7 @@ #define GetElementBaseDataCommandName "GetElementBaseData"; #define GetGridElementCommandName "GetGridElementData"; #define GetObjectDataCommandName "GetObjectData"; +#define GetOpeningDataCommandName "GetOpeningData"; #define GetSlabDataCommandName "GetSlabData"; #define GetRoomDataCommandName "GetRoomData"; #define GetRoofDataCommandName "GetRoofData"; @@ -38,6 +39,7 @@ #define CreateColumnCommandName "CreateColumn"; #define CreateGridElementCommandName "CreateGridElement"; #define CreateObjectCommandName "CreateObject"; +#define CreateOpeningCommandName "CreateOpening"; #define CreateSlabCommandName "CreateSlab"; #define CreateSkylightCommandName "CreateSkylight"; #define CreateRoofCommandName "CreateRoof"; diff --git a/ConnectorArchicad/AddOn/Sources/AddOn/TypeNameTables.cpp b/ConnectorArchicad/AddOn/Sources/AddOn/TypeNameTables.cpp index 52c35275b6..610edbc1cc 100644 --- a/ConnectorArchicad/AddOn/Sources/AddOn/TypeNameTables.cpp +++ b/ConnectorArchicad/AddOn/Sources/AddOn/TypeNameTables.cpp @@ -301,3 +301,63 @@ const GS::HashTable coreSymbolTypeNames { 3, "X"}, { 4, "CrossHair"} }; + + +const GS::HashTable openingFloorPlanDisplayModeNames +{ + { API_OpeningSymbolic, "Symbolic"}, + { API_OpeningSymbolicCut, "Symbolic Cut"}, + { API_OpeningSymbolicOverhead, "Symbolic Overhead"} +}; + + +const GS::HashTable openingFloorPlanConnectionModeNames +{ + { API_OpeningDisconnected, "Disconnected"}, + { API_OpeningConnected, "Connected"} +}; + + +const GS::HashTable openingOutlinesStyleNames +{ + { API_OpeningHideBorder, "Hide Border"}, + { API_OpeningShowUncutBorder, "Show Uncut Border"}, + { API_OpeningShowOverheadBorder, "Show Overhead Border"} +}; + + +const GS::HashTable openingBasePolygonTypeNames +{ + { API_OpeningBasePolygonRectangular, "Rectangular"}, + { API_OpeningBasePolygonCircular, "Circular"}, + { API_OpeningBasePolygonCustom, "Custom"} +}; + + +const GS::HashTable openingAnchorNames +{ + { APIAnc_LT, "Left Top"}, + { APIAnc_MT, "Middle Top"}, + { APIAnc_RT, "Right Top"}, + { APIAnc_LM, "Left Middle"}, + { APIAnc_MM, "Middle Middle"}, + { APIAnc_RM, "Right Middle"}, + { APIAnc_LB, "Left Bottom"}, + { APIAnc_MB, "Middle Bottom"}, + { APIAnc_RB, "Right Bottom"} +}; + + +const GS::HashTable openingLimitTypeNames +{ + { API_OpeningLimitInfinite, "Infinite"}, + { API_OpeningLimitFinite, "Finite"}, + { API_OpeningLimitHalfInfinite, "Half Infinite"} +}; + + +const GS::HashTable openingLinkedStatusNames +{ + { API_OpeningLinked, "Linked"}, + { API_OpeningNotLinked, "Not Linked"} +}; \ No newline at end of file diff --git a/ConnectorArchicad/AddOn/Sources/AddOn/TypeNameTables.hpp b/ConnectorArchicad/AddOn/Sources/AddOn/TypeNameTables.hpp index b478c0ca60..12d8488997 100644 --- a/ConnectorArchicad/AddOn/Sources/AddOn/TypeNameTables.hpp +++ b/ConnectorArchicad/AddOn/Sources/AddOn/TypeNameTables.hpp @@ -45,4 +45,12 @@ extern const GS::HashTable venTypeNames; extern const GS::HashTable coreSymbolTypeNames; +extern const GS::HashTable openingFloorPlanDisplayModeNames; +extern const GS::HashTable openingFloorPlanConnectionModeNames; +extern const GS::HashTable openingOutlinesStyleNames; +extern const GS::HashTable openingBasePolygonTypeNames; +extern const GS::HashTable openingAnchorNames; + +extern const GS::HashTable openingLimitTypeNames; +extern const GS::HashTable openingLinkedStatusNames; #endif diff --git a/ConnectorArchicad/AddOn/Sources/AddOnResources/RFIX/AddOnFix.grc b/ConnectorArchicad/AddOn/Sources/AddOnResources/RFIX/AddOnFix.grc index 02d663f4d1..6ad0e355df 100644 --- a/ConnectorArchicad/AddOn/Sources/AddOnResources/RFIX/AddOnFix.grc +++ b/ConnectorArchicad/AddOn/Sources/AddOnResources/RFIX/AddOnFix.grc @@ -6,9 +6,15 @@ AC_MDID_LOC /* Set AC_MDID_LOC value as your local id. */ } +#ifdef macintosh 'GICN' 10001 "AddOnIcon" { - "AddOnIcon" + "AddOnIconMac" } +#else +'GICN' 10001 "AddOnIcon" { + "AddOnIconWin" +} +#endif 'STR#' ID_FIX_ELEMENT_TYPE_STRINGS "Element Type Strings" { /* [ 1] */ "Wall" diff --git a/ConnectorArchicad/AddOn/Sources/AddOnResources/RFIX/Images/AddOnIconMac_18x18.svg b/ConnectorArchicad/AddOn/Sources/AddOnResources/RFIX/Images/AddOnIconMac_18x18.svg new file mode 100644 index 0000000000..0f1cfa4bb2 --- /dev/null +++ b/ConnectorArchicad/AddOn/Sources/AddOnResources/RFIX/Images/AddOnIconMac_18x18.svg @@ -0,0 +1,18 @@ + + AddOnIcon_18x18-svg + + + + + + + + + + + + + + \ No newline at end of file diff --git a/ConnectorArchicad/AddOn/Sources/AddOnResources/RFIX/Images/AddOnIconWin_18x18.svg b/ConnectorArchicad/AddOn/Sources/AddOnResources/RFIX/Images/AddOnIconWin_18x18.svg new file mode 100644 index 0000000000..fbe59e2a11 --- /dev/null +++ b/ConnectorArchicad/AddOn/Sources/AddOnResources/RFIX/Images/AddOnIconWin_18x18.svg @@ -0,0 +1,17 @@ + + AddOnIconWin_18x18-svg + + + + + + + + + + + \ No newline at end of file diff --git a/ConnectorArchicad/AddOn/Sources/AddOnResources/RFIX/Images/AddOnIcon_18x18.svg b/ConnectorArchicad/AddOn/Sources/AddOnResources/RFIX/Images/AddOnIcon_18x18.svg deleted file mode 100644 index 4031449236..0000000000 --- a/ConnectorArchicad/AddOn/Sources/AddOnResources/RFIX/Images/AddOnIcon_18x18.svg +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/ConnectorArchicad/ConnectorArchicad/Assets/icon-mac.icns b/ConnectorArchicad/ConnectorArchicad/Assets/icon-mac.icns new file mode 100644 index 0000000000..6ef6c0c333 Binary files /dev/null and b/ConnectorArchicad/ConnectorArchicad/Assets/icon-mac.icns differ diff --git a/ConnectorArchicad/ConnectorArchicad/Communication/Commands/Command_CreateOpening.cs b/ConnectorArchicad/ConnectorArchicad/Communication/Commands/Command_CreateOpening.cs new file mode 100644 index 0000000000..ab65f3dde1 --- /dev/null +++ b/ConnectorArchicad/ConnectorArchicad/Communication/Commands/Command_CreateOpening.cs @@ -0,0 +1,42 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using Speckle.Core.Models; +using Speckle.Newtonsoft.Json; +using Objects.BuiltElements.Archicad; + +namespace Archicad.Communication.Commands; + +sealed internal class CreateOpening : ICommand> +{ + [JsonObject(MemberSerialization.OptIn)] + public sealed class Parameters + { + [JsonProperty("openings")] + private IEnumerable Datas { get; } + + public Parameters(IEnumerable datas) + { + Datas = datas; + } + } + + [JsonObject(MemberSerialization.OptIn)] + private sealed class Result + { + [JsonProperty("applicationObjects")] + public IEnumerable ApplicationObjects { get; private set; } + } + + private IEnumerable Datas { get; } + + public CreateOpening(IEnumerable datas) + { + Datas = datas; + } + + public async Task> Execute() + { + var result = await HttpCommandExecutor.Execute("CreateOpening", new Parameters(Datas)); + return result == null ? null : result.ApplicationObjects; + } +} diff --git a/ConnectorArchicad/ConnectorArchicad/Communication/Commands/Command_GetElementBaseData.cs b/ConnectorArchicad/ConnectorArchicad/Communication/Commands/Command_GetElementBaseData.cs index 56fe20729e..82d9499427 100644 --- a/ConnectorArchicad/ConnectorArchicad/Communication/Commands/Command_GetElementBaseData.cs +++ b/ConnectorArchicad/ConnectorArchicad/Communication/Commands/Command_GetElementBaseData.cs @@ -1,13 +1,12 @@ using System.Collections.Generic; using System.Threading.Tasks; -using Speckle.Core.Kits; -using Speckle.Newtonsoft.Json; -using Objects.BuiltElements.Archicad; using ConnectorArchicad.Communication.Commands; +using Objects.BuiltElements.Archicad; +using Speckle.Newtonsoft.Json; namespace Archicad.Communication.Commands; -sealed internal class GetElementBaseData : GetDataBase, ICommand> +sealed internal class GetElementBaseData : GetDataBase, ICommand { [JsonObject(MemberSerialization.OptIn)] private sealed class Result @@ -19,17 +18,13 @@ private sealed class Result public GetElementBaseData(IEnumerable applicationIds, bool sendProperties, bool sendListingParameters) : base(applicationIds, sendProperties, sendListingParameters) { } - public async Task> Execute() + public async Task Execute() { - Result result = await HttpCommandExecutor.Execute( + dynamic result = await HttpCommandExecutor.Execute( "GetElementBaseData", new Parameters(ApplicationIds, SendProperties, SendListingParameters) ); - foreach (var directShape in result.Datas) - { - directShape.units = Units.Meters; - } - return result.Datas; + return (Speckle.Newtonsoft.Json.Linq.JArray)result["elements"]; } } diff --git a/ConnectorArchicad/ConnectorArchicad/Communication/Commands/Command_GetOpening.cs b/ConnectorArchicad/ConnectorArchicad/Communication/Commands/Command_GetOpening.cs new file mode 100644 index 0000000000..5e64507ed7 --- /dev/null +++ b/ConnectorArchicad/ConnectorArchicad/Communication/Commands/Command_GetOpening.cs @@ -0,0 +1,21 @@ +using System.Collections.Generic; +using System.Threading.Tasks; +using ConnectorArchicad.Communication.Commands; + +namespace Archicad.Communication.Commands; + +sealed internal class GetOpeningData : GetDataBase, ICommand +{ + public GetOpeningData(IEnumerable applicationIds, bool sendProperties, bool sendListingParameters) + : base(applicationIds, sendProperties, sendListingParameters) { } + + public async Task Execute() + { + dynamic result = await HttpCommandExecutor.Execute( + "GetOpeningData", + new Parameters(ApplicationIds, SendProperties, SendListingParameters) + ); + + return (Speckle.Newtonsoft.Json.Linq.JArray)result["openings"]; + } +} diff --git a/ConnectorArchicad/ConnectorArchicad/ConnectorArchicad.csproj b/ConnectorArchicad/ConnectorArchicad/ConnectorArchicad.csproj index e83aa31a00..8341b16c5e 100644 --- a/ConnectorArchicad/ConnectorArchicad/ConnectorArchicad.csproj +++ b/ConnectorArchicad/ConnectorArchicad/ConnectorArchicad.csproj @@ -6,6 +6,7 @@ enable ConnectorArchicad Assets\icon.ico + true diff --git a/ConnectorArchicad/ConnectorArchicad/Converters/ConverterArchicad.cs b/ConnectorArchicad/ConnectorArchicad/Converters/ConverterArchicad.cs index 29506c6a58..c00821258c 100644 --- a/ConnectorArchicad/ConnectorArchicad/Converters/ConverterArchicad.cs +++ b/ConnectorArchicad/ConnectorArchicad/Converters/ConverterArchicad.cs @@ -68,6 +68,7 @@ public bool CanConvertToNativeImplemented(Base @object) Objects.BuiltElements.Roof _ => true, Objects.BuiltElements.Room _ => true, Objects.BuiltElements.Wall _ => true, + Objects.BuiltElements.Opening _ => true, // Archicad elements Objects.BuiltElements.Archicad.ArchicadDoor _ => true, diff --git a/ConnectorArchicad/ConnectorArchicad/Converters/Converters/DirectShapeConverter.cs b/ConnectorArchicad/ConnectorArchicad/Converters/Converters/DirectShapeConverter.cs index c47a607798..fdb4711d10 100644 --- a/ConnectorArchicad/ConnectorArchicad/Converters/Converters/DirectShapeConverter.cs +++ b/ConnectorArchicad/ConnectorArchicad/Converters/Converters/DirectShapeConverter.cs @@ -7,6 +7,7 @@ using Archicad.Model; using Archicad.Operations; using Objects.Geometry; +using Speckle.Core.Kits; using Speckle.Core.Models; using Speckle.Core.Models.GraphTraversal; @@ -73,6 +74,7 @@ CancellationToken token IEnumerable result; result = await AsyncCommandProcessor.Execute(new Communication.Commands.CreateDirectShape(directShapes), token); + return result is null ? new List() : result.ToList(); } @@ -83,7 +85,8 @@ ConversionOptions conversionOptions ) { var elementModels = elements as ElementModelData[] ?? elements.ToArray(); - IEnumerable data = await AsyncCommandProcessor.Execute( + + Speckle.Newtonsoft.Json.Linq.JArray jArray = await AsyncCommandProcessor.Execute( new Communication.Commands.GetElementBaseData( elementModels.Select(e => e.applicationId), conversionOptions.SendProperties, @@ -93,7 +96,7 @@ ConversionOptions conversionOptions ); var directShapes = new List(); - if (data is null) + if (jArray is null) { return directShapes; } @@ -103,12 +106,18 @@ ConversionOptions conversionOptions context?.cumulativeTimer?.Begin(ConnectorArchicad.Properties.OperationNameTemplates.ConvertToSpeckle, Type.Name) ) { - foreach (Objects.BuiltElements.Archicad.DirectShape directShape in data) + foreach (Speckle.Newtonsoft.Json.Linq.JToken jToken in jArray) { + // convert between DTOs + Objects.BuiltElements.Archicad.DirectShape directShape = + Archicad.Converters.Utils.ConvertToSpeckleDTOs(jToken); + { + directShape.units = Units.Meters; directShape.displayValue = Operations.ModelConverter.MeshesToSpeckle( elementModels.First(e => e.applicationId == directShape.applicationId).model ); + directShapes.Add(directShape); } } diff --git a/ConnectorArchicad/ConnectorArchicad/Converters/Converters/OpeningConverter.cs b/ConnectorArchicad/ConnectorArchicad/Converters/Converters/OpeningConverter.cs new file mode 100644 index 0000000000..a7bf40d31f --- /dev/null +++ b/ConnectorArchicad/ConnectorArchicad/Converters/Converters/OpeningConverter.cs @@ -0,0 +1,135 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Threading; +using System.Threading.Tasks; +using Archicad.Communication; +using Archicad.Model; +using Speckle.Core.Kits; +using Speckle.Core.Logging; +using Speckle.Core.Models; +using Speckle.Core.Models.GraphTraversal; + +namespace Archicad.Converters; + +public sealed class OpeningConverter : IConverter +{ + public Type Type => typeof(Objects.BuiltElements.Opening); + + public Task> ConvertToArchicad( + IEnumerable elements, + CancellationToken token + ) + { + var openings = new List(); + + var context = Archicad.Helpers.Timer.Context.Peek; + using ( + context?.cumulativeTimer?.Begin(ConnectorArchicad.Properties.OperationNameTemplates.ConvertToNative, Type.Name) + ) + { + foreach (var tc in elements) + { + token.ThrowIfCancellationRequested(); + + switch (tc.current) + { + case Objects.BuiltElements.Archicad.ArchicadOpening archicadOpening: + archicadOpening.parentApplicationId = tc.parent.current.id; + Archicad.Converters.Utils.ConvertToArchicadDTOs( + archicadOpening + ); + openings.Add(archicadOpening); + break; + case Objects.BuiltElements.Opening opening: + try + { + Objects.Geometry.Vector extrusionBasePoint, + extrusionXAxis, + extrusionYAxis, + extrusionZAxis; + double width, + height; + Operations.ModelConverter.GetExtrusionParametersFromOutline( + opening.outline, + out extrusionBasePoint, + out extrusionXAxis, + out extrusionYAxis, + out extrusionZAxis, + out width, + out height + ); + openings.Add( + new Objects.BuiltElements.Archicad.ArchicadOpening + { + id = opening.id, + applicationId = opening.applicationId, + parentApplicationId = tc.parent.current.id, + extrusionGeometryBasePoint = new Objects.Geometry.Point(extrusionBasePoint), + extrusionGeometryXAxis = extrusionXAxis, + extrusionGeometryYAxis = extrusionYAxis, + extrusionGeometryZAxis = extrusionZAxis, + width = width, + height = height, + anchorIndex = 4, + } + ); + } + catch (SpeckleException ex) + { + SpeckleLog.Logger.Error(ex.Message); + } + break; + } + } + + IEnumerable result; + result = AsyncCommandProcessor.Execute(new Communication.Commands.CreateOpening(openings), token).Result; + + return Task.FromResult(result is null ? new List() : result.ToList()); + } + } + + public async Task> ConvertToSpeckle( + IEnumerable elements, + CancellationToken token, + ConversionOptions conversionOptions + ) + { + var elementModels = elements as ElementModelData[] ?? elements.ToArray(); + + Speckle.Newtonsoft.Json.Linq.JArray jArray = await AsyncCommandProcessor.Execute( + new Communication.Commands.GetOpeningData( + elementModels.Select(e => e.applicationId), + conversionOptions.SendProperties, + conversionOptions.SendListingParameters + ), + token + ); + + List openings = new(); + if (jArray is null) + { + return openings; + } + + var context = Archicad.Helpers.Timer.Context.Peek; + using ( + context?.cumulativeTimer?.Begin(ConnectorArchicad.Properties.OperationNameTemplates.ConvertToNative, Type.Name) + ) + { + foreach (Speckle.Newtonsoft.Json.Linq.JToken jToken in jArray) + { + Objects.BuiltElements.Archicad.ArchicadOpening opening = + Archicad.Converters.Utils.ConvertToSpeckleDTOs(jToken); + { + opening.outline = Operations.ModelConverter.CreateOpeningOutline(opening); + opening.units = Units.Meters; + } + openings.Add(opening); + } + } + + return openings; + } +} diff --git a/ConnectorArchicad/ConnectorArchicad/Converters/Converters/Utils.cs b/ConnectorArchicad/ConnectorArchicad/Converters/Converters/Utils.cs index 792d1992e7..eb0e7e1477 100644 --- a/ConnectorArchicad/ConnectorArchicad/Converters/Converters/Utils.cs +++ b/ConnectorArchicad/ConnectorArchicad/Converters/Converters/Utils.cs @@ -68,6 +68,14 @@ public static MeshModel.Vertex PointToNative(Point point, string? units = null) }; } + public static Vector ScaleToNative(Vector vector, string? units = null) + { + units ??= vector.units; + var scale = Units.GetConversionFactor(units, Units.Meters); + + return new Vector(vector.x * scale, vector.y * scale, vector.z * scale); + } + public static Polycurve PolycurveToSpeckle(ElementShape.Polyline archiPolyline) { var poly = new Polycurve @@ -180,7 +188,8 @@ public static T ConvertToSpeckleDTOs(dynamic jObject) if (level != null) { - PropertyInfo propLevel = speckleObject.GetType().GetProperty("archicadLevel"); + PropertyInfo propLevel = + speckleObject.GetType().GetProperty("archicadLevel") ?? speckleObject.GetType().GetProperty("level"); propLevel.SetValue(speckleObject, level); } diff --git a/ConnectorArchicad/ConnectorArchicad/Converters/ElementConverterManager.cs b/ConnectorArchicad/ConnectorArchicad/Converters/ElementConverterManager.cs index 330860564c..287ba885c4 100644 --- a/ConnectorArchicad/ConnectorArchicad/Converters/ElementConverterManager.cs +++ b/ConnectorArchicad/ConnectorArchicad/Converters/ElementConverterManager.cs @@ -13,6 +13,7 @@ using Column = Objects.BuiltElements.Column; using Door = Objects.BuiltElements.Archicad.ArchicadDoor; using Fenestration = Objects.BuiltElements.Archicad.ArchicadFenestration; +using Opening = Objects.BuiltElements.Opening; using Floor = Objects.BuiltElements.Floor; using Roof = Objects.BuiltElements.Roof; using Wall = Objects.BuiltElements.Wall; @@ -20,6 +21,7 @@ using Skylight = Objects.BuiltElements.Archicad.ArchicadSkylight; using GridLine = Objects.BuiltElements.GridLine; using DesktopUI2.Models; +using Objects.BuiltElements.Archicad; namespace Archicad; @@ -95,13 +97,24 @@ private ElementConverterManager() allObjects.AddRange(objects); // subelements translated into "elements" property of the parent - if (typeof(Fenestration).IsAssignableFrom(elemenType)) + if (typeof(Fenestration).IsAssignableFrom(elemenType) || typeof(Opening).IsAssignableFrom(elemenType)) { Collection elementCollection = null; foreach (Base item in objects) { - Base parent = allObjects.Find(x => x.applicationId == ((Fenestration)item).parentApplicationId); + string parentApplicationId = null; + + if (item is Fenestration fenestration) + { + parentApplicationId = fenestration.parentApplicationId; + } + else if (item is ArchicadOpening opening) + { + parentApplicationId = opening.parentApplicationId; + } + + Base parent = allObjects.Find(x => x.applicationId == parentApplicationId); if (parent == null) { @@ -247,6 +260,11 @@ bool forReceive return Converters[typeof(Roof)]; } + if (elementType.IsSubclassOf(typeof(Opening))) + { + return Converters[typeof(Opening)]; + } + if (elementType.IsAssignableFrom(typeof(Objects.BuiltElements.Room))) { return Converters[typeof(Archicad.Room)]; diff --git a/ConnectorArchicad/ConnectorArchicad/Converters/ElementTypeProvider.cs b/ConnectorArchicad/ConnectorArchicad/Converters/ElementTypeProvider.cs index da11c33ced..a2cb24e846 100644 --- a/ConnectorArchicad/ConnectorArchicad/Converters/ElementTypeProvider.cs +++ b/ConnectorArchicad/ConnectorArchicad/Converters/ElementTypeProvider.cs @@ -10,6 +10,7 @@ using Wall = Objects.BuiltElements.Archicad.ArchicadWall; using Window = Objects.BuiltElements.Archicad.ArchicadWindow; using Skylight = Objects.BuiltElements.Archicad.ArchicadSkylight; +using Opening = Objects.BuiltElements.Archicad.ArchicadOpening; namespace Archicad; @@ -28,7 +29,8 @@ public static class ElementTypeProvider { "Door", typeof(Door) }, { "Window", typeof(Window) }, { "Skylight", typeof(Skylight) }, - { "GridElement", typeof(GridElement) } + { "GridElement", typeof(GridElement) }, + { "Opening", typeof(Opening) } }; public static Type GetTypeByName(string name) diff --git a/ConnectorArchicad/ConnectorArchicad/Converters/ModelConverter.cs b/ConnectorArchicad/ConnectorArchicad/Converters/ModelConverter.cs index f19785f14a..b8db6345f7 100644 --- a/ConnectorArchicad/ConnectorArchicad/Converters/ModelConverter.cs +++ b/ConnectorArchicad/ConnectorArchicad/Converters/ModelConverter.cs @@ -3,6 +3,8 @@ using System.Linq; using Archicad.Converters; using Archicad.Model; +using Objects.BuiltElements.Archicad; +using Objects; using Objects.Geometry; using Objects.Other; using Objects.Utils; @@ -393,4 +395,210 @@ MeshModel meshModel return angleCos > angleCosLimit; } + + public static ICurve CreateOpeningOutline(ArchicadOpening opening) + { + double halfWidth = opening.width / 2.0 ?? 0.0; + double halfHeight = opening.height / 2.0 ?? 0.0; + Vector basePoint = new(0, 0, 0); + Vector extrusionBasePoint = new(opening.extrusionGeometryBasePoint); + + // Speckle datastructure does not handle the translation component, which we will use manually later, so its left empty. + System.DoubleNumerics.Matrix4x4 rotMatrix = + new( + (float)opening.extrusionGeometryXAxis.x, + (float)opening.extrusionGeometryXAxis.y, + (float)opening.extrusionGeometryXAxis.z, + 0, + (float)opening.extrusionGeometryYAxis.x, + (float)opening.extrusionGeometryYAxis.y, + (float)opening.extrusionGeometryYAxis.z, + 0, + (float)opening.extrusionGeometryZAxis.x, + (float)opening.extrusionGeometryZAxis.y, + (float)opening.extrusionGeometryZAxis.z, + 0, + 0, + 0, + 0, + 1 + ); + + Objects.Other.Transform transform = new(System.DoubleNumerics.Matrix4x4.Transpose(rotMatrix)); + + AdjustBasePoint(ref basePoint, halfWidth, halfHeight, opening.anchorIndex ?? 0); + + return opening.basePolygonType == "Rectangular" + ? CreateRectangle(basePoint, transform, extrusionBasePoint, halfWidth, halfHeight) + : CreateEllipse(basePoint, transform, extrusionBasePoint, halfWidth, halfHeight, opening); + } + + private static readonly Action[] anchorActions = new Action[] + { + (Vector basePoint, double halfWidth, double halfHeight) => + { + basePoint.x = halfWidth; + basePoint.y = -halfHeight; + }, // APIAnc_LT + (Vector basePoint, double halfWidth, double halfHeight) => + { + basePoint.y = -halfHeight; + }, // APIAnc_MT + (Vector basePoint, double halfWidth, double halfHeight) => + { + basePoint.x = -halfWidth; + basePoint.y = -halfHeight; + }, // APIAnc_RT + (Vector basePoint, double halfWidth, double halfHeight) => + { + basePoint.x = halfWidth; + }, // APIAnc_LM + (Vector basePoint, double halfWidth, double halfHeight) => { }, // APIAnc_MM + (Vector basePoint, double halfWidth, double halfHeight) => + { + basePoint.x = -halfWidth; + }, // APIAnc_RM + (Vector basePoint, double halfWidth, double halfHeight) => + { + basePoint.x = halfWidth; + basePoint.y = halfHeight; + }, // APIAnc_LB + (Vector basePoint, double halfWidth, double halfHeight) => + { + basePoint.y = halfHeight; + }, // APIAnc_MB + (Vector basePoint, double halfWidth, double halfHeight) => + { + basePoint.x = -halfWidth; + basePoint.y = halfHeight; + } // APIAnc_RB + }; + + private static void AdjustBasePoint(ref Vector basePoint, double halfWidth, double halfHeight, int anchor) + { + if (anchor >= 0 && anchor < anchorActions.Length) + { + anchorActions[anchor](basePoint, halfWidth, halfHeight); + } + } + + private static Polyline CreateRectangle( + Vector basePoint, + Objects.Other.Transform transform, + Vector extrusionBasePoint, + double halfWidth, + double halfHeight + ) + { + var poly = new Objects.Geometry.Polyline + { + value = new List(), + closed = true, + units = Units.Meters + }; + + // Coordinates of the four corners of the rectangle + Vector[] points = + { + new(-halfWidth, -halfHeight, 0), + new(halfWidth, -halfHeight, 0), + new(halfWidth, halfHeight, 0), + new(-halfWidth, halfHeight, 0) + }; + + // Transform the points to the correct position + foreach (var point in points) + { + Vector transformedPoint = point + basePoint; + transformedPoint.TransformTo(transform, out transformedPoint); + transformedPoint += extrusionBasePoint; + poly.value.AddRange(transformedPoint.ToList()); + } + + // Close the polyline + poly.value.AddRange(poly.value.Take(3)); + + return poly; + } + + private static Ellipse CreateEllipse( + Vector basePoint, + Objects.Other.Transform transform, + Vector extrusionBasePoint, + double halfWidth, + double halfHeight, + ArchicadOpening opening + ) + { + Vector centerPoint = new(basePoint.x, basePoint.y, basePoint.z); + centerPoint.TransformTo(transform, out centerPoint); + centerPoint += extrusionBasePoint; + + Point center = new(centerPoint.x, centerPoint.y, centerPoint.z); + + Objects.Geometry.Plane plane = + new(center, opening.extrusionGeometryZAxis, opening.extrusionGeometryXAxis, opening.extrusionGeometryYAxis); + + return new Ellipse(plane, halfWidth, halfHeight, Units.Meters); + } + + public static void GetExtrusionParametersFromOutline( + ICurve outline, + out Vector extrusionBasePoint, + out Vector extrusionXAxis, + out Vector extrusionYAxis, + out Vector extrusionZAxis, + out double width, + out double height + ) + { + // Assign default values to out parameters + extrusionBasePoint = new Vector(); + extrusionXAxis = new Vector(); + extrusionYAxis = new Vector(); + extrusionZAxis = new Vector(); + width = 0; + height = 0; + + if (outline is not Polyline polyline) + { + extrusionBasePoint = null; + extrusionXAxis = null; + extrusionYAxis = null; + extrusionZAxis = null; + return; + } + + // Form the 4 points of the rectangle from the polyline + List points = Enumerable + .Range(0, polyline.value.Count / 3) + .Select( + i => new Vector(polyline.value[i * 3], polyline.value[i * 3 + 1], polyline.value[i * 3 + 2], polyline.units) + ) + .ToList(); + + Vector bottomLeft = Utils.ScaleToNative(points[0]); + Vector topLeft = Utils.ScaleToNative(points[1]); + Vector topRight = Utils.ScaleToNative(points[2]); + Vector bottomRight = Utils.ScaleToNative(points[3]); + + // We set the anchor point to Middle-Middle, so we can calculate the extrusion base point more easily like so. + extrusionBasePoint = (bottomLeft + bottomRight + topRight + topLeft) * 0.25; + + Vector verticalDiff = topRight - bottomRight; + height = verticalDiff.Length; + + extrusionYAxis = verticalDiff / height; + + Vector horizontalDiff = bottomRight - bottomLeft; + width = horizontalDiff.Length; + + // Calculate the extrusion X axis + extrusionXAxis = horizontalDiff / width; + + // The last extrusion axis will be the cross product of the other two + extrusionZAxis = Vector.CrossProduct(extrusionXAxis, extrusionYAxis); + + extrusionZAxis.Normalize(); + } } diff --git a/ConnectorArchicad/ConnectorArchicad/Info.plist b/ConnectorArchicad/ConnectorArchicad/Info.plist new file mode 100644 index 0000000000..e42154e574 --- /dev/null +++ b/ConnectorArchicad/ConnectorArchicad/Info.plist @@ -0,0 +1,39 @@ + + + + + CFBundleName + acconnector + CFBundleDisplayName + Archicad Connector + CFBundleIdentifier + systems.speckle.acconnector + CFBundleVersion + 2.0.0 + CFBundlePackageType + APPL + CFBundleSignature + spkl + CFBundleExecutable + ConnectorArchicad + CFBundleIconFile + icon-mac.icns + CFBundleShortVersionString + 2.0.0 + CFBundleURLTypes + + + CFBundleURLName + Speckle + CFBundleURLSchemes + + speckle + + + + NSPrincipalClass + NSApplication + NSHighResolutionCapable + + + \ No newline at end of file diff --git a/ConnectorAutocadCivil/README.md b/ConnectorAutocadCivil/README.md index 9b74423e0d..02e9f4749b 100644 --- a/ConnectorAutocadCivil/README.md +++ b/ConnectorAutocadCivil/README.md @@ -4,13 +4,13 @@ ## Introduction -This is the âš ALPHAâš  version of the Speckle 2.0 AutoCAD Civil3D Connector. Currently, it only supports the very most basic conversions - please leave any comments, suggestions, and feature requests in our [Making Speckle](https://discourse.speckle.works/t/new-speckle-2-0-autocad-civil3d-suggestions/1155) forum discussion thread! +This is the âš Betaâš  version of the Speckle 2.0 AutoCAD Civil3D Connector. Currently, it supports the basic objects for both Autocad and Civil3D (refer to our docs for a full list) - please leave any comments, suggestions, and feature requests in our [Making Speckle](https://discourse.speckle.works/t/new-speckle-2-0-autocad-civil3d-suggestions/1155) forum discussion thread! ## Documentation Comprehensive developer and user documentation can be found in our: -#### 📚 [Speckle Docs website](https://speckle.guide/dev/) +#### 📚 [Speckle Docs website](https://speckle.guide/user/autocadcivil.html) ## Developing & Debugging @@ -21,8 +21,8 @@ Comprehensive developer and user documentation can be found in our: #### Supported versions -- AutoCAD: 2021, 2022 -- Civil3D: 2021, 2022 +- AutoCAD: 2021, 2022, 2023, 2024, 2025 +- Civil3D: 2021, 2022, 2023, 2024, 2025 ### Getting Started diff --git a/ConnectorGrasshopper/ConnectorGrasshopperShared/Ops/Operations.VariableInputReceiveComponent.cs b/ConnectorGrasshopper/ConnectorGrasshopperShared/Ops/Operations.VariableInputReceiveComponent.cs index ce1a78b883..0b2e02996c 100644 --- a/ConnectorGrasshopper/ConnectorGrasshopperShared/Ops/Operations.VariableInputReceiveComponent.cs +++ b/ConnectorGrasshopper/ConnectorGrasshopperShared/Ops/Operations.VariableInputReceiveComponent.cs @@ -547,6 +547,23 @@ public async Task ResetApiClient(StreamWrapper wrapper) try { account = wrapper?.GetAccount().Result; + + // hack for FE2 + // should we also fetch this for FE1-accounts that are trying to access FE2 stream? Probably not + if (account.serverInfo.frontend2 is true) + { + Client client = new(account); + var streamObj = client.StreamGet(StreamWrapper.StreamId, 100).Result; + foreach (Branch branch in streamObj.branches.items) + { + if (branch.id == StreamWrapper.BranchName) + { + StreamWrapper.BranchName = branch.name; + break; + } + } + client.Dispose(); + } } catch (SpeckleException e) { diff --git a/ConnectorGrasshopper/ConnectorGrasshopperShared/SchemaBuilder/CreateSchemaObject.cs b/ConnectorGrasshopper/ConnectorGrasshopperShared/SchemaBuilder/CreateSchemaObject.cs index 3749d94648..67f00ce746 100644 --- a/ConnectorGrasshopper/ConnectorGrasshopperShared/SchemaBuilder/CreateSchemaObject.cs +++ b/ConnectorGrasshopper/ConnectorGrasshopperShared/SchemaBuilder/CreateSchemaObject.cs @@ -252,13 +252,14 @@ public void SwitchConstructor(ConstructorInfo constructor) RegisterPropertyAsInputParameter(p, k++); } + SelectedConstructor = constructor; + UserInterfaceUtils.CreateCanvasDropdownForAllEnumInputs(this, props); Name = constructor.GetCustomAttribute().Name; Description = constructor.GetCustomAttribute().Description; Message = constructor.DeclaringType.FullName.Split('.')[0]; - SelectedConstructor = constructor; Params.Output[0].NickName = constructor.DeclaringType.Name; Params.OnParametersChanged(); diff --git a/Core/Core/Serialisation/SerializationUtilities/ValueConverter.cs b/Core/Core/Serialisation/SerializationUtilities/ValueConverter.cs index f648f3274f..70246a1363 100644 --- a/Core/Core/Serialisation/SerializationUtilities/ValueConverter.cs +++ b/Core/Core/Serialisation/SerializationUtilities/ValueConverter.cs @@ -1,6 +1,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Diagnostics.Contracts; using System.DoubleNumerics; using System.Drawing; using System.Globalization; @@ -157,16 +158,17 @@ public static bool ConvertValue(Type type, object? value, out object? convertedV #endregion } - // Handle List - if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(List<>)) + // Handle List<>, IList<>, and IReadOnlyList<> + if (type.IsGenericType && IsGenericList(type)) { if (value is not List valueList) { return false; } + var targetType = typeof(List<>).MakeGenericType(type.GenericTypeArguments); Type listElementType = type.GenericTypeArguments[0]; - IList ret = Activator.CreateInstance(type, valueList.Count) as IList; + IList ret = Activator.CreateInstance(targetType, valueList.Count) as IList; foreach (object inputListElement in valueList) { if (!ConvertValue(listElementType, inputListElement, out object? convertedListElement)) @@ -311,4 +313,21 @@ public static bool ConvertValue(Type type, object? value, out object? convertedV return false; } + + /// + /// Tests that the given is assignable from a generic type def + /// + /// + /// + [Pure] + private static bool IsGenericList(Type type) + { + if (!type.IsGenericType) + { + return false; + } + + Type typeDef = type.GetGenericTypeDefinition(); + return typeDef == typeof(List<>) || typeDef == typeof(IList<>) || typeDef == typeof(IReadOnlyList<>); + } } diff --git a/Core/Tests/Speckle.Core.Tests.Integration/ServerTransportTests.cs b/Core/Tests/Speckle.Core.Tests.Integration/ServerTransportTests.cs index 0baa04ac9b..4d111f0e2e 100644 --- a/Core/Tests/Speckle.Core.Tests.Integration/ServerTransportTests.cs +++ b/Core/Tests/Speckle.Core.Tests.Integration/ServerTransportTests.cs @@ -46,6 +46,7 @@ public void TearDown() private void CleanData() { + _transport?.Dispose(); if (Directory.Exists(_basePath)) { Directory.Delete(_basePath, true); @@ -73,7 +74,7 @@ public async Task SendAndReceiveObjectWithBlobs() // NOTE: used to debug diffing // await Operations.Send(myObject, new List { transport }); - var receivedObject = await Operations.Receive(sentObjectId, _transport); + var receivedObject = await Operations.Receive(sentObjectId, _transport, new MemoryTransport()); var allFiles = Directory .GetFiles(_transport.BlobStorageFolder) @@ -104,7 +105,7 @@ public async Task SendWithBlobsWithoutSQLiteSendCache() var memTransport = new MemoryTransport(); var sentObjectId = await Operations.Send(myObject, new List { _transport, memTransport }); - var receivedObject = await Operations.Receive(sentObjectId, _transport); + var receivedObject = await Operations.Receive(sentObjectId, _transport, new MemoryTransport()); var allFiles = Directory .GetFiles(_transport.BlobStorageFolder) diff --git a/Core/Tests/Speckle.Core.Tests.Unit/Serialisation/SerializerNonBreakingChanges.cs b/Core/Tests/Speckle.Core.Tests.Unit/Serialisation/SerializerNonBreakingChanges.cs index ef2c5e501e..30dbea5d06 100644 --- a/Core/Tests/Speckle.Core.Tests.Unit/Serialisation/SerializerNonBreakingChanges.cs +++ b/Core/Tests/Speckle.Core.Tests.Unit/Serialisation/SerializerNonBreakingChanges.cs @@ -87,6 +87,42 @@ public void ListToArray(double[] testCase) Assert.That(res.value, Is.EquivalentTo(testCase)); } + [Test, TestCaseSource(nameof(s_arrayTestCases))] + public void ListToIList(double[] testCase) + { + var from = new ListDoubleValueMock { value = testCase.ToList() }; + + var res = from.SerializeAsTAndDeserialize(); + Assert.That(res.value, Is.EquivalentTo(testCase)); + } + + [Test, TestCaseSource(nameof(s_arrayTestCases))] + public void ListToIReadOnlyList(double[] testCase) + { + var from = new ListDoubleValueMock { value = testCase.ToList() }; + + var res = from.SerializeAsTAndDeserialize(); + Assert.That(res.value, Is.EquivalentTo(testCase)); + } + + [Test, TestCaseSource(nameof(s_arrayTestCases))] + public void IListToList(double[] testCase) + { + var from = new IListDoubleValueMock { value = testCase.ToList() }; + + var res = from.SerializeAsTAndDeserialize(); + Assert.That(res.value, Is.EquivalentTo(testCase)); + } + + [Test, TestCaseSource(nameof(s_arrayTestCases))] + public void IReadOnlyListToList(double[] testCase) + { + var from = new IReadOnlyListDoubleValueMock { value = testCase.ToList() }; + + var res = from.SerializeAsTAndDeserialize(); + Assert.That(res.value, Is.EquivalentTo(testCase)); + } + [Test, TestCaseSource(nameof(MyEnums))] public void EnumToInt(MyEnum testCase) { @@ -171,6 +207,16 @@ public class ListDoubleValueMock : SerializerMock public List value { get; set; } } +public class IListDoubleValueMock : SerializerMock +{ + public IList value { get; set; } +} + +public class IReadOnlyListDoubleValueMock : SerializerMock +{ + public IReadOnlyList value { get; set; } +} + public class ArrayDoubleValueMock : SerializerMock { public double[] value { get; set; } diff --git a/Objects/Converters/ConverterAutocadCivil/ConverterAutocadCivilShared/ConverterAutocadCivil.Civil.cs b/Objects/Converters/ConverterAutocadCivil/ConverterAutocadCivilShared/ConverterAutocadCivil.Civil.cs index a5d50b5efc..89f47ac800 100644 --- a/Objects/Converters/ConverterAutocadCivil/ConverterAutocadCivilShared/ConverterAutocadCivil.Civil.cs +++ b/Objects/Converters/ConverterAutocadCivil/ConverterAutocadCivilShared/ConverterAutocadCivil.Civil.cs @@ -12,7 +12,6 @@ using Civil = Autodesk.Civil; using Autodesk.AutoCAD.Geometry; using Acad = Autodesk.AutoCAD.Geometry; -using AcadDB = Autodesk.AutoCAD.DatabaseServices; using Objects.BuiltElements.Civil; using Alignment = Objects.BuiltElements.Alignment; @@ -30,6 +29,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; @@ -640,7 +640,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(); @@ -666,25 +666,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 bulges = new List(); - for (int i = 0; i < count; i++) bulges.Add(featureline.GetBulge(i)); - var piBulges = new List(); - 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 } }; + AddNameAndDescriptionProperty(featureline.Name, featureline.Description, speckleFeatureline); speckleFeatureline["@piPoints"] = piPoints; speckleFeatureline["@elevationPoints"] = ePoints; @@ -1016,12 +1009,19 @@ public Structure StructureToSpeckle(CivilDB.Structure structure) }; // assign additional structure props - try { speckleStructure["grate"] = structure.Grate; } catch (Exception ex) when (!ex.IsFatal()) { } - try { speckleStructure["station"] = structure.Station; } catch (Exception ex) when (!ex.IsFatal()) { } - try { speckleStructure["network"] = structure.NetworkName; } catch (Exception ex) when (!ex.IsFatal()) { } AddNameAndDescriptionProperty(structure.Name, structure.Description, speckleStructure); speckleStructure["partData"] = PartDataRecordToSpeckle(structure.PartData); + try { speckleStructure["station"] = structure.Station; } catch (Exception ex) when (!ex.IsFatal()) { } + try { speckleStructure["network"] = structure.NetworkName; } catch (Exception ex) when (!ex.IsFatal()) { } + try { speckleStructure["rotation"] = structure.Rotation; } catch (Exception e) when (!e.IsFatal()) { } + try { speckleStructure["sumpDepth"] = structure.SumpDepth; } catch (Exception e) when (!e.IsFatal()) { } + try { speckleStructure["rimElevation"] = structure.RimElevation; } catch (Exception e) when (!e.IsFatal()) { } + try { speckleStructure["sumpElevation"] = structure.SumpElevation; } catch (Exception e) when (!e.IsFatal()) { } + try { speckleStructure["lengthOuter"] = structure.Length; } catch (Exception e) when (!e.IsFatal()) { } + try { speckleStructure["lengthInner"] = structure.InnerLength; } catch (Exception e) when (!e.IsFatal()) { } + try { speckleStructure["structureId"] = structure.Id.ToString(); } catch (Exception ex) when (!ex.IsFatal()) { } + return speckleStructure; } @@ -1035,29 +1035,37 @@ private List 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); + } + + return fields; + } + +#if CIVIL2022_OR_GREATER + /// + /// Converts PressureNetworkPartData into a list of DataField + /// + private List PartDataRecordToSpeckle(PressureNetworkPartData partData) + { + List fields = new(); + + foreach (PressurePartProperty partField in partData) + { + CivilDataField field = new(partField.Name, partField.GetType().ToString(), partField.Value, null, null, partField.DisplayName); fields.Add(field); } return fields; } +#endif // pipes // TODO: add pressure fittings public Pipe PipeToSpeckle(CivilDB.Pipe pipe) { - // get the pipe curve - ICurve curve; - switch (pipe.SubEntityType) - { - case PipeSubEntityType.Straight: - var line = new Acad.LineSegment3d(pipe.StartPoint, pipe.EndPoint); - curve = LineToSpeckle(line); - break; - default: - curve = CurveToSpeckle(pipe.BaseCurve); - break; - } + ICurve curve = CurveToSpeckle(pipe.BaseCurve); + Pipe specklePipe = new() { @@ -1081,8 +1089,9 @@ public Pipe PipeToSpeckle(CivilDB.Pipe pipe) try { specklePipe["endOffset"] = pipe.EndOffset; } catch(Exception ex) when(!ex.IsFatal()) { } try { specklePipe["startStation"] = pipe.StartStation; } catch(Exception ex) when(!ex.IsFatal()) { } try { specklePipe["endStation"] = pipe.EndStation; } catch(Exception ex) when(!ex.IsFatal()) { } - try { specklePipe["startStructure"] = pipe.StartStructureId.ToString(); } catch(Exception ex) when(!ex.IsFatal()) { } - try { specklePipe["endStructure"] = pipe.EndStructureId.ToString(); } catch(Exception ex) when(!ex.IsFatal()) { } + try { specklePipe["startStructureId"] = pipe.StartStructureId.ToString(); } catch(Exception ex) when(!ex.IsFatal()) { } + try { specklePipe["endStructureId"] = pipe.EndStructureId.ToString(); } catch(Exception ex) when(!ex.IsFatal()) { } + try { specklePipe["pipeId"] = pipe.Id.ToString(); } catch (Exception ex) when (!ex.IsFatal()) { } return specklePipe; } @@ -1090,17 +1099,7 @@ public Pipe PipeToSpeckle(CivilDB.Pipe pipe) public Pipe PipeToSpeckle(PressurePipe pipe) { // get the pipe curve - ICurve curve; - switch (pipe.BaseCurve) - { - case AcadDB.Line: - var line = new LineSegment3d(pipe.StartPoint, pipe.EndPoint); - curve = LineToSpeckle(line); - break; - default: - curve = CurveToSpeckle(pipe.BaseCurve); - break; - } + ICurve curve = CurveToSpeckle(pipe.BaseCurve); Pipe specklePipe = new() { @@ -1113,8 +1112,11 @@ public Pipe PipeToSpeckle(PressurePipe pipe) // assign additional pipe props AddNameAndDescriptionProperty(pipe.Name, pipe.Description, specklePipe); - specklePipe["isPressurePipe"] = true; +#if CIVIL2022_OR_GREATER + specklePipe["partData"] = PartDataRecordToSpeckle(pipe.PartData); +#endif + specklePipe["isPressurePipe"] = true; try { specklePipe["partType"] = pipe.PartType.ToString(); } catch (Exception e) when (!e.IsFatal()) { } try { specklePipe["slope"] = pipe.Slope; } catch (Exception e) when (!e.IsFatal()) { } try { specklePipe["network"] = pipe.NetworkName; } catch (Exception e) when (!e.IsFatal()) { } @@ -1122,19 +1124,161 @@ public Pipe PipeToSpeckle(PressurePipe pipe) try { specklePipe["endOffset"] = pipe.EndOffset; } catch (Exception e) when (!e.IsFatal()) { } try { specklePipe["startStation"] = pipe.StartStation; } catch (Exception e) when (!e.IsFatal()) { } try { specklePipe["endStation"] = pipe.EndStation; } catch (Exception e) when (!e.IsFatal()) { } + try { specklePipe["pipeId"] = pipe.Id.ToString(); } catch (Exception ex) when (!ex.IsFatal()) { } return specklePipe; } // 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; + + // get the calculated shapes + List speckleShapes = new(); + foreach (CalculatedShape shape in appliedSubassembly.Shapes) + { + CivilCalculatedShape speckleShape = CalculatedShapeToSpeckle(shape); + speckleShapes.Add(speckleShape); + } + + Point soePoint = PointToSpeckle(appliedSubassembly.OriginStationOffsetElevationToBaseline); + List 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) + { + // get the applied subassemblies + List speckleSubassemblies = new(); + foreach (AppliedSubassembly appliedSubassembly in appliedAssembly.GetAppliedSubassemblies()) + { + CivilAppliedSubassembly speckleSubassembly = AppliedSubassemblyToSpeckle(appliedSubassembly); + speckleSubassemblies.Add(speckleSubassembly); + } + + CivilAppliedAssembly speckleAppliedAssembly = new(speckleSubassemblies, appliedAssembly.AdjustedElevation, ModelUnits); + 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 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 codes = shape.CorridorCodes.ToList(); + List 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 codes = link.CorridorCodes.ToList(); + List 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 codes = point.CorridorCodes.ToList(); + Vector normalBaseline = VectorToSpeckle(point.NormalToBaseline); + Vector normalSubAssembly = VectorToSpeckle(point.NormalToSubassembly); + 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 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 alignments = new(); - List profiles = new(); List featurelines = new(); - foreach (Baseline baseline in corridor.Baselines) + List 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 @@ -1155,32 +1299,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 @@ -1202,9 +1320,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) diff --git a/Objects/Converters/ConverterAutocadCivil/ConverterAutocadCivilShared/ConverterAutocadCivil.cs b/Objects/Converters/ConverterAutocadCivil/ConverterAutocadCivilShared/ConverterAutocadCivil.cs index 957fff734b..96bd06d9f1 100644 --- a/Objects/Converters/ConverterAutocadCivil/ConverterAutocadCivilShared/ConverterAutocadCivil.cs +++ b/Objects/Converters/ConverterAutocadCivil/ConverterAutocadCivilShared/ConverterAutocadCivil.cs @@ -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); diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/AllRevitCategories.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/AllRevitCategories.cs index cb51ab0a0f..14edc8539f 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/AllRevitCategories.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/AllRevitCategories.cs @@ -36,27 +36,45 @@ public IRevitCategoryInfo GetRevitCategoryInfo(Base @base) return elementType; } - var matchingType = revitDocumentAggregateCache - .GetOrInitializeWithDefaultFactory() - .GetAllObjects() - .Where(catInfo => catInfo.ElementTypeType == typeof(T) && catInfo.BuiltInCategories.Count == 0) - .FirstOrDefault(); + IRevitCategoryInfo matchingType; + + if (revitDocumentAggregateCache is null) + { + matchingType = elementType; + } + else + { + matchingType = revitDocumentAggregateCache + .GetOrInitializeWithDefaultFactory() + .GetAllObjects() + .Where(catInfo => catInfo.ElementTypeType == typeof(T) && catInfo.BuiltInCategories.Count == 0) + .FirstOrDefault(); + } if (matchingType != null) { return matchingType; } - var categoryInfo = revitDocumentAggregateCache - .GetOrInitializeWithDefaultFactory() - .GetOrAdd( - typeof(T).Name, - () => - { - return new RevitCategoryInfo(typeof(T).Name, null, typeof(T), new List()); - }, - out _ - ); + IRevitCategoryInfo categoryInfo; + + if (revitDocumentAggregateCache is null) + { + categoryInfo = new RevitCategoryInfo(typeof(T).Name, null, typeof(T), new List()); + } + else + { + categoryInfo = revitDocumentAggregateCache + .GetOrInitializeWithDefaultFactory() + .GetOrAdd( + typeof(T).Name, + () => + { + return new RevitCategoryInfo(typeof(T).Name, null, typeof(T), new List()); + }, + out _ + ); + } return categoryInfo; } @@ -128,30 +146,26 @@ public IRevitCategoryInfo GetRevitCategoryInfo(string categoryName) } categoryName = CategoryNameFormatted(categoryName); - var revitCategoryInfoCache = revitDocumentAggregateCache.GetOrInitializeWithDefaultFactory(); - categoryInfo = revitCategoryInfoCache.TryGet(categoryName); - if (categoryInfo != null) + IRevitObjectCache revitCategoryInfoCache; + if (revitDocumentAggregateCache is not null) { - return categoryInfo; - } + revitCategoryInfoCache = revitDocumentAggregateCache.GetOrInitializeWithDefaultFactory(); - foreach (var info in revitCategoryInfoCache.GetAllObjects()) - { - if (categoryName.IndexOf(info.CategoryName, StringComparison.OrdinalIgnoreCase) >= 0) + categoryInfo = revitCategoryInfoCache.TryGet(categoryName); + if (categoryInfo != null) { - return info; + return categoryInfo; } - foreach (var alias in info.CategoryAliases) + else { - if (categoryName.IndexOf(alias, StringComparison.OrdinalIgnoreCase) >= 0) - { - return info; - } + return SHC.Undefined; } } - - return SHC.Undefined; + else + { + return SHC.Undefined; + } } #endregion @@ -173,29 +187,43 @@ public IRevitCategoryInfo GetRevitCategoryInfo(string categoryName) // pre 2.16 we're passing the "category" string else { - var revitCat = revitDocumentAggregateCache - .GetOrInitializeWithDefaultFactory() - .TryGet(unformattedCatName); - - if (revitCat == null) + if (revitDocumentAggregateCache is null) { return null; } + else + { + var revitCat = revitDocumentAggregateCache + .GetOrInitializeWithDefaultFactory() + .TryGet(unformattedCatName); - bic = Categories.GetBuiltInCategory(revitCat); - formattedName = CategoryNameFormatted(unformattedCatName); + if (revitCat == null) + { + return null; + } + + bic = Categories.GetBuiltInCategory(revitCat); + formattedName = CategoryNameFormatted(unformattedCatName); + } } - return revitDocumentAggregateCache - .GetOrInitializeWithDefaultFactory() - .GetOrAdd( - formattedName, - () => - { - return new RevitCategoryInfo(formattedName, null, null, new List { bic }); - }, - out _ - ); + if (revitDocumentAggregateCache is null) + { + return new RevitCategoryInfo(formattedName, null, null, new List { bic }); + } + else + { + return revitDocumentAggregateCache + .GetOrInitializeWithDefaultFactory() + .GetOrAdd( + formattedName, + () => + { + return new RevitCategoryInfo(formattedName, null, null, new List { bic }); + }, + out _ + ); + } } private static string CategoryNameFormatted(string name) diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/ConversionUtils.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/ConversionUtils.cs index 5aae514f7a..307cca0e29 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/ConversionUtils.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/ConversionUtils.cs @@ -390,39 +390,46 @@ private Parameter ParameterToSpeckle( #else ForgeTypeId unitTypeId = null; #endif + ParameterToSpeckleData paramData; + + // Local function to create ParameterToSpeckleData + ParameterToSpeckleData CreateParamData() + { + var definition = rp.Definition; + var newParamData = new ParameterToSpeckleData() + { + Definition = definition, + InternalName = paramInternalName, + IsReadOnly = rp.IsReadOnly, + IsShared = rp.IsShared, + IsTypeParameter = isTypeParameter, + Name = definition.Name, + UnitType = definition.GetUnityTypeString(), + }; + if (rp.StorageType == StorageType.Double) + { + unitTypeId = rp.GetUnitTypeId(); + newParamData.UnitsSymbol = GetSymbolUnit(rp, definition, unitTypeId); + newParamData.ApplicationUnits = + unitsOverride != null ? UnitsToNative(unitsOverride).ToUniqueString() : unitTypeId.ToUniqueString(); + } + return newParamData; + } // The parameter definitions are cached using the ParameterToSpeckleData struct // This is done because in the case of type and instance parameter there is lots of redundant data that needs to be extracted from the Revit DB // Caching noticeably speeds up the send process // TODO : could add some generic getOrAdd overloads to avoid creating closures - var paramData = revitDocumentAggregateCache - .GetOrInitializeEmptyCacheOfType(out _) - .GetOrAdd( - paramInternalName, - () => - { - var definition = rp.Definition; - var newParamData = new ParameterToSpeckleData() - { - Definition = definition, - InternalName = paramInternalName, - IsReadOnly = rp.IsReadOnly, - IsShared = rp.IsShared, - IsTypeParameter = isTypeParameter, - Name = definition.Name, - UnitType = definition.GetUnityTypeString(), - }; - if (rp.StorageType == StorageType.Double) - { - unitTypeId = rp.GetUnitTypeId(); - newParamData.UnitsSymbol = GetSymbolUnit(rp, definition, unitTypeId); - newParamData.ApplicationUnits = - unitsOverride != null ? UnitsToNative(unitsOverride).ToUniqueString() : unitTypeId.ToUniqueString(); - } - return newParamData; - }, - out _ - ); + if (revitDocumentAggregateCache is null) + { + paramData = CreateParamData(); + } + else + { + paramData = revitDocumentAggregateCache + .GetOrInitializeEmptyCacheOfType(out _) + .GetOrAdd(paramInternalName, CreateParamData, out _); + } return paramData.GetParameterObjectWithValue(rp.GetValue(paramData.Definition, unitTypeId)); } @@ -450,9 +457,16 @@ ForgeTypeId unitTypeId return null; } - return revitDocumentAggregateCache - .GetOrInitializeEmptyCacheOfType(out _) - .GetOrAdd(unitTypeId.ToUniqueString(), () => unitTypeId.GetSymbol(), out _); + if (revitDocumentAggregateCache is null) + { + return unitTypeId.GetSymbol(); + } + else + { + return revitDocumentAggregateCache + .GetOrInitializeEmptyCacheOfType(out _) + .GetOrAdd(unitTypeId.ToUniqueString(), () => unitTypeId.GetSymbol(), out _); + } } /// diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/ConverterRevit.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/ConverterRevit.cs index 337f32a2f4..4c9a38d3f4 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/ConverterRevit.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/ConverterRevit.cs @@ -1,3 +1,4 @@ +#nullable enable using System; using System.Collections.Generic; using System.Linq; @@ -109,7 +110,7 @@ public ConverterRevit() Report.Log($"Using converter: {Name} v{ver}"); } - private IRevitDocumentAggregateCache revitDocumentAggregateCache; + private IRevitDocumentAggregateCache? revitDocumentAggregateCache; private IConvertedObjectsCache receivedObjectsCache; private TransactionManager transactionManager; diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertBrace.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertBrace.cs index 0613b4d8ab..8de864d03a 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertBrace.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertBrace.cs @@ -1,8 +1,10 @@ +using System; using Autodesk.Revit.DB.Structure; using Objects.BuiltElements; using Objects.BuiltElements.Revit; using Speckle.Core.Models; using System.Collections.Generic; +using Objects.Geometry; using DB = Autodesk.Revit.DB; namespace Objects.Converter.Revit; @@ -37,18 +39,21 @@ public ApplicationObject BraceToNative(Brace speckleBrace) private Base BraceToSpeckle(DB.FamilyInstance myFamily, out List notes) { - notes = new List(); - var myBeam = BeamToSpeckle(myFamily, out notes) as RevitBeam; + var myBeam = (RevitBeam)BeamToSpeckle(myFamily, out notes); - var myBrace = new RevitBrace() + var myBrace = new RevitBrace( + myBeam.family, + myBeam.type, + myBeam.baseLine, + myBeam.level, + myBeam.units, + myBeam.elementId, + Array.Empty() + ) { + displayValue = myBeam.displayValue, applicationId = myBeam.applicationId, - type = myBeam.type, - baseLine = myBeam.baseLine, - level = myBeam.level, - family = myBeam.family, parameters = myBeam.parameters, - displayValue = myBeam.displayValue, }; var dynamicProps = myBeam.GetMembers(DynamicBaseMemberType.Dynamic); diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertColumn.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertColumn.cs index 0f813d6165..94efd55a14 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertColumn.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertColumn.cs @@ -249,39 +249,29 @@ double topOffset public Base ColumnToSpeckle(DB.FamilyInstance revitColumn, out List notes) { notes = new List(); - var symbol = revitColumn.Document.GetElement(revitColumn.GetTypeId()) as FamilySymbol; - - var speckleColumn = new RevitColumn(); - speckleColumn.family = symbol.FamilyName; - speckleColumn.type = revitColumn.Document.GetElement(revitColumn.GetTypeId()).Name; - speckleColumn.level = ConvertAndCacheLevel(revitColumn, BuiltInParameter.FAMILY_BASE_LEVEL_PARAM); - speckleColumn.topLevel = ConvertAndCacheLevel(revitColumn, BuiltInParameter.FAMILY_TOP_LEVEL_PARAM); - speckleColumn.baseOffset = GetParamValue(revitColumn, BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM); - speckleColumn.topOffset = GetParamValue(revitColumn, BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM); - speckleColumn.facingFlipped = revitColumn.FacingFlipped; - speckleColumn.handFlipped = revitColumn.HandFlipped; - speckleColumn.isSlanted = revitColumn.IsSlantedColumn; - //speckleColumn.structural = revitColumn.StructuralType == StructuralType.Column; + var symbol = (FamilySymbol)revitColumn.Document.GetElement(revitColumn.GetTypeId()); + + RevitLevel level = ConvertAndCacheLevel(revitColumn, BuiltInParameter.FAMILY_BASE_LEVEL_PARAM); + RevitLevel topLevel = ConvertAndCacheLevel(revitColumn, BuiltInParameter.FAMILY_TOP_LEVEL_PARAM); + double baseOffset = GetParamValue(revitColumn, BuiltInParameter.FAMILY_BASE_LEVEL_OFFSET_PARAM); + double topOffset = GetParamValue(revitColumn, BuiltInParameter.FAMILY_TOP_LEVEL_OFFSET_PARAM); //geometry var baseGeometry = LocationToSpeckle(revitColumn); var baseLine = baseGeometry as ICurve; - //make line from point and height if (baseLine == null && baseGeometry is Point basePoint) + //make line from point and height { - if ( - symbol.Family.FamilyPlacementType == FamilyPlacementType.OneLevelBased - || symbol.Family.FamilyPlacementType == FamilyPlacementType.WorkPlaneBased - ) + if (symbol.Family.FamilyPlacementType is FamilyPlacementType.OneLevelBased or FamilyPlacementType.WorkPlaneBased) { return RevitInstanceToSpeckle(revitColumn, out notes, null); } - var elevation = speckleColumn.topLevel.elevation; + var elevation = topLevel.elevation; baseLine = new Line( basePoint, - new Point(basePoint.x, basePoint.y, elevation + speckleColumn.topOffset, ModelUnits), + new Point(basePoint.x, basePoint.y, elevation + topOffset, ModelUnits), ModelUnits ); } @@ -291,7 +281,25 @@ public Base ColumnToSpeckle(DB.FamilyInstance revitColumn, out List note return RevitElementToSpeckle(revitColumn, out notes); } - speckleColumn.baseLine = baseLine; //all speckle columns should be line based + double rotation = revitColumn.Location is LocationPoint location ? location.Rotation : 0; + + var speckleColumn = new RevitColumn( + symbol.FamilyName, + revitColumn.Document.GetElement(revitColumn.GetTypeId()).Name, + baseLine, //all speckle columns should be line based + level, + topLevel, + ModelUnits, + revitColumn.Id.ToString(), + baseOffset, + topOffset, + revitColumn.FacingFlipped, + revitColumn.HandFlipped, + revitColumn.IsSlantedColumn, + rotation, + GetElementDisplayValue(revitColumn) + //structural: revitColumn.StructuralType == StructuralType.Column; + ); GetAllRevitParamsAndIds( speckleColumn, @@ -307,13 +315,6 @@ public Base ColumnToSpeckle(DB.FamilyInstance revitColumn, out List note } ); - if (revitColumn.Location is LocationPoint) - { - speckleColumn.rotation = ((LocationPoint)revitColumn.Location).Rotation; - } - - speckleColumn.displayValue = GetElementDisplayValue(revitColumn); - return speckleColumn; } } diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertWall.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertWall.cs index 11bbd0ceaf..73033b0442 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertWall.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/PartialClasses/ConvertWall.cs @@ -187,18 +187,21 @@ public Base WallToSpeckle(DB.Wall revitWall, out List notes) return RevitElementToSpeckle(revitWall, out notes); } - RevitWall speckleWall = new(); - speckleWall.family = revitWall.WallType.FamilyName.ToString(); - speckleWall.type = revitWall.WallType.Name; - speckleWall.baseLine = (ICurve)baseGeometry; - speckleWall.level = ConvertAndCacheLevel(revitWall, BuiltInParameter.WALL_BASE_CONSTRAINT); - speckleWall.topLevel = ConvertAndCacheLevel(revitWall, BuiltInParameter.WALL_HEIGHT_TYPE); - speckleWall.height = GetParamValue(revitWall, BuiltInParameter.WALL_USER_HEIGHT_PARAM); - speckleWall.baseOffset = GetParamValue(revitWall, BuiltInParameter.WALL_BASE_OFFSET); - speckleWall.topOffset = GetParamValue(revitWall, BuiltInParameter.WALL_TOP_OFFSET); - speckleWall.structural = GetParamValue(revitWall, BuiltInParameter.WALL_STRUCTURAL_SIGNIFICANT); - speckleWall.flipped = revitWall.Flipped; - + RevitWall speckleWall = + new( + revitWall.WallType.FamilyName, + revitWall.WallType.Name, + (ICurve)baseGeometry, + ConvertAndCacheLevel(revitWall, BuiltInParameter.WALL_BASE_CONSTRAINT), + ConvertAndCacheLevel(revitWall, BuiltInParameter.WALL_HEIGHT_TYPE), + GetParamValue(revitWall, BuiltInParameter.WALL_USER_HEIGHT_PARAM), + ModelUnits, + revitWall.Id.ToString(), + GetParamValue(revitWall, BuiltInParameter.WALL_BASE_OFFSET), + GetParamValue(revitWall, BuiltInParameter.WALL_TOP_OFFSET), + revitWall.Flipped, + GetParamValue(revitWall, BuiltInParameter.WALL_STRUCTURAL_SIGNIFICANT) + ); //CreateVoids(revitWall, speckleWall); if (revitWall.CurtainGrid is not CurtainGrid grid) @@ -261,19 +264,33 @@ private IEnumerable GetSubsetOfElementsInView(BuiltInCategory categor return children; } - var allSubelementsInView = revitDocumentAggregateCache - .GetOrInitializeEmptyCacheOfType>(out _) - .GetOrAdd( - category.ToString(), - () => - { - using var filter = new ElementCategoryFilter(category); - using var collector = new FilteredElementCollector(Doc, ViewSpecificOptions.View.Id); + var allSubelementsInView = new HashSet(); + + if (revitDocumentAggregateCache is null) + { + var filter = new ElementCategoryFilter(category); + var collector = new FilteredElementCollector(Doc, ViewSpecificOptions.View.Id); - return new HashSet(collector.WhereElementIsNotElementType().WherePasses(filter).ToElementIds()); - }, - out _ + allSubelementsInView = new HashSet( + collector.WhereElementIsNotElementType().WherePasses(filter).ToElementIds() ); + } + else + { + allSubelementsInView = revitDocumentAggregateCache + .GetOrInitializeEmptyCacheOfType>(out _) + .GetOrAdd( + category.ToString(), + () => + { + using var filter = new ElementCategoryFilter(category); + using var collector = new FilteredElementCollector(Doc, ViewSpecificOptions.View.Id); + + return new HashSet(collector.WhereElementIsNotElementType().WherePasses(filter).ToElementIds()); + }, + out _ + ); + } return children.Where(allSubelementsInView.Contains); } diff --git a/Objects/Converters/ConverterRevit/ConverterRevitShared/RevitElementTypeUtils.cs b/Objects/Converters/ConverterRevit/ConverterRevitShared/RevitElementTypeUtils.cs index f6ce277023..43678de1c8 100644 --- a/Objects/Converters/ConverterRevit/ConverterRevitShared/RevitElementTypeUtils.cs +++ b/Objects/Converters/ConverterRevit/ConverterRevitShared/RevitElementTypeUtils.cs @@ -140,6 +140,12 @@ public void SetElementFamily(Base @base, string family) appObj.Update(logItem: $"Could not find valid incoming type for element of type \"{element.speckle_type}\""); } var typeInfo = AllCategories.GetRevitCategoryInfo(element); + + if (revitDocumentAggregateCache is null) + { + return default; + } + var types = revitDocumentAggregateCache .GetOrInitializeWithDefaultFactory>() .GetOrAddGroupOfTypes(typeInfo); diff --git a/Objects/Converters/ConverterTeklaStructures/ConverterTeklaStructuresShared/PartialClasses/ConvertBeam.cs b/Objects/Converters/ConverterTeklaStructures/ConverterTeklaStructuresShared/PartialClasses/ConvertBeam.cs index 8ad1e75f55..1c9f0980ff 100644 --- a/Objects/Converters/ConverterTeklaStructures/ConverterTeklaStructuresShared/PartialClasses/ConvertBeam.cs +++ b/Objects/Converters/ConverterTeklaStructures/ConverterTeklaStructuresShared/PartialClasses/ConvertBeam.cs @@ -192,12 +192,14 @@ public TeklaBeam BeamToSpeckle(Tekla.Structures.Model.Beam beam) Point speckleStartPoint = new(startPoint.X, startPoint.Y, startPoint.Z, units); Point speckleEndPoint = new(endPoint.X, endPoint.Y, endPoint.Z, units); - speckleBeam.baseLine = new Line(speckleStartPoint, speckleEndPoint, units); - speckleBeam.baseLine.length = Math.Sqrt( - Math.Pow((startPoint.X - endPoint.X), 2) - + Math.Pow((startPoint.Y - endPoint.Y), 2) - + Math.Pow((startPoint.Z - endPoint.Z), 2) - ); + speckleBeam.baseLine = new Line(speckleStartPoint, speckleEndPoint, units) + { + length = Math.Sqrt( + Math.Pow((startPoint.X - endPoint.X), 2) + + Math.Pow((startPoint.Y - endPoint.Y), 2) + + Math.Pow((startPoint.Z - endPoint.Z), 2) + ), + }; speckleBeam.profile = GetBeamProfile(beam.Profile.ProfileString); speckleBeam.material = GetMaterial(beam.Material.MaterialString); var beamCS = beam.GetCoordinateSystem(); diff --git a/Objects/Objects/BuiltElements/AdvanceSteel/AsteelBeam.cs b/Objects/Objects/BuiltElements/AdvanceSteel/AsteelBeam.cs index 83db3e1c81..af9fde1bba 100644 --- a/Objects/Objects/BuiltElements/AdvanceSteel/AsteelBeam.cs +++ b/Objects/Objects/BuiltElements/AdvanceSteel/AsteelBeam.cs @@ -1,5 +1,3 @@ -using System.Collections.Generic; -using Objects.Geometry; using Objects.Structural.Materials; using Objects.Structural.Properties.Profiles; using Speckle.Core.Kits; @@ -7,7 +5,7 @@ namespace Objects.BuiltElements.AdvanceSteel; -public class AsteelBeam : Beam, IDisplayValue>, IHasVolume, IHasArea, IAsteelObject +public class AsteelBeam : Beam, IHasVolume, IHasArea, IAsteelObject { [DetachProperty] public SectionProfile profile { get; set; } diff --git a/Objects/Objects/BuiltElements/Archicad/ArchicadOpening.cs b/Objects/Objects/BuiltElements/Archicad/ArchicadOpening.cs new file mode 100644 index 0000000000..3c501c95bf --- /dev/null +++ b/Objects/Objects/BuiltElements/Archicad/ArchicadOpening.cs @@ -0,0 +1,83 @@ +using System.Collections.Generic; +using Speckle.Core.Kits; +using Speckle.Core.Models; +using Objects.Geometry; + +namespace Objects.BuiltElements.Archicad; + +public class ArchicadOpening : Opening +{ + [SchemaInfo("ArchicadOpening", "Creates an Archicad opening.", "Archicad", "Structure")] + public ArchicadOpening() { } + + public string parentApplicationId { get; set; } + + // Element base + public string? elementType { get; set; } /*APINullabe*/ + + public List? classifications { get; set; } /*APINullabe*/ + public Base? elementProperties { get; set; } + public Base? componentProperties { get; set; } + + // Floor Plan Parameters + public string? floorPlanDisplayMode { get; set; } /*APINullabe*/ + public string? connectionMode { get; set; } /*APINullabe*/ + + // Cut Surfaces Parameters + public bool? cutsurfacesUseLineOfCutElements { get; set; } /*APINullabe*/ + public short? cutsurfacesLinePenIndex { get; set; } /*APINullabe*/ + public string? cutsurfacesLineIndex { get; set; } /*APINullabe*/ + + // Outlines Parameters + public string? outlinesStyle { get; set; } /*APINullabe*/ + public bool? outlinesUseLineOfCutElements { get; set; } /*APINullabe*/ + public string? outlinesUncutLineIndex { get; set; } /*APINullabe*/ + public string? outlinesOverheadLineIndex { get; set; } /*APINullabe*/ + public short? outlinesUncutLinePenIndex { get; set; } /*APINullabe*/ + public short? outlinesOverheadLinePenIndex { get; set; } /*APINullabe*/ + + // Opening Cover Fills Parameters + public bool? useCoverFills { get; set; } /*APINullabe*/ + public bool? useFillsOfCutElements { get; set; } /*APINullabe*/ + public string? coverFillIndex { get; set; } /*APINullabe*/ + public short? coverFillPenIndex { get; set; } /*APINullabe*/ + public short? coverFillBackgroundPenIndex { get; set; } /*APINullabe*/ + public string? coverFillOrientation { get; set; } /*APINullabe*/ // Kérdéses.. + + // Cover Fill Transformation Parameters + public double? coverFillTransformationOrigoX { get; set; } + public double? coverFillTransformationOrigoY { get; set; } + public double? coverFillTransformationOrigoZ { get; set; } + public double? coverFillTransformationXAxisX { get; set; } + public double? coverFillTransformationXAxisY { get; set; } + public double? coverFillTransformationXAxisZ { get; set; } + public double? coverFillTransformationYAxisX { get; set; } + public double? coverFillTransformationYAxisY { get; set; } + public double? coverFillTransformationYAxisZ { get; set; } + + // Reference Axis Parameters + public bool? showReferenceAxis { get; set; } /*APINullabe*/ + public short? referenceAxisPenIndex { get; set; } /*APINullabe*/ + public string? referenceAxisLineTypeIndex { get; set; } /*APINullabe*/ + public double? referenceAxisOverhang { get; set; } /*APINullabe*/ + + // Extrusion Geometry Parameters + // Plane Frame + public Point extrusionGeometryBasePoint { get; set; } + public Vector extrusionGeometryXAxis { get; set; } + public Vector extrusionGeometryYAxis { get; set; } + public Vector extrusionGeometryZAxis { get; set; } + + // Opening Extrustion Parameters + public string? basePolygonType { get; set; } /*APINullabe*/ + public double? width { get; set; } /*APINullabe*/ + public double? height { get; set; } /*APINullabe*/ + public string? constraint { get; set; } /*APINullabe*/ + public string? anchor { get; set; } /*APINullabe */ + public int? anchorIndex { get; set; } /*APINullabe*/ + public double? anchorAltitude { get; set; } /*APINullabe*/ + public string? limitType { get; set; } /*APINullabe*/ + public double? extrusionStartOffSet { get; set; } /*APINullabe*/ + public double? finiteBodyLength { get; set; } /*APINullabe*/ + public string? linkedStatus { get; set; } /*APINullabe*/ +} diff --git a/Objects/Objects/BuiltElements/Archicad/DirectShape.cs b/Objects/Objects/BuiltElements/Archicad/DirectShape.cs index 8b2f11caf0..8ae08ece91 100644 --- a/Objects/Objects/BuiltElements/Archicad/DirectShape.cs +++ b/Objects/Objects/BuiltElements/Archicad/DirectShape.cs @@ -16,7 +16,10 @@ public DirectShape(string applicationId, List displayValue) // Element base public string elementType { get; set; } + public List classifications { get; set; } + public Base? elementProperties { get; set; } + public Base? componentProperties { get; set; } public ArchicadLevel level { get; set; } diff --git a/Objects/Objects/BuiltElements/Archicad/ElementShape.cs b/Objects/Objects/BuiltElements/Archicad/ElementShape.cs index 4da45cb3ae..cd78ab4717 100644 --- a/Objects/Objects/BuiltElements/Archicad/ElementShape.cs +++ b/Objects/Objects/BuiltElements/Archicad/ElementShape.cs @@ -1,7 +1,9 @@ using System.Collections.Generic; using Objects.Geometry; using Objects.Primitive; +using Speckle.Core.Kits; using Speckle.Core.Models; +using Speckle.Newtonsoft.Json; namespace Objects.BuiltElements.Archicad; @@ -19,6 +21,9 @@ public ElementShape(Polyline contourPolyline, List? holePolylines = nu public List? holePolylines { get; set; } + /// + /// This class is only used for Archicad interop + /// public sealed class PolylineSegment : Base, ICurve { public PolylineSegment() { } @@ -33,21 +38,30 @@ public PolylineSegment(Point startPoint, Point endPoint, double? arcAngle = null public Point startPoint { get; set; } public Point endPoint { get; set; } + + [JsonIgnore] + public string units => Units.Meters; public double arcAngle { get; set; } public bool? bodyFlag { get; set; } public double length { get; set; } public Interval domain { get; set; } = new(0, 1); } + /// + /// This class is only used for Archicad interop + /// public sealed class Polyline : Base, ICurve { public Polyline() { } public Polyline(List segments) { - polylineSegments = segments; + this.polylineSegments = segments; } + [JsonIgnore] + public string units => Units.Meters; + public List polylineSegments { get; set; } = new(); public double length { get; set; } public Interval domain { get; set; } = new(0, 1); diff --git a/Objects/Objects/BuiltElements/Baseline.cs b/Objects/Objects/BuiltElements/Baseline.cs new file mode 100644 index 0000000000..a78fc9b069 --- /dev/null +++ b/Objects/Objects/BuiltElements/Baseline.cs @@ -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; + } + + /// + /// The name of this baseline + /// + public string name { get; set; } + + /// + /// The horizontal component of this baseline + /// + public abstract Alignment? alignment { get; internal set; } + + /// + /// The vertical component of this baseline + /// + public abstract Profile? profile { get; internal set; } + + [DetachProperty] + public Featureline? featureline { get; internal set; } + + public bool isFeaturelineBased { get; set; } +} + +/// +/// Generic instance class +/// +public abstract class Baseline : 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; + } + } + } +} diff --git a/Objects/Objects/BuiltElements/Beam.cs b/Objects/Objects/BuiltElements/Beam.cs index 7d917c6c93..d868921632 100644 --- a/Objects/Objects/BuiltElements/Beam.cs +++ b/Objects/Objects/BuiltElements/Beam.cs @@ -5,22 +5,31 @@ namespace Objects.BuiltElements; -public class Beam : Base, IDisplayValue> +public class Beam : Base, IDisplayValue> { public Beam() { } - [SchemaInfo("Beam", "Creates a Speckle beam", "BIM", "Structure")] - public Beam([SchemaMainParam] ICurve baseLine) + public Beam(ICurve baseLine, Level? level, string? units, IReadOnlyList? displayValue = null) { this.baseLine = baseLine; + this.level = level; + this.units = units; + this.displayValue = ((IReadOnlyList?)displayValue) ?? new[] { (Base)baseLine }; } public ICurve baseLine { get; set; } public virtual Level? level { get; internal set; } - public string units { get; set; } + public string? units { get; set; } [DetachProperty] - public List displayValue { get; set; } + public IReadOnlyList displayValue { get; set; } + + #region Schema Info Constructors + [SchemaInfo("Beam", "Creates a Speckle beam", "BIM", "Structure")] + public Beam([SchemaMainParam] ICurve baseLine) + : this(baseLine, null, null) { } + + #endregion } diff --git a/Objects/Objects/BuiltElements/Brace.cs b/Objects/Objects/BuiltElements/Brace.cs index c51cd56828..c8a90447ee 100644 --- a/Objects/Objects/BuiltElements/Brace.cs +++ b/Objects/Objects/BuiltElements/Brace.cs @@ -5,20 +5,25 @@ namespace Objects.BuiltElements; -public class Brace : Base, IDisplayValue> +public class Brace : Base, IDisplayValue> { public Brace() { } - [SchemaInfo("Brace", "Creates a Speckle brace", "BIM", "Structure")] - public Brace([SchemaMainParam] ICurve baseLine) + public Brace(ICurve baseLine, string? units, IReadOnlyList? displayValue = null) { this.baseLine = baseLine; + this.units = units; + this.displayValue = ((IReadOnlyList?)displayValue) ?? new[] { (Base)baseLine }; } public ICurve baseLine { get; set; } - public string units { get; set; } + public string? units { get; set; } [DetachProperty] - public List displayValue { get; set; } + public IReadOnlyList displayValue { get; set; } + + [SchemaInfo("Brace", "Creates a Speckle brace", "BIM", "Structure")] + public Brace([SchemaMainParam] ICurve baseLine) + : this(baseLine, null) { } } diff --git a/Objects/Objects/BuiltElements/Civil/CivilAppliedAssembly.cs b/Objects/Objects/BuiltElements/Civil/CivilAppliedAssembly.cs new file mode 100644 index 0000000000..f490c643de --- /dev/null +++ b/Objects/Objects/BuiltElements/Civil/CivilAppliedAssembly.cs @@ -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 appliedSubassemblies, + double adjustedElevation, + string units + ) + { + this.appliedSubassemblies = appliedSubassemblies; + this.adjustedElevation = adjustedElevation; + this.units = units; + } + + public List appliedSubassemblies { get; set; } + + public double adjustedElevation { get; set; } + + public string units { get; set; } +} diff --git a/Objects/Objects/BuiltElements/Civil/CivilAppliedSubassembly.cs b/Objects/Objects/BuiltElements/Civil/CivilAppliedSubassembly.cs new file mode 100644 index 0000000000..f4beb7a3d0 --- /dev/null +++ b/Objects/Objects/BuiltElements/Civil/CivilAppliedSubassembly.cs @@ -0,0 +1,37 @@ +using System.Collections.Generic; +using Objects.Geometry; +using Objects.Other.Civil; +using Speckle.Core.Models; + +namespace Objects.BuiltElements.Civil; + +public class CivilAppliedSubassembly : Base +{ + public CivilAppliedSubassembly() { } + + public CivilAppliedSubassembly( + string subassemblyId, + string subassemblyName, + List shapes, + Point stationOffsetElevationToBaseline, + List parameters + ) + { + this.subassemblyId = subassemblyId; + this.subassemblyName = subassemblyName; + this.shapes = shapes; + this.stationOffsetElevationToBaseline = stationOffsetElevationToBaseline; + this.parameters = parameters; + } + + public string subassemblyId { get; set; } + + public string subassemblyName { get; set; } + + public List shapes { get; set; } + + public Point stationOffsetElevationToBaseline { get; set; } + + [DetachProperty] + public List parameters { get; set; } +} diff --git a/Objects/Objects/BuiltElements/Civil/CivilBaseline.cs b/Objects/Objects/BuiltElements/Civil/CivilBaseline.cs new file mode 100644 index 0000000000..826ef8df2b --- /dev/null +++ b/Objects/Objects/BuiltElements/Civil/CivilBaseline.cs @@ -0,0 +1,54 @@ +using System.Collections.Generic; + +namespace Objects.BuiltElements.Civil; + +public class CivilBaseline : Baseline +{ + public CivilBaseline() { } + + public CivilBaseline( + string name, + List regions, + List stations, + double startStation, + double endStation, + CivilAlignment alignment, + CivilProfile profile + ) + { + this.name = name; + this.regions = regions; + this.stations = stations; + this.startStation = startStation; + this.endStation = endStation; + this.alignment = alignment; + this.profile = profile; + isFeaturelineBased = false; + } + + public CivilBaseline( + string name, + List regions, + List stations, + double startStation, + double endStation, + Featureline featureline + ) + { + this.name = name; + this.regions = regions; + this.stations = stations; + this.startStation = startStation; + this.endStation = endStation; + this.featureline = featureline; + isFeaturelineBased = true; + } + + public List regions { get; set; } + + public List stations { get; set; } + + public double startStation { get; set; } + + public double endStation { get; set; } +} diff --git a/Objects/Objects/BuiltElements/Civil/CivilBaselineRegion.cs b/Objects/Objects/BuiltElements/Civil/CivilBaselineRegion.cs new file mode 100644 index 0000000000..5aabffd3f7 --- /dev/null +++ b/Objects/Objects/BuiltElements/Civil/CivilBaselineRegion.cs @@ -0,0 +1,45 @@ +using System.Collections.Generic; +using Speckle.Core.Models; + +namespace Objects.BuiltElements.Civil; + +public class CivilBaselineRegion : Base +{ + public CivilBaselineRegion() { } + + public CivilBaselineRegion( + string name, + double startStation, + double endStation, + string assemblyId, + string? assemblyName, + List appliedAssemblies + ) + { + this.name = name; + this.startStation = startStation; + this.endStation = endStation; + this.assemblyId = assemblyId; + this.assemblyName = assemblyName; + this.appliedAssemblies = appliedAssemblies; + } + + /// + /// The name of the region + /// + public string name { get; set; } + + /// + /// The id of the assembly of the region + /// + public string assemblyId { get; set; } + + public string? assemblyName { get; set; } + + public double startStation { get; set; } + + public double endStation { get; set; } + + [DetachProperty] + public List appliedAssemblies { get; set; } +} diff --git a/Objects/Objects/BuiltElements/Civil/CivilCalculatedLink.cs b/Objects/Objects/BuiltElements/Civil/CivilCalculatedLink.cs new file mode 100644 index 0000000000..aa0bc94979 --- /dev/null +++ b/Objects/Objects/BuiltElements/Civil/CivilCalculatedLink.cs @@ -0,0 +1,20 @@ +using System.Collections.Generic; +using Speckle.Core.Models; + +namespace Objects.BuiltElements.Civil; + +public class CivilCalculatedLink : Base, ICivilCalculatedObject +{ + public CivilCalculatedLink() { } + + public CivilCalculatedLink(List codes, List points) + { + this.codes = codes; + this.points = points; + } + + public List codes { get; set; } + + [DetachProperty] + public List points { get; set; } +} diff --git a/Objects/Objects/BuiltElements/Civil/CivilCalculatedPoint.cs b/Objects/Objects/BuiltElements/Civil/CivilCalculatedPoint.cs new file mode 100644 index 0000000000..c6ed147b4f --- /dev/null +++ b/Objects/Objects/BuiltElements/Civil/CivilCalculatedPoint.cs @@ -0,0 +1,35 @@ +using System.Collections.Generic; +using Objects.Geometry; +using Speckle.Core.Models; + +namespace Objects.BuiltElements.Civil; + +public class CivilCalculatedPoint : Base, ICivilCalculatedObject +{ + public CivilCalculatedPoint() { } + + public CivilCalculatedPoint( + Point point, + List codes, + Vector normalToBaseline, + Vector normalToSubassembly, + Point stationOffsetElevationToBaseline + ) + { + this.point = point; + this.codes = codes; + this.normalToBaseline = normalToBaseline; + this.normalToSubassembly = normalToSubassembly; + this.stationOffsetElevationToBaseline = stationOffsetElevationToBaseline; + } + + public Point point { get; set; } + + public List codes { get; set; } + + public Vector normalToBaseline { get; set; } + + public Vector normalToSubassembly { get; set; } + + public Point stationOffsetElevationToBaseline { get; set; } +} diff --git a/Objects/Objects/BuiltElements/Civil/CivilCalculatedShape.cs b/Objects/Objects/BuiltElements/Civil/CivilCalculatedShape.cs new file mode 100644 index 0000000000..1e6a3fb7b6 --- /dev/null +++ b/Objects/Objects/BuiltElements/Civil/CivilCalculatedShape.cs @@ -0,0 +1,26 @@ +using System.Collections.Generic; +using Speckle.Core.Models; + +namespace Objects.BuiltElements.Civil; + +public class CivilCalculatedShape : Base, ICivilCalculatedObject +{ + public CivilCalculatedShape() { } + + public CivilCalculatedShape(List codes, List links, double area, string units) + { + this.codes = codes; + this.links = links; + this.area = area; + this.units = units; + } + + public List codes { get; set; } + + [DetachProperty] + public List links { get; set; } + + public double area { get; set; } + + public string units { get; set; } +} diff --git a/Objects/Objects/BuiltElements/Column.cs b/Objects/Objects/BuiltElements/Column.cs index e13e054eaa..3b4d405575 100644 --- a/Objects/Objects/BuiltElements/Column.cs +++ b/Objects/Objects/BuiltElements/Column.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Objects.Geometry; using Speckle.Core.Kits; @@ -5,22 +6,32 @@ namespace Objects.BuiltElements; -public class Column : Base, IDisplayValue> +public class Column : Base, IDisplayValue> { public Column() { } - [SchemaInfo("Column", "Creates a Speckle column", "BIM", "Structure")] - public Column([SchemaMainParam] ICurve baseLine) + public Column(ICurve baseLine, string? units, Level? level = null, IReadOnlyList? displayValue = null) { this.baseLine = baseLine; + this.units = units; + this.level = level; + this.displayValue = ((IReadOnlyList?)displayValue) ?? new[] { (Base)baseLine }; } public ICurve baseLine { get; set; } public virtual Level? level { get; internal set; } - public string units { get; set; } + public string? units { get; set; } [DetachProperty] - public List displayValue { get; set; } + public IReadOnlyList displayValue { get; set; } + + #region Schema Info Constructors + + [SchemaInfo("Column", "Creates a Speckle column", "BIM", "Structure")] + [SchemaDeprecated, Obsolete("Use other constructor")] + public Column([SchemaMainParam] ICurve baseLine) + : this(baseLine, null) { } + #endregion } diff --git a/Objects/Objects/BuiltElements/Duct.cs b/Objects/Objects/BuiltElements/Duct.cs index f530be6faf..6ef56bbc53 100644 --- a/Objects/Objects/BuiltElements/Duct.cs +++ b/Objects/Objects/BuiltElements/Duct.cs @@ -7,10 +7,47 @@ namespace Objects.BuiltElements; -public class Duct : Base, IDisplayValue> +public class Duct : Base, IDisplayValue> { public Duct() { } + public Duct( + ICurve baseCurve, + double width, + double height, + double diameter, + double length, + string? units, + double velocity = 0, + IReadOnlyList? displayValue = null + ) + { + this.baseCurve = baseCurve; + this.width = width; + this.height = height; + this.diameter = diameter; + this.length = length; + this.units = units; + this.velocity = velocity; + this.displayValue = ((IReadOnlyList?)displayValue) ?? new[] { (Base)baseCurve }; + } + + [JsonIgnore, Obsolete("Replaced with baseCurve property")] + public Line? baseLine { get; set; } + + public ICurve baseCurve { get; set; } + public double width { get; set; } + public double height { get; set; } + public double diameter { get; set; } + public double length { get; set; } + public double velocity { get; set; } + + public string? units { get; set; } + + [DetachProperty] + public IReadOnlyList displayValue { get; set; } + + #region Schema Info Constructors /// /// SchemaBuilder constructor for a Speckle duct /// @@ -22,13 +59,8 @@ public Duct() { } /// Assign units when using this constructor due to , , and params [SchemaInfo("Duct", "Creates a Speckle duct", "BIM", "MEP"), SchemaDeprecated] public Duct([SchemaMainParam] Line baseLine, double width, double height, double diameter, double velocity = 0) - { - baseCurve = baseLine; - this.width = width; - this.height = height; - this.diameter = diameter; - this.velocity = velocity; - } + : this(baseLine, width, height, diameter, default, null, velocity) //TODO: what to do with length??? + { } /// /// SchemaBuilder constructor for a Speckle duct @@ -41,26 +73,6 @@ public Duct([SchemaMainParam] Line baseLine, double width, double height, double /// Assign units when using this constructor due to , , and params [SchemaInfo("Duct", "Creates a Speckle duct", "BIM", "MEP")] public Duct([SchemaMainParam] ICurve baseCurve, double width, double height, double diameter, double velocity = 0) - { - this.baseCurve = baseCurve; - this.width = width; - this.height = height; - this.diameter = diameter; - this.velocity = velocity; - } - - [JsonIgnore, Obsolete("Replaced with baseCurve property")] - public Line baseLine { get; set; } - - public ICurve baseCurve { get; set; } - public double width { get; set; } - public double height { get; set; } - public double diameter { get; set; } - public double length { get; set; } - public double velocity { get; set; } - - public string units { get; set; } - - [DetachProperty] - public List displayValue { get; set; } + : this(baseCurve, width, height, diameter, default, null, velocity) { } //TODO: what to do with length??? + #endregion } diff --git a/Objects/Objects/BuiltElements/Revit/RevitBeam.cs b/Objects/Objects/BuiltElements/Revit/RevitBeam.cs index b483b12a11..6d7859e3da 100644 --- a/Objects/Objects/BuiltElements/Revit/RevitBeam.cs +++ b/Objects/Objects/BuiltElements/Revit/RevitBeam.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Objects.Geometry; using Objects.Utils; using Speckle.Core.Kits; using Speckle.Core.Models; @@ -9,20 +10,20 @@ public class RevitBeam : Beam { public RevitBeam() { } - [SchemaInfo("RevitBeam", "Creates a Revit beam by curve and base level.", "Revit", "Structure")] public RevitBeam( string family, string type, - [SchemaMainParam] ICurve baseLine, - Level level, + ICurve baseLine, + Level? level, + string? units, + List? displayValue = null, List? parameters = null ) + : base(baseLine, level, units, displayValue) { this.family = family; this.type = type; - this.baseLine = baseLine; this.parameters = parameters?.ToBase(); - this.level = level; } public string family { get; set; } @@ -35,4 +36,18 @@ public RevitBeam( get => base.level; set => base.level = value; } + + #region Schema Info Constructors + + [SchemaInfo("RevitBeam", "Creates a Revit beam by curve and base level.", "Revit", "Structure")] + public RevitBeam( + string family, + string type, + [SchemaMainParam] ICurve baseLine, + Level level, + List? parameters = null + ) + : this(family, type, baseLine, level, null, parameters: parameters) { } + + #endregion } diff --git a/Objects/Objects/BuiltElements/Revit/RevitBrace.cs b/Objects/Objects/BuiltElements/Revit/RevitBrace.cs index 6254f5e9b8..ce5966afc6 100644 --- a/Objects/Objects/BuiltElements/Revit/RevitBrace.cs +++ b/Objects/Objects/BuiltElements/Revit/RevitBrace.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using Objects.Geometry; using Objects.Utils; using Speckle.Core.Kits; using Speckle.Core.Models; @@ -9,25 +10,42 @@ public class RevitBrace : Brace { public RevitBrace() { } - [SchemaInfo("RevitBrace", "Creates a Revit brace by curve and base level.", "Revit", "Structure")] public RevitBrace( string family, string type, - [SchemaMainParam] ICurve baseLine, + ICurve baseLine, Level? level, + string? units, + string? elementId, + IReadOnlyList? displayValue = null, List? parameters = null ) + : base(baseLine, units, displayValue) { this.family = family; this.type = type; - this.baseLine = baseLine; - this.parameters = parameters?.ToBase(); this.level = level; + this.elementId = elementId; + this.parameters = parameters?.ToBase(); } public string family { get; set; } public string type { get; set; } public Base? parameters { get; set; } - public string elementId { get; set; } + public string? elementId { get; set; } public Level? level { get; set; } + + #region Schema Info Constructor + + [SchemaInfo("RevitBrace", "Creates a Revit brace by curve and base level.", "Revit", "Structure")] + public RevitBrace( + string family, + string type, + [SchemaMainParam] ICurve baseLine, + Level? level, + List? parameters = null + ) + : this(family, type, baseLine, level, null, null, parameters: parameters) { } + + #endregion } diff --git a/Objects/Objects/BuiltElements/Revit/RevitColumn.cs b/Objects/Objects/BuiltElements/Revit/RevitColumn.cs index 5a770db9ba..64e4db93b0 100644 --- a/Objects/Objects/BuiltElements/Revit/RevitColumn.cs +++ b/Objects/Objects/BuiltElements/Revit/RevitColumn.cs @@ -1,4 +1,6 @@ +using System; using System.Collections.Generic; +using Objects.Geometry; using Objects.Utils; using Speckle.Core.Kits; using Speckle.Core.Models; @@ -9,49 +11,82 @@ public class RevitColumn : Column { public RevitColumn() { } - /// - /// SchemaBuilder constructor for a Revit column - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// Assign units when using this constructor due to and params - [SchemaInfo("RevitColumn Vertical", "Creates a vertical Revit Column by point and levels.", "Revit", "Architecture")] public RevitColumn( string family, string type, - [SchemaParamInfo("Only the lower point of this line will be used as base point."), SchemaMainParam] ICurve baseLine, - Level level, - Level topLevel, + ICurve baseLine, + Level? level, + Level? topLevel, + string? units, + string? elementId, double baseOffset = 0, double topOffset = 0, - bool structural = false, - [SchemaParamInfo("Rotation angle in radians")] double rotation = 0, + bool facingFlipped = false, + bool handFlipped = false, + bool isSlanted = false, + double rotation = 0, + IReadOnlyList? displayValue = null, List? parameters = null ) + : base(baseLine, units, level, displayValue) { this.family = family; this.type = type; - this.baseLine = baseLine; this.topLevel = topLevel; + this.elementId = elementId; this.baseOffset = baseOffset; this.topOffset = topOffset; + this.facingFlipped = facingFlipped; + this.handFlipped = handFlipped; + this.isSlanted = isSlanted; this.rotation = rotation; this.parameters = parameters?.ToBase(); - this.level = level; } - [ - SchemaDeprecated, - SchemaInfo("RevitColumn Slanted (old)", "Creates a slanted Revit Column by curve.", "Revit", "Structure") - ] + public Level? topLevel { get; set; } + public double baseOffset { get; set; } + public double topOffset { get; set; } + public bool facingFlipped { get; set; } + public bool handFlipped { get; set; } + public double rotation { get; set; } + public bool isSlanted { get; set; } + public string family { get; set; } + public string type { get; set; } + public Base? parameters { get; set; } + public string? elementId { get; set; } + + #region Schema Info Constructors + + [SchemaInfo("RevitColumn Vertical", "Creates a vertical Revit Column by point and levels.", "Revit", "Architecture")] + public RevitColumn( + string family, + string type, + [SchemaParamInfo("Only the lower point of this line will be used as base point."), SchemaMainParam] ICurve baseLine, + Level level, + Level topLevel, + double baseOffset = 0, + double topOffset = 0, + bool structural = false, + [SchemaParamInfo("Rotation angle in radians")] double rotation = 0, + List? parameters = null + ) + : this( + family, + type, + baseLine, + level, + topLevel, + null, + null, + baseOffset, + topOffset, + rotation: rotation, + parameters: parameters + ) { } + + [Obsolete("Use other constructors")] + [SchemaDeprecated] + [SchemaInfo("RevitColumn Slanted (old)", "Creates a slanted Revit Column by curve.", "Revit", "Structure")] [System.Diagnostics.CodeAnalysis.SuppressMessage( "Style", "IDE0060:Remove unused parameter", @@ -84,31 +119,7 @@ public RevitColumn( bool structural = false, List? parameters = null ) - { - this.family = family; - this.type = type; - this.baseLine = baseLine; - this.level = level; - this.topLevel = topLevel; - isSlanted = true; - this.parameters = parameters?.ToBase(); - } - - public new Level? level - { - get => base.level; - set => base.level = value; - } + : this(family, type, baseLine, level, topLevel, null, null, displayValue: null, parameters: parameters) { } - public Level? topLevel { get; set; } - public double baseOffset { get; set; } - public double topOffset { get; set; } - public bool facingFlipped { get; set; } - public bool handFlipped { get; set; } - public double rotation { get; set; } - public bool isSlanted { get; set; } - public string family { get; set; } - public string type { get; set; } - public Base? parameters { get; set; } - public string elementId { get; set; } + #endregion } diff --git a/Objects/Objects/BuiltElements/Revit/RevitDuct.cs b/Objects/Objects/BuiltElements/Revit/RevitDuct.cs index 8c75f4ba04..1501466456 100644 --- a/Objects/Objects/BuiltElements/Revit/RevitDuct.cs +++ b/Objects/Objects/BuiltElements/Revit/RevitDuct.cs @@ -1,3 +1,4 @@ +using System; using System.Collections.Generic; using Objects.BuiltElements.Revit.Interfaces; using Objects.Geometry; @@ -11,69 +12,52 @@ public class RevitDuct : Duct, IHasMEPConnectors { public RevitDuct() { } - /// - /// SchemaBuilder constructor for a Revit duct (deprecated) - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// Assign units when using this constructor due to , , and params - [SchemaInfo("RevitDuct", "Creates a Revit duct", "Revit", "MEP"), SchemaDeprecated] public RevitDuct( string family, string type, - [SchemaMainParam] Line baseLine, + ICurve baseCurve, string systemName, string systemType, Level level, double width, double height, double diameter, + double length, + string? units, + string? elementId, double velocity = 0, + IReadOnlyList? displayValue = null, List? parameters = null ) + : base(baseCurve, width, height, diameter, length, units, velocity, displayValue) { - baseCurve = baseLine; this.family = family; this.type = type; - this.width = width; - this.height = height; - this.diameter = diameter; - this.velocity = velocity; this.systemName = systemName; this.systemType = systemType; - this.parameters = parameters?.ToBase(); this.level = level; + this.parameters = parameters?.ToBase(); + this.elementId = elementId; } - /// - /// SchemaBuilder constructor for a Revit duct - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// Assign units when using this constructor due to , , and params - [SchemaInfo("RevitDuct", "Creates a Revit duct", "Revit", "MEP")] + public string family { get; set; } + public string type { get; set; } + public string systemName { get; set; } + public string systemType { get; set; } + public Level level { get; set; } + public Base? parameters { get; set; } + public string? elementId { get; set; } + public List Connectors { get; set; } = new(); + + #region Schema Info Constructors + + [SchemaInfo("RevitDuct (DEPRECATED)", "Creates a Revit duct", "Revit", "MEP")] + [SchemaDeprecated] + [Obsolete("Use other Constructor")] public RevitDuct( string family, string type, - [SchemaMainParam] ICurve baseCurve, + [SchemaMainParam] Line baseLine, string systemName, string systemType, Level level, @@ -84,7 +68,7 @@ public RevitDuct( List? parameters = null ) { - this.baseCurve = baseCurve; + baseCurve = baseLine; this.family = family; this.type = type; this.width = width; @@ -97,36 +81,44 @@ public RevitDuct( this.level = level; } - public string family { get; set; } - public string type { get; set; } - public string systemName { get; set; } - public string systemType { get; set; } - public Level level { get; set; } - public Base? parameters { get; set; } - public string elementId { get; set; } - public List Connectors { get; set; } = new(); + [SchemaInfo("RevitDuct", "Creates a Revit duct", "Revit", "MEP")] + public RevitDuct( + string family, + string type, + [SchemaMainParam] ICurve baseCurve, + string systemName, + string systemType, + Level level, + double width, + double height, + double diameter, + double velocity = 0, + List? parameters = null + ) + : this( + family, + type, + baseCurve, + systemName, + systemType, + level, + width, + height, + diameter, + default, //TODO: what to do with length? + null, + null, + velocity, + parameters: parameters + ) { } + + #endregion } public class RevitFlexDuct : RevitDuct { public RevitFlexDuct() { } - /// - /// SchemaBuilder constructor for a Revit flex duct - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// Assign units when using this constructor due to , , and params - [SchemaInfo("RevitFlexDuct", "Creates a Revit flex duct", "Revit", "MEP")] public RevitFlexDuct( string family, string type, @@ -137,27 +129,76 @@ public RevitFlexDuct( double width, double height, double diameter, + double length, Vector startTangent, Vector endTangent, + string? units, + string? elementId, double velocity = 0, + IReadOnlyList? displayValue = null, List? parameters = null ) + : base( + family, + type, + baseCurve, + systemName, + systemType, + level, + width, + height, + diameter, + length, + units, + elementId, + velocity, + displayValue, + parameters + ) { - this.baseCurve = baseCurve; - this.family = family; - this.type = type; - this.width = width; - this.height = height; - this.diameter = diameter; this.startTangent = startTangent; this.endTangent = endTangent; - this.velocity = velocity; - this.systemName = systemName; - this.systemType = systemType; - this.parameters = parameters?.ToBase(); - this.level = level; } public Vector startTangent { get; set; } public Vector endTangent { get; set; } + + #region Schema Info Constructor + + [SchemaInfo("RevitFlexDuct", "Creates a Revit flex duct", "Revit", "MEP")] + public RevitFlexDuct( + string family, + string type, + [SchemaMainParam] ICurve baseCurve, + string systemName, + string systemType, + Level level, + double width, + double height, + double diameter, + Vector startTangent, + Vector endTangent, + double velocity = 0, + List? parameters = null + ) + : this( + family, + type, + baseCurve, + systemName, + systemType, + level, + width, + height, + diameter, + 0, + startTangent, + endTangent, + null, + null, + velocity, + parameters: parameters + ) { } + + #endregion } diff --git a/Objects/Objects/BuiltElements/Revit/RevitWall.cs b/Objects/Objects/BuiltElements/Revit/RevitWall.cs index ac9d4bfe29..a9d59dc5ad 100644 --- a/Objects/Objects/BuiltElements/Revit/RevitWall.cs +++ b/Objects/Objects/BuiltElements/Revit/RevitWall.cs @@ -11,69 +11,84 @@ public class RevitWall : Wall { public RevitWall() { } - /// - /// SchemaBuilder constructor for a Revit wall - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// Assign units when using this constructor due to and params - [SchemaInfo( - "RevitWall by curve and levels", - "Creates a Revit wall with a top and base level.", - "Revit", - "Architecture" - )] public RevitWall( string family, string type, - [SchemaMainParam] ICurve baseLine, + ICurve baseLine, Level level, - Level topLevel, + Level? topLevel, + double height, + string? units, + string? elementId, double baseOffset = 0, double topOffset = 0, bool flipped = false, bool structural = false, - [SchemaParamInfo("Set in here any nested elements that this level might have.")] List? elements = null, + IReadOnlyList? displayValue = null, + List? elements = null, List? parameters = null ) + : base(height, units, baseLine, level, displayValue, elements) { this.family = family; this.type = type; - this.baseLine = baseLine; this.baseOffset = baseOffset; this.topOffset = topOffset; this.flipped = flipped; this.structural = structural; - this.level = level; + this.elementId = elementId; this.topLevel = topLevel; - this.elements = elements; this.parameters = parameters?.ToBase(); } - /// - /// SchemaBuilder constructor for a Revit wall - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// Assign units when using this constructor due to , , and params + public string family { get; set; } + public string type { get; set; } + public double baseOffset { get; set; } + public double topOffset { get; set; } + public bool flipped { get; set; } + public bool structural { get; set; } + public Level? topLevel { get; set; } + public Base? parameters { get; set; } + public string? elementId { get; set; } + + #region Schema Info Constructors + + [SchemaInfo( + "RevitWall by curve and levels", + "Creates a Revit wall with a top and base level.", + "Revit", + "Architecture" + )] + public RevitWall( + string family, + string type, + [SchemaMainParam] ICurve baseLine, + Level level, + Level topLevel, + double baseOffset = 0, + double topOffset = 0, + bool flipped = false, + bool structural = false, + [SchemaParamInfo("Set in here any nested elements that this level might have.")] List? elements = null, + List? parameters = null + ) + : this( + family, + type, + baseLine, + level, + topLevel, + 0, + null, + null, + baseOffset, + topOffset, + flipped, + structural, + elements: elements, + parameters: parameters + ) { } + [SchemaInfo("RevitWall by curve and height", "Creates an unconnected Revit wall.", "Revit", "Architecture")] public RevitWall( string family, @@ -88,36 +103,23 @@ public RevitWall( [SchemaParamInfo("Set in here any nested elements that this wall might have.")] List? elements = null, List? parameters = null ) - { - this.family = family; - this.type = type; - this.baseLine = baseLine; - this.height = height; - this.baseOffset = baseOffset; - this.topOffset = topOffset; - this.flipped = flipped; - this.structural = structural; - this.level = level; - this.elements = elements; - this.parameters = parameters?.ToBase(); - } - - public string family { get; set; } - public string type { get; set; } - public double baseOffset { get; set; } - public double topOffset { get; set; } - public bool flipped { get; set; } - public bool structural { get; set; } - - public new Level? level - { - get => base.level; - set => base.level = value; - } - - public Level topLevel { get; set; } - public Base? parameters { get; set; } - public string elementId { get; set; } + : this( + family, + type, + baseLine, + level, + null, + height, + null, + null, + baseOffset, + topOffset, + flipped, + structural, + elements: elements, + parameters: parameters + ) { } + #endregion } public class RevitFaceWall : Wall diff --git a/Objects/Objects/BuiltElements/Wall.cs b/Objects/Objects/BuiltElements/Wall.cs index 9f6cb754d7..46b8684356 100644 --- a/Objects/Objects/BuiltElements/Wall.cs +++ b/Objects/Objects/BuiltElements/Wall.cs @@ -5,39 +5,48 @@ namespace Objects.BuiltElements; -public class Wall : Base, IDisplayValue> +public class Wall : Base, IDisplayValue> { public Wall() { } - /// - /// SchemaBuilder constructor for a Speckle wall - /// - /// - /// - /// - /// Assign units when using this constructor due to param - [SchemaInfo("Wall", "Creates a Speckle wall", "BIM", "Architecture")] public Wall( double height, - [SchemaMainParam] ICurve baseLine, - [SchemaParamInfo("Any nested elements that this wall might have")] List? elements = null + string? units, + ICurve baseLine, + Level? level = null, + IReadOnlyList? displayValue = null, + List? elements = null ) { this.height = height; + this.units = units; this.baseLine = baseLine; + this.level = level; + this.displayValue = ((IReadOnlyList?)displayValue) ?? new[] { (Base)baseLine }; this.elements = elements; } public double height { get; set; } - [DetachProperty] - public List? elements { get; set; } - + public string? units { get; set; } public ICurve baseLine { get; set; } public virtual Level? level { get; internal set; } - public string units { get; set; } + [DetachProperty] + public List? elements { get; set; } [DetachProperty] - public List displayValue { get; set; } + public IReadOnlyList displayValue { get; set; } + + #region SchemaInfo Ctors + + [SchemaInfo("Wall", "Creates a Speckle wall", "BIM", "Architecture")] + public Wall( + double height, + [SchemaMainParam] ICurve baseLine, + [SchemaParamInfo("Any nested elements that this wall might have")] List? elements = null + ) + : this(height, null, baseLine, null, null, elements) { } + + #endregion } diff --git a/Objects/Objects/Interfaces.cs b/Objects/Objects/Interfaces.cs index 9bd5aa4ea0..373e129d2e 100644 --- a/Objects/Objects/Interfaces.cs +++ b/Objects/Objects/Interfaces.cs @@ -28,7 +28,7 @@ public interface IHasArea /// /// The area of the object /// - double area { get; set; } + double area { get; } } /// @@ -39,7 +39,7 @@ public interface IHasVolume /// /// The volume of the object /// - double volume { get; set; } + double volume { get; } } /// @@ -50,12 +50,14 @@ public interface ICurve /// /// The length of the curve. /// - double length { get; set; } + double length { get; } /// /// The numerical domain driving the curve's internal parametrization. /// - Interval domain { get; set; } + Interval domain { get; } + + string units { get; } } /// @@ -110,5 +112,16 @@ public interface IDisplayValue T displayValue { get; } } +/// +/// Represents a calculated object for civil disciplines +/// +public interface ICivilCalculatedObject +{ + /// + /// for this calculated object. + /// + List codes { get; set; } +} + #endregion diff --git a/Objects/Objects/Objects.csproj b/Objects/Objects/Objects.csproj index b3463e5523..b4a703d8a8 100644 --- a/Objects/Objects/Objects.csproj +++ b/Objects/Objects/Objects.csproj @@ -33,4 +33,4 @@ - \ No newline at end of file + diff --git a/Objects/Objects/Other/Civil/CivilDataField.cs b/Objects/Objects/Other/Civil/CivilDataField.cs index 48e1a2ad83..6919669d85 100644 --- a/Objects/Objects/Other/Civil/CivilDataField.cs +++ b/Objects/Objects/Other/Civil/CivilDataField.cs @@ -4,17 +4,27 @@ public class CivilDataField : DataField { public CivilDataField() { } - public CivilDataField(string name, string type, string units, string context, object? value = null) + public CivilDataField( + string name, + string type, + object? value, + string? units = null, + string? context = null, + string? displayName = null + ) { this.name = name; this.type = type; + this.value = value; this.units = units; this.context = context; - this.value = value; + this.displayName = displayName; } /// /// The context type of the Civil3D part /// - public string context { get; set; } + public string? context { get; set; } + + public string? displayName { get; set; } } diff --git a/Objects/Objects/Other/DataField.cs b/Objects/Objects/Other/DataField.cs index 6770b3a8ef..4d3fd5a1ea 100644 --- a/Objects/Objects/Other/DataField.cs +++ b/Objects/Objects/Other/DataField.cs @@ -9,12 +9,12 @@ public class DataField : Base { public DataField() { } - public DataField(string name, string type, string units, object? value = null) + public DataField(string name, string type, object? value, string? units = null) { this.name = name; this.type = type; - this.units = units; this.value = value; + this.units = units; } public string name { get; set; } @@ -23,5 +23,5 @@ public DataField(string name, string type, string units, object? value = null) public object? value { get; set; } - public string units { get; set; } + public string? units { get; set; } } diff --git a/Objects/Objects/Structural/Geometry/Element1D.cs b/Objects/Objects/Structural/Geometry/Element1D.cs index d1d74eab82..abce21d796 100644 --- a/Objects/Objects/Structural/Geometry/Element1D.cs +++ b/Objects/Objects/Structural/Geometry/Element1D.cs @@ -6,27 +6,74 @@ namespace Objects.Structural.Geometry; -public class Element1D : Base, IDisplayValue> +public class Element1D : Base, IDisplayValue> { public Element1D() { } - public Element1D(Line baseLine) + public Element1D( + Line baseLine, + Property1D property, + ElementType1D type, + string? name, + string? units, + Restraint? end1Releases = null, + Restraint? end2Releases = null, + Vector? end1Offset = null, + Vector? end2Offset = null, + Plane? localAxis = null, + Node? orientationNode = null, + double orientationAngle = 0, + IReadOnlyList? displayValue = null + ) { this.baseLine = baseLine; + this.property = property; + this.type = type; + this.name = name; + this.units = units; + this.end1Releases = end1Releases ?? new Restraint("FFFFFF"); + this.end2Releases = end2Releases ?? new Restraint("FFFFFF"); + this.end1Offset = end1Offset ?? new Vector(0, 0, 0); + this.end2Offset = end2Offset ?? new Vector(0, 0, 0); + this.localAxis = localAxis; + this.orientationNode = orientationNode; + this.orientationAngle = orientationAngle; + this.displayValue = ((IReadOnlyList?)displayValue) ?? new[] { (Base)baseLine }; } - /// - /// SchemaBuilder constructor for structural 1D element (based on local axis) - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// + public string? name { get; set; } //add unique id as base identifier, name can change too easily + public Line baseLine { get; set; } + + [DetachProperty] + public Property1D property { get; set; } + + public ElementType1D type { get; set; } + public Restraint end1Releases { get; set; } + public Restraint end2Releases { get; set; } + public Vector end1Offset { get; set; } + public Vector end2Offset { get; set; } + public Node? orientationNode { get; set; } + public double orientationAngle { get; set; } + public Plane? localAxis { get; set; } + + [DetachProperty] + public Base? parent { get; set; } //parent element + + [DetachProperty] + public Node? end1Node { get; set; } //startNode + + [DetachProperty] + public Node? end2Node { get; set; } //endNode + + [DetachProperty] + public List? topology { get; set; } + + public string? units { get; set; } + + [DetachProperty] + public IReadOnlyList displayValue { get; set; } + + #region Schema Info Constructors [SchemaInfo( "Element1D (from local axis)", "Creates a Speckle structural 1D element (from local axis)", @@ -46,31 +93,8 @@ public Element1D( [SchemaParamInfo("If null, defaults to no offsets")] Vector? end2Offset = null, Plane? localAxis = null ) - { - this.baseLine = baseLine; - this.property = property; - this.type = type; - this.name = name; - this.end1Releases = end1Releases ?? new Restraint("FFFFFF"); - this.end2Releases = end2Releases ?? new Restraint("FFFFFF"); - this.end1Offset = end1Offset ?? new Vector(0, 0, 0); - this.end2Offset = end2Offset ?? new Vector(0, 0, 0); - this.localAxis = localAxis; - } + : this(baseLine, property, type, name, null, end1Releases, end2Releases, end1Offset, end2Offset, localAxis) { } - /// - /// SchemaBuilder constructor for structural 1D element (based on orientation node and angle) - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// - /// [SchemaInfo( "Element1D (from orientation node and angle)", "Creates a Speckle structural 1D element (from orientation node and angle)", @@ -91,48 +115,19 @@ public Element1D( Node? orientationNode = null, double orientationAngle = 0 ) - { - this.baseLine = baseLine; - this.property = property; - this.type = type; - this.name = name; - this.end1Releases = end1Releases ?? new Restraint("FFFFFF"); - this.end2Releases = end2Releases ?? new Restraint("FFFFFF"); - this.end1Offset = end1Offset ?? new Vector(0, 0, 0); - this.end2Offset = end2Offset ?? new Vector(0, 0, 0); - this.orientationNode = orientationNode; - this.orientationAngle = orientationAngle; - } - - public string? name { get; set; } //add unique id as base identifier, name can change too easily - public Line baseLine { get; set; } + : this( + baseLine, + property, + type, + name, + null, + end1Releases, + end2Releases, + end1Offset, + end2Offset, + orientationNode: orientationNode, + orientationAngle: orientationAngle + ) { } - [DetachProperty] - public Property1D property { get; set; } - - public ElementType1D type { get; set; } - public Restraint end1Releases { get; set; } - public Restraint end2Releases { get; set; } - public Vector end1Offset { get; set; } - public Vector end2Offset { get; set; } - public Node? orientationNode { get; set; } - public double orientationAngle { get; set; } - public Plane? localAxis { get; set; } - - [DetachProperty] - public Base parent { get; set; } //parent element - - [DetachProperty] - public Node end1Node { get; set; } //startNode - - [DetachProperty] - public Node end2Node { get; set; } //endNode - - [DetachProperty] - public List topology { get; set; } - - public string units { get; set; } - - [DetachProperty] - public List displayValue { get; set; } + #endregion } diff --git a/Objects/Tests/Objects.Tests.Unit/ModelPropertySupportedTypes.cs b/Objects/Tests/Objects.Tests.Unit/ModelPropertySupportedTypes.cs new file mode 100644 index 0000000000..342e0cad23 --- /dev/null +++ b/Objects/Tests/Objects.Tests.Unit/ModelPropertySupportedTypes.cs @@ -0,0 +1,81 @@ +using System; +using System.Collections.Generic; +using System.DoubleNumerics; +using System.Drawing; +using System.Linq; +using NUnit.Framework; +using Speckle.Core.Models; +using Speckle.Core.Serialisation; +using Speckle.Newtonsoft.Json; + +namespace Objects.Tests.Unit; + +/// +/// Tests that all Base object models in the kit have properties that are an allowed type +/// This test is not exhaustive, there are plenty of generic arg combinations that will pass this test, +/// but still not work / are not defined behaviour. This test will just catch many types that definitely won't work +/// +public class ModelPropertySupportedTypes +{ + /// + /// Set of types that we support in Base objects + /// If it's not in the list, or is commented out, it's not supported by our serializer! + /// + /// + /// If you're tempted to add to this list, please ensure both our serializer and deserializer support properties of this type + /// Check the + /// Check the + /// (or is an interface where all concrete types are supported) + /// You should also consider adding a test in SerializerNonBreakingChanges + /// + private readonly HashSet _allowedTypes = + new() + { + typeof(Boolean), + typeof(Byte), + typeof(UInt32), + typeof(UInt64), + typeof(Int16), + typeof(Int32), + typeof(Int64), + //typeof(Half), + typeof(Single), + typeof(Double), + typeof(Char), + typeof(string), + typeof(DateTime), + typeof(Guid), + typeof(Color), + typeof(List<>), + typeof(Nullable<>), + typeof(IList<>), + typeof(IReadOnlyList<>), + typeof(Dictionary<,>), + //typeof(IDictionary<,>), + //typeof(IReadOnlyDictionary<,>), + typeof(ICurve), + typeof(Object), + typeof(Matrix4x4), + }; + + [Test] + [TestCaseSource(typeof(GenericTests), nameof(GenericTests.AvailableTypesInKit))] + public void TestObjects(Type t) + { + var members = DynamicBase.GetInstanceMembers(t).Where(p => !p.IsDefined(typeof(JsonIgnoreAttribute), true)); + + foreach (var prop in members) + { + if (prop.PropertyType.IsAssignableTo(typeof(Base))) + continue; + if (prop.PropertyType.IsEnum) + continue; + if (prop.PropertyType.IsSZArray) + continue; + + Type propType = prop.PropertyType; + Type typeDef = propType.IsGenericType ? propType.GetGenericTypeDefinition() : propType; + Assert.That(_allowedTypes, Does.Contain(typeDef), $"{typeDef} was not in allowedTypes"); + } + } +}