/
spivag
/
command_occ
Обзор
Документация
Войти
/
spivag
/
command_occ
Код
Запросы
1
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
initial
commands/part_structure.cpp
699 строк
22 KB
spivag
Запрос на слияние 'c3d_sdk_removal' (
#2
) из c3d_sdk_removal в initial
16 апр 2026, 15:34
Верифицирован
16 апр 2026, 15:34
e04e876
Код
Авторство
О чём код?
// // Created by Alexander Spivakov on 01.07.2025. // #include "part_structure.h" #include <shape_iterator.h> #include <shape_command.h> #include <optional> #include <unordered_map> #include <cmath> // Simple OCConstraint implementation for OpenCASCADE class OCConstraint { public: OCConstraint() = default; virtual ~OCConstraint() = default; }; // Alignment enum for OpenCASCADE (replacing GCM_alignment) enum class OCAlignment { CLOSEST, COORIENTED, OPPOSITE }; // Minimal InstanceConstraintManager for OpenCASCADE class InstanceConstraintManager { public: template<typename T> T RegisterPartReferenceForPlacemetUpdate(T partRef) { // Placeholder implementation return partRef; } bool SetLocationFixed(void* partRef) { // Placeholder implementation return true; } template<typename T1, typename T2> void* RegisterGeometryForPlcaementCalculation(T1 geom1, T2 geom2) { // Placeholder implementation return nullptr; } std::shared_ptr<OCConstraint> AddCoaxialConstraint(void* geom1, void* geom2) { return std::make_shared<OCConstraint>(); } std::shared_ptr<OCConstraint> AddCoincidentConstraint(void* geom1, void* geom2, OCAlignment alignment) { return std::make_shared<OCConstraint>(); } std::shared_ptr<OCConstraint> AddTangentConstraint(void* geom1, void* geom2) { return std::make_shared<OCConstraint>(); } std::shared_ptr<OCConstraint> AddParpendicularConstraint(void* geom1, void* geom2) { return std::make_shared<OCConstraint>(); } bool ResolveConstraintsSystem() { // Placeholder implementation return true; } }; std::weak_ptr< PartInstance > Document::GetRootPart() const { return m_rootPart; } bool Document::SetRootPart( std::shared_ptr< PartInstance > const& part ) { const bool partPresent = std::find( cbegin( m_partInstances ), cend( m_partInstances ), part ) != cend( m_partInstances ); if ( partPresent ) m_rootPart = part; return partPresent; } std::weak_ptr< PartInstance > Document::AddPart( std::string const& humanReadableName ) { m_partInstances.emplace_back( std::make_shared< PartInstance >( humanReadableName ) ); return std::weak_ptr< PartInstance >( m_partInstances.back() ); } std::weak_ptr< PartInstance > Document::AddPart( std::string const& humanReadableName, std::vector< std::shared_ptr< IShapeBuilder > > const& shapes ) { auto newPart = std::make_shared< PartInstance >( humanReadableName ); for ( const auto& shape : shapes ) { if ( shape == nullptr ) continue; newPart->AddShape( shape ); AddShape( shape ); } m_partInstances.emplace_back( newPart ); return std::weak_ptr< PartInstance >( m_partInstances.back() ); } void Document::AddShape( std::shared_ptr< IShapeBuilder > const& shape ) { m_shapes.insert( shape ); } // void Document::StoreShapes( std::ostream & os ) const // { // json_impl storeFormatter; // ShapeSerializeProvider shapeSerializer( storeFormatter ); // for ( auto const& shapeToStore : m_shapes ) // shapeToStore->Accept( shapeSerializer ); // json_impl shapesOfDocument; // shapesOfDocument["document_shapes"] = storeFormatter; // os << shapesOfDocument.dump( 4 ) << std::endl; // } // // bool Document::RestoreShapes( std::istream & is ) // { // json_impl json_source = json_impl::parse( is ); // if ( !json_source.contains( "document_shapes" ) ) // { // return false; // } // auto jShapes = json_source["document_shapes"]; // if ( !jShapes.is_array() ) // { // return false; // } // // std::vector< std::shared_ptr< IShapeBuilder > > shapeBuilders = MakeShapes( jShapes ); // // return true; // } class MbSpaceItem; class PartShapesIteratorImpl : public IPartShapesIterator { public: PartShapesIteratorImpl( std::vector< std::pair< std::weak_ptr< IShapeBuilder >, bool > >::iterator const& begItr, std::vector< std::pair< std::weak_ptr< IShapeBuilder >, bool > >::iterator const& endItr, bool onlyActive ) : m_curItr{ begItr } , m_endItr{ endItr } , m_emitOnlyEnabled{ onlyActive } { } bool HasNext() const override { return m_curItr != m_endItr; } void Next() override { ++m_curItr; if ( m_emitOnlyEnabled ) { while ( ( m_curItr != m_endItr ) && !m_curItr->second ) { ++m_curItr; } } } std::weak_ptr< IShapeBuilder > Shape() override { return HasNext() ? m_curItr->first : std::weak_ptr< IShapeBuilder >{}; } private: std::vector< std::pair< std::weak_ptr< IShapeBuilder >, bool > >::iterator m_curItr; std::vector< std::pair< std::weak_ptr< IShapeBuilder >, bool > >::iterator m_endItr; bool m_emitOnlyEnabled{}; }; class PartInstancesIteratorImpl : public IPartInstancesIterator { public: PartInstancesIteratorImpl( std::vector< std::shared_ptr< PartInstanceReference > >::iterator const& begItr, std::vector< std::shared_ptr< PartInstanceReference > >::iterator const& endItr ) : m_curItr{ begItr } , m_endItr{ endItr } { } bool HasNext() const override { return m_curItr != m_endItr; } void Next() override { ++m_curItr; } std::weak_ptr< PartInstanceReference > PartReference() override { return HasNext() ? std::weak_ptr< PartInstanceReference >{ *m_curItr } : std::weak_ptr< PartInstanceReference >{}; } private: std::vector< std::shared_ptr< PartInstanceReference > >::iterator m_curItr; std::vector< std::shared_ptr< PartInstanceReference > >::iterator m_endItr; }; // --- Реализация итератора по зарегистрированным ограничениям ------------------------------------ class ConstraintIteratorImpl : public IConstraintIterator { public: using ContainerIt = std::vector< PartInstance::ConstraintVariant >::const_iterator; ConstraintIteratorImpl( ContainerIt const& beg, ContainerIt const& end ) : m_cur{ beg } , m_end{ end } { } bool HasNext() const override { return m_cur != m_end; } void Next() override { if ( m_cur != m_end ) ++m_cur; } std::variant< CoaxialConstraint, CoincidenceConstraint, TangentConstraint, PerpendicularConstraint > Constraint() const override { if ( m_cur == m_end ) throw std::range_error{ "No constraints" }; return *m_cur; } private: ContainerIt m_cur; ContainerIt m_end; }; PartInstance::PartInstance( std::string const& name ) : m_name{ name } { } void PartInstance::Accept( PartStructureVisitor& visitor ) const { visitor.Visit( *this ); } [[nodiscard]] std::shared_ptr< PartInstance > PartInstance::MakeDeepClone() const { std::shared_ptr< PartInstance > newborn = std::make_shared< PartInstance >( this->m_name ); newborn->m_geometry = this->m_geometry; for ( const auto& curRef : this->m_instances ) { if ( curRef == nullptr ) continue; auto subIntance = curRef->ReferencedInstance().lock(); if ( subIntance == nullptr ) continue; auto subInstanceReplica = subIntance->MakeDeepClone(); newborn->m_instances.push_back( std::make_shared< PartInstanceReference >( subInstanceReplica, curRef->Location(), curRef->Name() ) ); } return newborn; } void PartInstance::AddShape( std::shared_ptr< IShapeBuilder > const& shape ) { try { GetGeometry()->AddShape( shape ); } catch ( std::exception& ) { } } void PartInstance::RemoveShape( std::shared_ptr< IShapeBuilder > const& shape ) { if ( !m_instances.empty() ) return; GetGeometry()->RemoveShape( shape ); } void PartInstance::EnableShape( std::shared_ptr< IShapeBuilder > const& shape ) { try { GetGeometry()->EnableShape( shape ); } catch ( std::exception& ) { } } void PartInstance::DisableShape( std::shared_ptr< IShapeBuilder > const& shape ) { try { GetGeometry()->DisableShape( shape ); } catch ( std::exception& ) { } } bool PartInstance::IsShapeEnabled( std::shared_ptr< IShapeBuilder > const& shape ) const { if ( ( !m_instances.empty() ) || ( m_geometry == nullptr ) ) throw std::range_error{ "No shapes" }; return m_geometry->IsShapeEnabled( shape ); } std::shared_ptr< IPartShapesIterator > PartInstance::GetShapesIterator() { try { return GetGeometry()->GetShapesIterator(); } catch ( std::exception& ) { throw std::range_error{ "No shapes" }; } } std::shared_ptr< IPartShapesIterator > PartInstance::GetEnabledShapesIterator() { try { return GetGeometry()->GetEnabledShapesIterator(); } catch ( std::exception& ) { throw std::range_error{ "No shapes" }; } } std::shared_ptr< PartGeometry > PartInstance::GetGeometry() { if ( !m_instances.empty() ) throw std::range_error{ "No shapes" }; if ( m_geometry == nullptr ) m_geometry = std::make_shared< PartGeometry >(); return m_geometry; } void PartGeometry::AddShape( std::shared_ptr< IShapeBuilder > const& shape ) { if ( shape == nullptr ) return; auto existingItr = std::find_if( cbegin( m_shapes ), cend( m_shapes ), [&shape]( const auto& curShape ) { return curShape.first.lock() == shape; } ); if ( existingItr == cend( m_shapes ) ) { m_shapes.push_back( std::make_pair< std::weak_ptr< IShapeBuilder >, bool >( std::weak_ptr< IShapeBuilder >{ shape }, true ) ); } } void PartGeometry::RemoveShape( std::shared_ptr< IShapeBuilder > const& shape ) { if ( shape == nullptr ) return; auto existingItr = std::find_if( cbegin( m_shapes ), cend( m_shapes ), [&shape]( const auto& curShape ) { return curShape.first.lock() == shape; } ); if ( existingItr != cend( m_shapes ) ) { m_shapes.erase( existingItr ); } } void PartGeometry::EnableShape( std::shared_ptr< IShapeBuilder > const& shape ) { if ( shape == nullptr ) return; auto existingItr = std::find_if( begin( m_shapes ), end( m_shapes ), [&shape]( const auto& curShape ) { return curShape.first.lock() == shape; } ); if ( existingItr != end( m_shapes ) ) { existingItr->second = true; } } void PartGeometry::DisableShape( std::shared_ptr< IShapeBuilder > const& shape ) { if ( shape == nullptr ) return; auto existingItr = std::find_if( begin( m_shapes ), end( m_shapes ), [&shape]( const auto& curShape ) { return curShape.first.lock() == shape; } ); if ( existingItr != end( m_shapes ) ) { existingItr->second = false; } } void PartGeometry::Accept( PartStructureVisitor& visitor ) const { visitor.Visit( *this ); } std::shared_ptr< IPartShapesIterator > PartGeometry::GetShapesIterator() { return std::make_shared< PartShapesIteratorImpl >( m_shapes.empty() ? m_shapes.end() : m_shapes.begin(), m_shapes.end(), false ); } std::shared_ptr< IPartShapesIterator > PartGeometry::GetEnabledShapesIterator() { return std::make_shared< PartShapesIteratorImpl >( m_shapes.empty() ? m_shapes.end() : m_shapes.begin(), m_shapes.end(), true ); } bool PartGeometry::IsShapeEnabled( std::shared_ptr< IShapeBuilder > const& shape ) const { if ( shape == nullptr ) return false; auto existingItr = std::find_if( cbegin( m_shapes ), cend( m_shapes ), [&shape]( const auto& curShape ) { return curShape.first.lock() == shape; } ); if ( existingItr == cend( m_shapes ) ) { throw std::range_error{ "Missing shape" }; } return existingItr->second; } std::shared_ptr< PartInstanceReference > PartInstance::AddPartInstance( std::shared_ptr< PartInstance > const& part, gp_Trsf const& placement, std::string const& instanceName ) { if ( m_geometry != nullptr ) return {}; if ( part == nullptr ) return {}; auto result = std::make_shared< PartInstanceReference >( part, placement, instanceName ); m_instances.push_back( result ); return result; } std::shared_ptr< PartInstanceReference > PartInstance::AddPartInstanceClone( std::shared_ptr< PartInstance > const& part, gp_Trsf const& placement, std::string const& instanceName ) { if ( m_geometry != nullptr ) return {}; if ( part == nullptr ) return {}; auto partClone = part->MakeDeepClone(); auto result = std::make_shared< PartInstanceReference >( partClone, placement, instanceName ); m_instances.push_back( result ); return result; } void PartInstance::RemovePartInstance( std::shared_ptr< PartInstanceReference > const& instance ) { auto instItr = std::find( cbegin( m_instances ), cend( m_instances ), instance ); if ( instItr != cend( m_instances ) ) m_instances.erase( instItr ); } std::shared_ptr< IPartInstancesIterator > PartInstance::GetInstancesIterator() { return std::make_shared< PartInstancesIteratorImpl >( m_instances.empty() ? m_instances.end() : m_instances.begin(), m_instances.end() ); } bool PartInstance::SamePartGeometry( std::weak_ptr< PartInstance > const& to ) const { auto toLock{ to.lock() }; if ( toLock.get() == this ) return true; if ( m_geometry == toLock->m_geometry ) return true; if ( m_instances.size() != toLock->m_instances.size() ) return false; try { for ( size_t i = 0, sz = m_instances.size(); i < sz; i++ ) { if ( !m_instances[i]->SamePartGeometry( toLock->m_instances[i] ) ) { return false; } } } catch ( std::exception& ) { return false; } return true; } std::optional< bool > PartInstance::UpdateInstancesLocations() { if ( m_constraints == nullptr ) return {}; // Placeholder for OpenCASCADE constraint solving // For now, return true as a placeholder return std::make_optional< bool >( true ); } //bool PartInstance::SetLocationFixed( std::shared_ptr< PartInstanceReference > const& referenceToFixLocation ) //{ // if ( m_constraints == nullptr ) // m_constraints = std::make_unique< InstanceConstraintManager >(); // auto partForConstraint = m_constraints->RegisterPartReferenceForPlacemetUpdate( referenceToFixLocation ); // return m_constraints->SetLocationFixed( partForConstraint ); //} std::optional< CoaxialConstraint > PartInstance::SetCoaxial( ConstraintElement const& one, ConstraintElement const& other ) { std::optional< CoaxialConstraint > result{}; if ( ( !one.IsValid() ) || ( !other.IsValid() ) ) return result; // TODO :: в первом приближении рассматриваем только экземпляры, непосредственно лежащие в данном // const bool onePresentInReferences{ m_instances.cend() // != std::find_if( cbegin( m_instances ), // cend( m_instances ), // [one]( auto const& cutRef ) // { return cutRef == one.second.lock(); } ) }; // if ( !onePresentInReferences ) // return result; // const bool otherPresentInReferences{ m_instances.cend() // != std::find_if( cbegin( m_instances ), // cend( m_instances ), // [other]( auto const& cutRef ) // { return cutRef == other.second.lock(); } ) }; // if ( !otherPresentInReferences ) // return result; if ( m_constraints == nullptr ) m_constraints = std::make_unique< InstanceConstraintManager >(); auto matingOne = m_constraints->RegisterGeometryForPlcaementCalculation( one.ReferenceApplyTransformTo(), one.GeometryCalculateTransformBy() ); auto matingOther = m_constraints->RegisterGeometryForPlcaementCalculation( other.ReferenceApplyTransformTo(), other.GeometryCalculateTransformBy() ); auto ocConstraint = std::make_shared<OCConstraint>(); result = std::make_optional< CoaxialConstraint >( one, other, ocConstraint ); if ( result ) RegisterConstraint( *result ); return result; } std::optional< CoincidenceConstraint > PartInstance::SetCoincident( ConstraintElement const& one, ConstraintElement const& other, MateOrientation orientationHint ) { std::optional< CoincidenceConstraint > result{}; if ( ( !one.IsValid() ) || ( !other.IsValid() ) ) return result; if ( m_constraints == nullptr ) m_constraints = std::make_unique< InstanceConstraintManager >(); auto matingOne = m_constraints->RegisterGeometryForPlcaementCalculation( one.ReferenceApplyTransformTo(), one.GeometryCalculateTransformBy() ); auto matingOther = m_constraints->RegisterGeometryForPlcaementCalculation( other.ReferenceApplyTransformTo(), other.GeometryCalculateTransformBy() ); OCAlignment aVal = OCAlignment::CLOSEST; switch ( orientationHint ) { case MateOrientation::same: aVal = OCAlignment::COORIENTED; break; case MateOrientation::opposite: aVal = OCAlignment::OPPOSITE; break; case MateOrientation::solverDecides: aVal = OCAlignment::CLOSEST; break; default: break; } auto ocConstraint = std::make_shared<OCConstraint>(); result = std::make_optional< CoincidenceConstraint >( one, other, orientationHint, ocConstraint ); if ( result ) RegisterConstraint( *result ); return result; } std::optional< TangentConstraint > PartInstance::SetTangent( ConstraintElement const& one, ConstraintElement const& other ) { std::optional< TangentConstraint > result{}; if ( ( !one.IsValid() ) || ( !other.IsValid() ) ) return result; if ( m_constraints == nullptr ) m_constraints = std::make_unique< InstanceConstraintManager >(); auto matingOne = m_constraints->RegisterGeometryForPlcaementCalculation( one.ReferenceApplyTransformTo(), one.GeometryCalculateTransformBy() ); auto matingOther = m_constraints->RegisterGeometryForPlcaementCalculation( other.ReferenceApplyTransformTo(), other.GeometryCalculateTransformBy() ); auto ocConstraint = std::make_shared<OCConstraint>(); result = std::make_optional< TangentConstraint >( one, other, ocConstraint ); if ( result ) RegisterConstraint( *result ); return result; } std::optional< PerpendicularConstraint > PartInstance::SetPerpendicular( ConstraintElement const& one, ConstraintElement const& other ) { std::optional< PerpendicularConstraint > result{}; if ( ( !one.IsValid() ) || ( !other.IsValid() ) ) return result; if ( m_constraints == nullptr ) m_constraints = std::make_unique< InstanceConstraintManager >(); auto matingOne = m_constraints->RegisterGeometryForPlcaementCalculation( one.ReferenceApplyTransformTo(), one.GeometryCalculateTransformBy() ); auto matingOther = m_constraints->RegisterGeometryForPlcaementCalculation( other.ReferenceApplyTransformTo(), other.GeometryCalculateTransformBy() ); auto ocConstraint = std::make_shared<OCConstraint>(); result = std::make_optional< PerpendicularConstraint >( one, other, ocConstraint ); if ( result ) RegisterConstraint( *result ); return result; } PartInstanceReference::PartInstanceReference( std::shared_ptr< PartInstance > const& part, gp_Trsf const& placement, std::string const& name ) : m_part{ part } , m_location{ placement } , m_name{ name } { } void PartInstanceReference::UpdateLocation( gp_Trsf const& location ) { m_location = location; } void PartInstanceReference::Accept( PartStructureVisitor& visitor ) const { visitor.Visit( *this ); } bool PartInstanceReference::SamePartGeometry( std::weak_ptr< PartInstanceReference > const& other ) const { auto toLock{ other.lock() }; if ( !toLock ) return false; if ( toLock.get() == this ) return true; double const tol = R1::Distance::Epsilon(); for ( int i = 1; i <= 3; ++i ) for ( int j = 1; j <= 4; ++j ) if ( std::abs( m_location.Value( i, j ) - toLock->m_location.Value( i, j ) ) > tol ) return false; auto myPart = m_part.lock(); auto otherPart = toLock->m_part.lock(); if ( !myPart || !otherPart ) return false; return myPart->SamePartGeometry( toLock->m_part ); } bool PartInstance::SetLocationFixed( std::shared_ptr< PartInstanceReference > const& referenceToFixLocation ) { if ( m_constraints == nullptr ) m_constraints = std::make_unique< InstanceConstraintManager >(); return m_constraints->SetLocationFixed( referenceToFixLocation.get() ); } std::weak_ptr< PartInstance > PartInstanceReference::ReferencedInstance() const { return m_part; } gp_Trsf PartInstanceReference::Location() const { return m_location; } std::string PartInstanceReference::Name() const { return m_name; } void PartInstance::RegisterConstraint( PartInstance::ConstraintVariant const& constraint ) { m_constraintsStorage.push_back( constraint ); } std::shared_ptr< IConstraintIterator > PartInstance::GetConstraintsIterator() const { return std::make_shared< ConstraintIteratorImpl >( m_constraintsStorage.cbegin(), m_constraintsStorage.cend() ); }