Merge branch 'develop' into feature/CNX-651_Add_Properties_from_Properties_and_Classification_tab_to_send
# Conflicts: # SpeckleLib/Speckle/Database/Storage/ArchicadDBase/Element/ArchicadElementDBaseEngine.cpp # SpeckleLib/Speckle/Record/Element/Element.cpp # SpeckleLib/SpeckleLib17.vcxproj.filters
This commit is contained in:
+6
-1
@@ -13,6 +13,8 @@
|
||||
#include "Speckle/Record/Element/Column.h"
|
||||
#include "Speckle/Record/Element/ColumnSegment.h"
|
||||
#include "Speckle/Record/Element/ModelElement.h"
|
||||
#include "Speckle/Record/Element/Beam.h"
|
||||
#include "Speckle/Record/Element/BeamSegment.h"
|
||||
#include "Speckle/Record/Element/Memo.h"
|
||||
#include "Speckle/Utility/Guid.h"
|
||||
#include "Speckle/Utility/String.h"
|
||||
@@ -76,11 +78,14 @@ namespace {
|
||||
return std::make_unique<Column>(elementData, tableID);
|
||||
case API_ColumnSegmentID:
|
||||
return std::make_unique<ColumnSegment>(elementData, tableID);
|
||||
case API_BeamID:
|
||||
return std::make_unique<Beam>(elementData, tableID);
|
||||
case API_BeamSegmentID:
|
||||
return std::make_unique<BeamSegment>(elementData, tableID);
|
||||
default:
|
||||
return std::make_unique<ModelElement>(elementData, tableID);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
|
||||
@@ -30,6 +30,21 @@ namespace {
|
||||
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Append a single face to the Mesh given by the vertices
|
||||
--------------------------------------------------------------------*/
|
||||
void Mesh::appendFace(const std::vector<double>& vertices) {
|
||||
if (vertices.empty())
|
||||
return;
|
||||
|
||||
m_vertices.insert(m_vertices.end(), vertices.begin(), vertices.end());
|
||||
int lastVertexIndex = m_faces.empty() ? -1 : m_faces.back();
|
||||
int faceSize = vertices.size() / 3;
|
||||
m_faces.push_back(faceSize);
|
||||
for (int i = 0; i < faceSize; i++)
|
||||
m_faces.push_back(++lastVertexIndex);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Fill an inventory with the package items
|
||||
|
||||
|
||||
@@ -29,10 +29,19 @@ namespace speckle::primitive {
|
||||
Mesh(active::measure::LengthType unit = active::measure::LengthType::metre) : base{utility::Guid{true}, utility::Guid{}, unit} {}
|
||||
/*!
|
||||
Constructor
|
||||
@param unit The mesh unit type
|
||||
@param material The mesh material
|
||||
*/
|
||||
Mesh(const ModelerAPI::Material& material,
|
||||
active::measure::LengthType unit = active::measure::LengthType::metre) :
|
||||
base{ utility::Guid{true}, utility::Guid{}, unit }, m_material{ material } {}
|
||||
/*!
|
||||
Constructor
|
||||
@param unit The mesh unit type
|
||||
@param vertices The mesh vertices
|
||||
@param faces The mesh faces (the number of indices in the face followed by the vertex indices)
|
||||
@param colors The mesh face colours
|
||||
@param unit The mesh unit type
|
||||
@param material The mesh material
|
||||
*/
|
||||
Mesh(std::vector<double>&& vertices, std::vector<int>&& faces, std::vector<int>&& colors, const ModelerAPI::Material& material,
|
||||
active::measure::LengthType unit = active::measure::LengthType::metre) :
|
||||
@@ -45,6 +54,12 @@ namespace speckle::primitive {
|
||||
@return The speckle type (relevant objects should override as required)
|
||||
*/
|
||||
speckle::utility::String getSpeckleType() const override { return "Objects.Geometry.Mesh"; }
|
||||
|
||||
/*!
|
||||
Append a single face to the Mesh given by the vertices
|
||||
@param vertices The vertices to append
|
||||
*/
|
||||
void appendFace(const std::vector<double>& vertices);
|
||||
|
||||
// MARK: - Serialisation
|
||||
|
||||
|
||||
@@ -0,0 +1,174 @@
|
||||
#include "Speckle/Record/Element/Beam.h"
|
||||
|
||||
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
|
||||
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
|
||||
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
|
||||
#include "Speckle/Environment/Addon.h"
|
||||
#include "Speckle/Primitive/Mesh/Mesh.h"
|
||||
#include "Speckle/SpeckleResource.h"
|
||||
#include "Speckle/Utility/Guid.h"
|
||||
|
||||
using namespace active::serialise;
|
||||
using namespace speckle::environment;
|
||||
using namespace speckle::record::attribute;
|
||||
using namespace speckle::record::element;
|
||||
using namespace speckle::utility;
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
namespace speckle::record::element {
|
||||
|
||||
class Beam::Data {
|
||||
public:
|
||||
friend class Beam;
|
||||
|
||||
#ifdef ARCHICAD
|
||||
Data(const API_Element& elem) : root{ std::make_unique<API_BeamType>(elem.beam) } {}
|
||||
Data(const Data& source) : root{ std::make_unique<API_BeamType>(*source.root) } {}
|
||||
#endif
|
||||
|
||||
private:
|
||||
std::unique_ptr<API_BeamType> root;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
namespace {
|
||||
|
||||
///Serialisation fields
|
||||
enum FieldIndex {
|
||||
segmentID,
|
||||
};
|
||||
|
||||
///Serialisation field IDs
|
||||
static std::array fieldID = {
|
||||
Identity{"segments"},
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Default constructor
|
||||
--------------------------------------------------------------------*/
|
||||
Beam::Beam() {
|
||||
} //Beam::Beam
|
||||
|
||||
|
||||
#ifdef ARCHICAD
|
||||
/*--------------------------------------------------------------------
|
||||
Constructor
|
||||
|
||||
elemData: Archicad element data
|
||||
tableID: The element table ID (AC database, e.g. floor plan, 3D)
|
||||
--------------------------------------------------------------------*/
|
||||
Beam::Beam(const API_Element& elemData, const speckle::utility::Guid& tableID) : base{ elemData.header.guid, tableID } {
|
||||
m_data = std::make_unique<Data>(elemData);
|
||||
} //Beam::Beam
|
||||
#endif
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Copy constructor
|
||||
|
||||
source: The object to copy
|
||||
--------------------------------------------------------------------*/
|
||||
Beam::Beam(const Beam& source) : base{ source } {
|
||||
m_data = source.m_data ? std::make_unique<Data>(*m_data) : nullptr;
|
||||
} //Beam::Beam
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Destructor
|
||||
--------------------------------------------------------------------*/
|
||||
Beam::~Beam() {}
|
||||
|
||||
|
||||
#ifdef ARCHICAD
|
||||
/*--------------------------------------------------------------------
|
||||
Get the (immutable) API element header data
|
||||
|
||||
return: The element header data (only use this data for low-level operations - for normal code, call getters/setters)
|
||||
--------------------------------------------------------------------*/
|
||||
const API_Elem_Head& Beam::getHead() const {
|
||||
return m_data->root->head;
|
||||
} //Beam::getHead
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Get the (mutable) API element header data
|
||||
|
||||
return: The element header data (only use this data for low-level operations - for normal code, call getters/setters)
|
||||
--------------------------------------------------------------------*/
|
||||
API_Elem_Head& Beam::getHead() {
|
||||
return m_data->root->head;
|
||||
} //Beam::getHead
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Load the element memo structure (elements must override according to requirements)
|
||||
|
||||
filter: Filter bits specifying memo requirements
|
||||
--------------------------------------------------------------------*/
|
||||
void Beam::loadMemo(filter_bits filter, std::unique_ptr<Memo>& memo) const {
|
||||
//Establish the memo filter for this element
|
||||
if (!SegmentedBeam::isMemoLoaded())
|
||||
filter |= SegmentedBeam::getPartFilter();
|
||||
Element::loadMemo(filter, memo);
|
||||
//Receive the memo data into the element (when available)
|
||||
if (memo) {
|
||||
if (filter & SegmentedBeam::getPartFilter())
|
||||
SegmentedBeam::receive(*memo);
|
||||
}
|
||||
SegmentedBeam::setMemoLoaded(true); //Always mark the data as loaded to prevent repeated attempts on error
|
||||
} //Beam::loadMemo
|
||||
#endif
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Fill an inventory with the package items
|
||||
|
||||
inventory: The inventory to receive the package items
|
||||
|
||||
return: True if the package has added items to the inventory
|
||||
--------------------------------------------------------------------*/
|
||||
bool Beam::fillInventory(Inventory& inventory) const {
|
||||
using enum Entry::Type;
|
||||
inventory.merge(Inventory{
|
||||
{
|
||||
{ fieldID[segmentID], segmentID, getSegmentCount(), std::nullopt }, //TODO: implement other fields
|
||||
},
|
||||
}.withType(&typeid(Beam)));
|
||||
return base::fillInventory(inventory);
|
||||
} //Beam::fillInventory
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Get the specified cargo
|
||||
|
||||
item: The inventory item to retrieve
|
||||
|
||||
return: The requested cargo (nullptr on failure)
|
||||
--------------------------------------------------------------------*/
|
||||
Cargo::Unique Beam::getCargo(const Inventory::Item& item) const {
|
||||
if (item.ownerType != &typeid(Beam))
|
||||
return base::getCargo(item);
|
||||
using namespace active::serialise;
|
||||
switch (item.index) {
|
||||
case segmentID:
|
||||
if (auto segment = getSegment(item.available); segment != nullptr) {
|
||||
return Cargo::Unique{new PackageWrap{*segment}};
|
||||
} else
|
||||
return nullptr;
|
||||
default:
|
||||
return nullptr; //Requested an unknown index
|
||||
}
|
||||
} //Beam::getCargo
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Set to the default package content
|
||||
--------------------------------------------------------------------*/
|
||||
void Beam::setDefault() {
|
||||
base::setDefault();
|
||||
m_data.reset();
|
||||
} //Beam::setDefault
|
||||
@@ -0,0 +1,137 @@
|
||||
#ifndef SPECKLE_RECORD_ELEMENT_BEAM
|
||||
#define SPECKLE_RECORD_ELEMENT_BEAM
|
||||
|
||||
#include "Speckle/Record/Element/BeamSegment.h"
|
||||
#include "Speckle/Record/Element/Element.h"
|
||||
#include "Speckle/Record/Element/Interface/Assembly/Path.h"
|
||||
#include "Speckle/Record/Element/Interface/SegmentedBeam.h"
|
||||
|
||||
namespace speckle::record::element {
|
||||
|
||||
class BeamSegment;
|
||||
|
||||
/*!
|
||||
BIM beam class
|
||||
*/
|
||||
class Beam : public Element, public SegmentedBeam, public assembly::Path {
|
||||
public:
|
||||
|
||||
// MARK: - Types
|
||||
|
||||
using base = Element;
|
||||
///Unique pointer
|
||||
using Unique = std::unique_ptr<Beam>;
|
||||
///Shared pointer
|
||||
using Shared = std::shared_ptr<Beam>;
|
||||
///Optional
|
||||
using Option = std::optional<Beam>;
|
||||
|
||||
// MARK: - Constructors
|
||||
|
||||
using base::base;
|
||||
|
||||
/*!
|
||||
Default constructor
|
||||
*/
|
||||
Beam();
|
||||
#ifdef ARCHICAD
|
||||
/*!
|
||||
Constructor
|
||||
@param elemData Archicad element data
|
||||
@param tableID The beam element ID (AC database, e.g. floor plan, 3D)
|
||||
*/
|
||||
Beam(const API_Element& elemData, const speckle::utility::Guid& tableID);
|
||||
#endif
|
||||
/*!
|
||||
Copy constructor
|
||||
@param source The object to copy
|
||||
*/
|
||||
Beam(const Beam& source);
|
||||
/*!
|
||||
Destructor
|
||||
*/
|
||||
~Beam();
|
||||
|
||||
/*!
|
||||
Object cloning
|
||||
@return A clone of this object
|
||||
*/
|
||||
Beam* clonePtr() const override { return new Beam{*this}; }
|
||||
|
||||
|
||||
// MARK: - Functions (const)
|
||||
|
||||
/*!
|
||||
Get the BIM application parent table ID
|
||||
@return The BIM table ID
|
||||
*/
|
||||
virtual database::BIMRecordID getTableID() const override { return Element::getTableID(); }
|
||||
/*!
|
||||
Get the element body
|
||||
@return nullptr (Beams don't explicitly have a 3D body - this comes from its child segments)
|
||||
*/
|
||||
virtual Body* getBody() const override { return nullptr; }
|
||||
/*!
|
||||
Get the number of segments in the path (elements must override according to requirements)
|
||||
@return The segment count
|
||||
*/
|
||||
virtual size_t getSegmentCount() const override { return SegmentedBeam::getSegmentCount(); }
|
||||
/*!
|
||||
Get a segment from the path (elements must override according to requirements)
|
||||
@param index The index of the required segment
|
||||
@return The requested segment (nullptr on failure)
|
||||
*/
|
||||
virtual BeamSegment* getSegment(size_t index) const override { return SegmentedBeam::getSegment(index); }
|
||||
#ifdef ARCHICAD
|
||||
/*!
|
||||
Get the (immutable) API element header data
|
||||
@return The element header data (only use this data for low-level operations - for normal code, call getters/setters)
|
||||
*/
|
||||
const API_Elem_Head& getHead() const override;
|
||||
#endif
|
||||
|
||||
// MARK: - Functions (mutating)
|
||||
|
||||
#ifdef ARCHICAD
|
||||
/*!
|
||||
Get the (mutable) API element header data
|
||||
@return The element header data (only use this data for low-level operations - for normal code, call getters/setters)
|
||||
*/
|
||||
API_Elem_Head& getHead() override;
|
||||
#endif
|
||||
|
||||
// MARK: - Serialisation
|
||||
|
||||
/*!
|
||||
Fill an inventory with the package items
|
||||
@param inventory The inventory to receive the package items
|
||||
@return True if the package has added items to the inventory
|
||||
*/
|
||||
bool fillInventory(active::serialise::Inventory& inventory) const override;
|
||||
/*!
|
||||
Get the specified cargo
|
||||
@param item The inventory item to retrieve
|
||||
@return The requested cargo (nullptr on failure)
|
||||
*/
|
||||
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
|
||||
/*!
|
||||
Set to the default package content
|
||||
*/
|
||||
void setDefault() override;
|
||||
|
||||
protected:
|
||||
/*!
|
||||
Load the element memo structure (elements must override according to requirements)
|
||||
@param filter Filter bits specifying memo requirements
|
||||
*/
|
||||
virtual void loadMemo(filter_bits filter, std::unique_ptr<Memo>& memo) const override;
|
||||
|
||||
private:
|
||||
class Data;
|
||||
///The beam data
|
||||
std::unique_ptr<Data> m_data;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //SPECKLE_RECORD_ELEMENT_BEAM
|
||||
@@ -0,0 +1,159 @@
|
||||
#include "Speckle/Record/Element/BeamSegment.h"
|
||||
|
||||
#include "Active/Serialise/Item/Wrapper/ValueWrap.h"
|
||||
#include "Active/Serialise/Package/Wrapper/PackageWrap.h"
|
||||
#include "Active/Serialise/Package/Wrapper/ContainerWrap.h"
|
||||
#include "Speckle/Environment/Addon.h"
|
||||
#include "Speckle/Primitive/Mesh/Mesh.h"
|
||||
#include "Speckle/SpeckleResource.h"
|
||||
#include "Speckle/Utility/Guid.h"
|
||||
|
||||
#ifdef ARCHICAD
|
||||
#include <ACAPinc.h>
|
||||
#endif
|
||||
|
||||
using namespace active::serialise;
|
||||
using namespace speckle::environment;
|
||||
using namespace speckle::record::attribute;
|
||||
using namespace speckle::record::element;
|
||||
using namespace speckle::utility;
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
namespace speckle::record::element {
|
||||
|
||||
class BeamSegment::Data {
|
||||
public:
|
||||
friend class BeamSegment;
|
||||
|
||||
#ifdef ARCHICAD
|
||||
Data(const API_BeamSegmentType& seg) : root{ std::make_unique<API_BeamSegmentType>(seg) } {}
|
||||
Data(const Data& source) : root{ std::make_unique<API_BeamSegmentType>(*source.root) } {}
|
||||
|
||||
private:
|
||||
std::unique_ptr<API_BeamSegmentType> root;
|
||||
#endif
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Default constructor
|
||||
--------------------------------------------------------------------*/
|
||||
BeamSegment::BeamSegment() {
|
||||
} //BeamSegment::BeamSegment
|
||||
|
||||
|
||||
#ifdef ARCHICAD
|
||||
/*--------------------------------------------------------------------
|
||||
Constructor
|
||||
|
||||
elemData: Archicad element data
|
||||
tableID: The element table ID (AC database, e.g. floor plan, 3D)
|
||||
--------------------------------------------------------------------*/
|
||||
BeamSegment::BeamSegment(const API_Element& elemData, const speckle::utility::Guid& tableID) : base{ elemData.header.guid, tableID } {
|
||||
m_data = std::make_unique<Data>(elemData.beamSegment);
|
||||
} //BeamSegment::BeamSegment
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Constructor
|
||||
|
||||
segment: The segment element data
|
||||
tableID: The parent table ID
|
||||
cutOrigin: Cut at the segment origin
|
||||
cutEnd: Cut at the segment end
|
||||
scheme: The segment scheme
|
||||
profile: The segment profile (nullptr = none)
|
||||
--------------------------------------------------------------------*/
|
||||
BeamSegment::BeamSegment(const API_BeamSegmentType& segment, const speckle::utility::Guid& tableID, const API_AssemblySegmentCutData& cutOrigin,
|
||||
const API_AssemblySegmentCutData& cutEnd, const API_AssemblySegmentSchemeData& scheme,
|
||||
const API_AssemblySegmentProfileData* profile) :
|
||||
base{segment.head.guid, tableID}, assembly::Segment{cutOrigin, cutEnd, scheme, profile} {
|
||||
m_data = std::make_unique<Data>(segment);
|
||||
} //BeamSegment::BeamSegment
|
||||
#endif
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Copy constructor
|
||||
|
||||
source: The object to copy
|
||||
--------------------------------------------------------------------*/
|
||||
BeamSegment::BeamSegment(const BeamSegment& source) : base{ source } {
|
||||
m_data = source.m_data ? std::make_unique<Data>(*source.m_data) : nullptr;
|
||||
} //BeamSegment::BeamSegment
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Move constructor
|
||||
|
||||
source: The object to move
|
||||
--------------------------------------------------------------------*/
|
||||
BeamSegment::BeamSegment(BeamSegment&& source) noexcept : base{source} {
|
||||
m_data = std::move(source.m_data);
|
||||
} //BeamSegment::BeamSegment
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Destructor
|
||||
--------------------------------------------------------------------*/
|
||||
BeamSegment::~BeamSegment() {}
|
||||
|
||||
|
||||
#ifdef ARCHICAD
|
||||
/*--------------------------------------------------------------------
|
||||
Get the (immutable) API element header data
|
||||
|
||||
return: The element header data (only use this data for low-level operations - for normal code, call getters/setters)
|
||||
--------------------------------------------------------------------*/
|
||||
const API_Elem_Head& BeamSegment::getHead() const {
|
||||
return m_data->root->head;
|
||||
} //BeamSegment::getHead
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Get the (mutable) API element header data
|
||||
|
||||
return: The element header data (only use this data for low-level operations - for normal code, call getters/setters)
|
||||
--------------------------------------------------------------------*/
|
||||
API_Elem_Head& BeamSegment::getHead() {
|
||||
return m_data->root->head;
|
||||
} //BeamSegment::getHead
|
||||
#endif
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Fill an inventory with the package items
|
||||
|
||||
inventory: The inventory to receive the package items
|
||||
|
||||
return: True if the package has added items to the inventory
|
||||
--------------------------------------------------------------------*/
|
||||
bool BeamSegment::fillInventory(Inventory& inventory) const {
|
||||
using enum Entry::Type;
|
||||
//TODO: Implement other fields as required
|
||||
return base::fillInventory(inventory);
|
||||
} //BeamSegment::fillInventory
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Get the specified cargo
|
||||
|
||||
item: The inventory item to retrieve
|
||||
|
||||
return: The requested cargo (nullptr on failure)
|
||||
--------------------------------------------------------------------*/
|
||||
Cargo::Unique BeamSegment::getCargo(const Inventory::Item& item) const {
|
||||
//TODO: Implement other fields as required
|
||||
return base::getCargo(item);
|
||||
} //BeamSegment::getCargo
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Set to the default package content
|
||||
--------------------------------------------------------------------*/
|
||||
void BeamSegment::setDefault() {
|
||||
m_data.reset();
|
||||
} //BeamSegment::setDefault
|
||||
@@ -0,0 +1,130 @@
|
||||
#ifndef SPECKLE_RECORD_ELEMENT_BEAM_SEGMENT
|
||||
#define SPECKLE_RECORD_ELEMENT_BEAM_SEGMENT
|
||||
|
||||
#include "Speckle/Record/Element/Element.h"
|
||||
#include "Speckle/Record/Element/Interface/Assembly/Segment.h"
|
||||
|
||||
namespace speckle::record::element {
|
||||
|
||||
class SegmentedBeam;
|
||||
|
||||
/*!
|
||||
BIM beam class
|
||||
*/
|
||||
class BeamSegment : public Element, public assembly::Segment {
|
||||
public:
|
||||
|
||||
// MARK: - Types
|
||||
|
||||
using base = Element;
|
||||
///Unique pointer
|
||||
using Unique = std::unique_ptr<BeamSegment>;
|
||||
///Shared pointer
|
||||
using Shared = std::shared_ptr<BeamSegment>;
|
||||
///Optional
|
||||
using Option = std::optional<BeamSegment>;
|
||||
|
||||
// MARK: - Constructors
|
||||
|
||||
using base::base;
|
||||
|
||||
/*!
|
||||
Default constructor
|
||||
*/
|
||||
BeamSegment();
|
||||
#ifdef ARCHICAD
|
||||
/*!
|
||||
Constructor
|
||||
@param elemData Archicad element data
|
||||
@param tableID The element table ID (AC database, e.g. floor plan, 3D)
|
||||
*/
|
||||
BeamSegment(const API_Element& elemData, const speckle::utility::Guid& tableID);
|
||||
#endif
|
||||
/*!
|
||||
Copy constructor
|
||||
@param source The object to copy
|
||||
*/
|
||||
BeamSegment(const BeamSegment& source);
|
||||
/*!
|
||||
Move constructor
|
||||
@param source The object to move
|
||||
*/
|
||||
BeamSegment(BeamSegment&& source) noexcept;
|
||||
/*!
|
||||
Destructor
|
||||
*/
|
||||
~BeamSegment();
|
||||
|
||||
/*!
|
||||
Object cloning
|
||||
@return A clone of this object
|
||||
*/
|
||||
BeamSegment* clonePtr() const override { return new BeamSegment{*this}; }
|
||||
|
||||
|
||||
// MARK: - Functions (const)
|
||||
|
||||
#ifdef ARCHICAD
|
||||
/*!
|
||||
Get the (immutable) API element header data
|
||||
@return The element header data (only use this data for low-level operations - for normal code, call getters/setters)
|
||||
*/
|
||||
const API_Elem_Head& getHead() const override;
|
||||
#endif
|
||||
|
||||
// MARK: - Functions (mutating)
|
||||
|
||||
#ifdef ARCHICAD
|
||||
/*!
|
||||
Get the (mutable) API element header data
|
||||
@return The element header data (only use this data for low-level operations - for normal code, call getters/setters)
|
||||
*/
|
||||
API_Elem_Head& getHead() override;
|
||||
#endif
|
||||
|
||||
// MARK: - Serialisation
|
||||
|
||||
/*!
|
||||
Fill an inventory with the package items
|
||||
@param inventory The inventory to receive the package items
|
||||
@return True if the package has added items to the inventory
|
||||
*/
|
||||
bool fillInventory(active::serialise::Inventory& inventory) const override;
|
||||
/*!
|
||||
Get the specified cargo
|
||||
@param item The inventory item to retrieve
|
||||
@return The requested cargo (nullptr on failure)
|
||||
*/
|
||||
Cargo::Unique getCargo(const active::serialise::Inventory::Item& item) const override;
|
||||
/*!
|
||||
Set to the default package content
|
||||
*/
|
||||
void setDefault() override;
|
||||
|
||||
protected:
|
||||
friend class SegmentedBeam;
|
||||
|
||||
#ifdef ARCHICAD
|
||||
/*!
|
||||
Constructor
|
||||
@param segment The segment element data
|
||||
@param tableID The parent table ID
|
||||
@param cutOrigin Cut at the segment origin
|
||||
@param cutEnd Cut at the segment end
|
||||
@param scheme The segment scheme
|
||||
@param profile The segment profile (nullptr = none)
|
||||
*/
|
||||
BeamSegment(const API_BeamSegmentType& segment, const speckle::utility::Guid& tableID, const API_AssemblySegmentCutData& cutOrigin,
|
||||
const API_AssemblySegmentCutData& cutEnd, const API_AssemblySegmentSchemeData& scheme,
|
||||
const API_AssemblySegmentProfileData* profile = nullptr);
|
||||
#endif
|
||||
|
||||
private:
|
||||
class Data;
|
||||
///The beam data
|
||||
std::unique_ptr<Data> m_data;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //SPECKLE_RECORD_ELEMENT_BEAM_SEGMENT
|
||||
@@ -109,7 +109,7 @@ bool Element::fillInventory(Inventory& inventory) const {
|
||||
return: The requested cargo (nullptr on failure)
|
||||
--------------------------------------------------------------------*/
|
||||
Cargo::Unique Element::getCargo(const Inventory::Item& item) const {
|
||||
return base::getCargo(item);
|
||||
return base::getCargo(item);
|
||||
} //Element::getCargo
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,160 @@
|
||||
#include "Speckle/Record/Element/Interface/SegmentedBeam.h"
|
||||
|
||||
#include "Speckle/Record/Element/BeamSegment.h"
|
||||
#include "Speckle/Record/Element/Memo.h"
|
||||
#include "Speckle/Record/Element/Interface/Assembly/Path.h"
|
||||
#include "Speckle/Utility/BIMMemory.h"
|
||||
|
||||
using namespace active::serialise;
|
||||
using namespace speckle::record::attribute;
|
||||
using namespace speckle::record::element;
|
||||
using namespace speckle::utility;
|
||||
|
||||
namespace speckle::record::element {
|
||||
|
||||
class SegmentedBeam::Data {
|
||||
public:
|
||||
friend class SegmentedBeam;
|
||||
|
||||
std::vector<BeamSegment> segments;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Default constructor
|
||||
--------------------------------------------------------------------*/
|
||||
SegmentedBeam::SegmentedBeam() {
|
||||
} //SegmentedBeam::SegmentedBeam
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Copy constructor
|
||||
|
||||
source: The object to copy
|
||||
--------------------------------------------------------------------*/
|
||||
SegmentedBeam::SegmentedBeam(const SegmentedBeam& source) : base{ source } {
|
||||
m_data = source.m_data ? std::make_unique<Data>(*m_data) : nullptr;
|
||||
} //SegmentedBeam::SegmentedBeam
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Destructor
|
||||
--------------------------------------------------------------------*/
|
||||
SegmentedBeam::~SegmentedBeam() {}
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Get the number of segments
|
||||
|
||||
return. The number of segments (0 on error)
|
||||
--------------------------------------------------------------------*/
|
||||
size_t SegmentedBeam::getSegmentCount() const {
|
||||
confirmPart(getPartFilter());
|
||||
return m_data ? m_data->segments.size() : 0;
|
||||
} //SegmentedBeam::getSegmentCount
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Get a beam segment
|
||||
|
||||
index: The index of the required segment
|
||||
|
||||
return: The requested segment, nullptr on error
|
||||
--------------------------------------------------------------------*/
|
||||
BeamSegment* SegmentedBeam::getSegment(size_t index) const {
|
||||
confirmPart(getPartFilter());
|
||||
return (m_data && (index < m_data->segments.size())) ? &m_data->segments[index] : nullptr;
|
||||
} //SegmentedBeam::getSegment
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Return the bits for the part filter required to load the data necessary to build this object
|
||||
|
||||
return: The required filter bits
|
||||
--------------------------------------------------------------------*/
|
||||
Part::filter_bits SegmentedBeam::getPartFilter() const {
|
||||
#ifdef ARCHICAD
|
||||
return APIMemoMask_BeamSegment | APIMemoMask_AssemblySegmentCut | APIMemoMask_AssemblySegmentScheme | APIMemoMask_AssemblySegmentProfile;
|
||||
#endif
|
||||
} //SegmentedBeam::getPartFilter
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Determine if the element memo content has been validated (elements must override according to requirements)
|
||||
|
||||
return: True if the element memo content is valid
|
||||
--------------------------------------------------------------------*/
|
||||
bool SegmentedBeam::isPartValid() const {
|
||||
return m_data && !m_data->segments.empty();
|
||||
} //SegmentedBeam::isPartValid
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Load the element memo structure (elements must override according to requirements)
|
||||
|
||||
filter: Filter bits specifying memo requirements
|
||||
--------------------------------------------------------------------*/
|
||||
void SegmentedBeam::loadMemo(filter_bits filter, std::unique_ptr<Memo>& memo) const {
|
||||
|
||||
} //SegmentedBeam::loadMemo
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Send the element part back to a memo structure for storage (elements must override according to requirements)
|
||||
|
||||
memo: The memo to carry the data
|
||||
|
||||
return: True if the data was successfully sent
|
||||
--------------------------------------------------------------------*/
|
||||
bool SegmentedBeam::send(Memo* memo) const {
|
||||
//TODO: Complete when required
|
||||
return false;
|
||||
} //SegmentedBeam::send
|
||||
|
||||
|
||||
/*--------------------------------------------------------------------
|
||||
Receive the element memo data from a memo structure (elements must override according to requirements)
|
||||
|
||||
memo: The memo carrying the data
|
||||
|
||||
return: True if the data was successfully received
|
||||
--------------------------------------------------------------------*/
|
||||
bool SegmentedBeam::receive(const Memo& memo) const {
|
||||
#ifdef ARCHICAD
|
||||
if (!memo || (memo.root()->beamSegments == nullptr))
|
||||
return false;
|
||||
if (m_data)
|
||||
m_data->segments.clear();
|
||||
else
|
||||
m_data = std::make_unique<Data>();
|
||||
//Confirm that required data is present in the memo
|
||||
auto segmentPtr = memo.root()->beamSegments;
|
||||
auto cutPtr = memo.root()->assemblySegmentCuts;
|
||||
auto schemePtr = memo.root()->assemblySegmentSchemes;
|
||||
auto profilePtr = memo.root()->assemblySegmentProfiles;
|
||||
if ((segmentPtr == nullptr) || (cutPtr == nullptr) || (schemePtr == nullptr))
|
||||
return false;
|
||||
//Determine available item count
|
||||
auto segmentCount = BIMMemory::getPtrSize(segmentPtr) / sizeof(API_BeamSegmentType);
|
||||
auto cutCount = BIMMemory::getPtrSize(cutPtr) / sizeof(API_AssemblySegmentCutData);
|
||||
auto schemeCount = BIMMemory::getPtrSize(schemePtr) / sizeof(API_AssemblySegmentSchemeData);
|
||||
auto profileCount = BIMMemory::getPtrSize(profilePtr) / sizeof(API_AssemblySegmentProfileData);
|
||||
if ((segmentCount == 0) || (cutCount != (segmentCount + 1)) || (schemeCount != segmentCount))
|
||||
return false;
|
||||
auto path = dynamic_cast<const assembly::Path*>(this);
|
||||
for (size_t n = 0 ; n < segmentCount; ++n) {
|
||||
const API_AssemblySegmentProfileData* thisProfile = nullptr;
|
||||
for (size_t i = 0; i < profileCount; ++i) {
|
||||
if (profilePtr[i].segmentIndex == n) {
|
||||
thisProfile = profilePtr + i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
m_data->segments.emplace_back(BeamSegment{segmentPtr[n], getTableID(), cutPtr[n], cutPtr[n + 1], schemePtr[n], thisProfile});
|
||||
m_data->segments.back().setPath(path);
|
||||
}
|
||||
setMemoLoaded(true);
|
||||
#endif
|
||||
return true;
|
||||
} //SegmentedBeam::receive
|
||||
@@ -0,0 +1,103 @@
|
||||
#ifndef SPECKLE_RECORD_ELEMENT_SEGMENTED_BEAM
|
||||
#define SPECKLE_RECORD_ELEMENT_SEGMENTED_BEAM
|
||||
|
||||
#include "Speckle/Database/Identity/BIMRecordID.h"
|
||||
#include "Speckle/Record/Element/Interface/Part.h"
|
||||
|
||||
namespace speckle::record::element {
|
||||
|
||||
class BeamSegment;
|
||||
|
||||
/*!
|
||||
Interface for a beam type that is made up of consecutive segments
|
||||
|
||||
Note that the child segments use lazy loading to avoid high overheads when accessing data relevant to the parent beam only
|
||||
*/
|
||||
class SegmentedBeam : public Part {
|
||||
public:
|
||||
|
||||
// MARK: - Types
|
||||
|
||||
using base = Part;
|
||||
///Unique pointer
|
||||
using Unique = std::unique_ptr<SegmentedBeam>;
|
||||
///Shared pointer
|
||||
using Shared = std::shared_ptr<SegmentedBeam>;
|
||||
///Optional
|
||||
using Option = std::optional<SegmentedBeam>;
|
||||
|
||||
// MARK: - Constructors
|
||||
|
||||
/*!
|
||||
Default constructor
|
||||
*/
|
||||
SegmentedBeam();
|
||||
/*!
|
||||
Copy constructor
|
||||
@param source The object to copy
|
||||
*/
|
||||
SegmentedBeam(const SegmentedBeam& source);
|
||||
/*!
|
||||
Destructor
|
||||
*/
|
||||
~SegmentedBeam();
|
||||
|
||||
// MARK: - Functions (const)
|
||||
|
||||
/*!
|
||||
Get the BIM application parent table ID
|
||||
@return The BIM table ID
|
||||
*/
|
||||
virtual database::BIMRecordID getTableID() const = 0;
|
||||
/*!
|
||||
Get the number of segments
|
||||
@return The number of segments (0 on error)
|
||||
*/
|
||||
size_t getSegmentCount() const;
|
||||
/*!
|
||||
Get a beam segment
|
||||
@param index The index of the required segment
|
||||
@return The requested segment, nullptr on error
|
||||
*/
|
||||
BeamSegment* getSegment(size_t index) const;
|
||||
|
||||
// MARK: - Functions (mutating)
|
||||
|
||||
protected:
|
||||
/*!
|
||||
Return the bits for the part filter required to load the data necessary to build this object
|
||||
@return The required filter bits */
|
||||
filter_bits getPartFilter() const;
|
||||
/*!
|
||||
Determine if the element part content has been validated (elements must override according to requirements)
|
||||
@return True if the element part content is valid
|
||||
*/
|
||||
bool isPartValid() const override;
|
||||
/*!
|
||||
Load the element memo structure (elements must override according to requirements)
|
||||
@param filter Filter bits specifying memo requirements
|
||||
*/
|
||||
void loadMemo(filter_bits filter, std::unique_ptr<Memo>& memo) const override;
|
||||
|
||||
/*!
|
||||
Send the element part back to a memo structure for storage (elements must override according to requirements)
|
||||
@param memo The memo to carry the data
|
||||
@return True if the data was successfully sent
|
||||
*/
|
||||
bool send(Memo* memo) const override;
|
||||
/*!
|
||||
Receive the element memo data from a memo structure (elements must override according to requirements)
|
||||
@param memo The memo carrying the data
|
||||
@return True if the data was successfully received
|
||||
*/
|
||||
bool receive(const Memo& memo) const override;
|
||||
|
||||
private:
|
||||
class Data;
|
||||
///The segment data - mutable to support lazy loading
|
||||
mutable std::unique_ptr<Data> m_data;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
#endif //SPECKLE_RECORD_ELEMENT_SEGMENTED_BEAM
|
||||
@@ -129,7 +129,6 @@ ModelElement::Body* ModelElement::getBody() const {
|
||||
return m_data->m_cache.get();
|
||||
}
|
||||
|
||||
|
||||
void* dummy = nullptr;
|
||||
GSErrCode err = ACAPI_Sight_GetCurrentWindowSight(&dummy);
|
||||
if (err != NoError)
|
||||
@@ -149,6 +148,9 @@ ModelElement::Body* ModelElement::getBody() const {
|
||||
|
||||
auto elementBody = new ModelElement::Body();
|
||||
|
||||
// Map to collect meshes per material name
|
||||
std::map<GS::UniString, primitive::Mesh> materialMeshMap;
|
||||
|
||||
Int32 nElements = acModel.GetElementCount();
|
||||
for (Int32 iElement = 1; iElement <= nElements; iElement++)
|
||||
{
|
||||
@@ -166,49 +168,51 @@ ModelElement::Body* ModelElement::getBody() const {
|
||||
Int32 polyCount = body.GetPolygonCount();
|
||||
for (Int32 polyIndex = 1; polyIndex <= polyCount; ++polyIndex)
|
||||
{
|
||||
ModelerAPI::Polygon polygon{};
|
||||
ModelerAPI::Polygon polygon{};
|
||||
body.GetPolygon(polyIndex, &polygon);
|
||||
|
||||
ModelerAPI::Material material{};
|
||||
polygon.GetMaterial(&material);
|
||||
auto materialName = material.GetName();
|
||||
if (materialMeshMap.find(materialName) == materialMeshMap.end()) {
|
||||
materialMeshMap[materialName] = primitive::Mesh(material);
|
||||
}
|
||||
|
||||
Int32 convexPolyCount = polygon.GetConvexPolygonCount();
|
||||
|
||||
for (Int32 convPolyIndex = 1; convPolyIndex <= convexPolyCount; ++convPolyIndex)
|
||||
{
|
||||
std::vector<double> vertices;
|
||||
std::vector<int> faces;
|
||||
std::vector<int> colors;
|
||||
|
||||
ModelerAPI::ConvexPolygon convexPolygon{};
|
||||
polygon.GetConvexPolygon(convPolyIndex, &convexPolygon);
|
||||
Int32 vertexCount = convexPolygon.GetVertexCount();
|
||||
|
||||
faces.push_back(vertexCount);
|
||||
for (Int32 vertexIndex = 1; vertexIndex <= vertexCount; ++vertexIndex)
|
||||
{
|
||||
ModelerAPI::Vertex vertex{};
|
||||
body.GetVertex(convexPolygon.GetVertexIndex(vertexIndex), &vertex);
|
||||
|
||||
// TODO: change vertices array to hold Vertex instead of double values
|
||||
// Collect vertices (as doubles for now, but should be changed to Vertex type)
|
||||
vertices.push_back(vertex.x);
|
||||
vertices.push_back(vertex.y);
|
||||
vertices.push_back(vertex.z);
|
||||
|
||||
//double alpha = material.GetTransparency();
|
||||
//ModelerAPI::Color color = material.GetSurfaceColor();
|
||||
//colors.push_back(ARGBToInt(alpha, color.red, color.green, color.blue));
|
||||
|
||||
faces.push_back(vertexIndex - 1);
|
||||
}
|
||||
elementBody->push_back(primitive::Mesh(std::move(vertices), std::move(faces), std::move(colors), material));
|
||||
|
||||
materialMeshMap[materialName].appendFace(std::move(vertices));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto& [materialName, mesh] : materialMeshMap)
|
||||
{
|
||||
elementBody->push_back(std::move(mesh));
|
||||
}
|
||||
|
||||
m_data->m_cache.reset(elementBody);
|
||||
return m_data->m_cache.get();
|
||||
#endif
|
||||
}
|
||||
} //ModelElement::getBody
|
||||
|
||||
|
||||
#ifdef ARCHICAD
|
||||
|
||||
@@ -76,6 +76,8 @@
|
||||
<ClInclude Include="Speckle\Record\Credentials\ServerInfo.h" />
|
||||
<ClInclude Include="Speckle\Record\Credentials\ServerMigration.h" />
|
||||
<ClInclude Include="Speckle\Record\Credentials\UserInfo.h" />
|
||||
<ClInclude Include="Speckle\Record\Element\Beam.h" />
|
||||
<ClInclude Include="Speckle\Record\Element\BeamSegment.h" />
|
||||
<ClInclude Include="Speckle\Record\Element\Column.h" />
|
||||
<ClInclude Include="Speckle\Record\Element\ColumnSegment.h" />
|
||||
<ClInclude Include="Speckle\Record\Element\DrawingElement.h" />
|
||||
@@ -85,6 +87,7 @@
|
||||
<ClInclude Include="Speckle\Record\Element\Interface\Assembly\Path.h" />
|
||||
<ClInclude Include="Speckle\Record\Element\Interface\Assembly\Segment.h" />
|
||||
<ClInclude Include="Speckle\Record\Element\Interface\Part.h" />
|
||||
<ClInclude Include="Speckle\Record\Element\Interface\SegmentedBeam.h" />
|
||||
<ClInclude Include="Speckle\Record\Element\Interface\SegmentedColumn.h" />
|
||||
<ClInclude Include="Speckle\Record\Element\Memo.h" />
|
||||
<ClInclude Include="Speckle\Record\Element\ModelElement.h" />
|
||||
@@ -155,6 +158,8 @@
|
||||
<ClCompile Include="Speckle\Record\Credentials\ServerInfo.cpp" />
|
||||
<ClCompile Include="Speckle\Record\Credentials\ServerMigration.cpp" />
|
||||
<ClCompile Include="Speckle\Record\Credentials\UserInfo.cpp" />
|
||||
<ClCompile Include="Speckle\Record\Element\Beam.cpp" />
|
||||
<ClCompile Include="Speckle\Record\Element\BeamSegment.cpp" />
|
||||
<ClCompile Include="Speckle\Record\Element\Column.cpp" />
|
||||
<ClCompile Include="Speckle\Record\Element\ColumnSegment.cpp" />
|
||||
<ClCompile Include="Speckle\Record\Element\DrawingElement.cpp" />
|
||||
@@ -164,6 +169,7 @@
|
||||
<ClCompile Include="Speckle\Record\Element\Interface\Assembly\Path.cpp" />
|
||||
<ClCompile Include="Speckle\Record\Element\Interface\Assembly\Segment.cpp" />
|
||||
<ClCompile Include="Speckle\Record\Element\Interface\Part.cpp" />
|
||||
<ClCompile Include="Speckle\Record\Element\Interface\SegmentedBeam.cpp" />
|
||||
<ClCompile Include="Speckle\Record\Element\Interface\SegmentedColumn.cpp" />
|
||||
<ClCompile Include="Speckle\Record\Element\Memo.cpp" />
|
||||
<ClCompile Include="Speckle\Record\Element\ModelElement.cpp" />
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Resource Files">
|
||||
@@ -406,6 +406,15 @@
|
||||
<ClInclude Include="Speckle\Record\Property\Group.h">
|
||||
<Filter>Speckle\Record\Property</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Speckle\Record\Element\Interface\SegmentedBeam.h">
|
||||
<Filter>Speckle\Record\Element\Interface</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Speckle\Record\Element\Beam.h">
|
||||
<Filter>Speckle\Record\Element</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Speckle\Record\Element\BeamSegment.h">
|
||||
<Filter>Speckle\Record\Element</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="Speckle\Environment\Addon.cpp">
|
||||
@@ -612,6 +621,15 @@
|
||||
<ClCompile Include="Speckle\Record\Property\Group.cpp">
|
||||
<Filter>Speckle\Record\Property</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Speckle\Record\Element\Interface\SegmentedBeam.cpp">
|
||||
<Filter>Speckle\Record\Element\Interface</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Speckle\Record\Element\Beam.cpp">
|
||||
<Filter>Speckle\Record\Element</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Speckle\Record\Element\BeamSegment.cpp">
|
||||
<Filter>Speckle\Record\Element</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Text Include="Speckle\CMakeLists.txt">
|
||||
|
||||
Reference in New Issue
Block a user