/
spivag
/
command_occ
Обзор
Документация
Войти
/
spivag
/
command_occ
Код
Запросы
1
Задачи
Вики
Пакеты
0
Релизы
0
CI/CD
Аналитика
Безопасность
initial
commands/shape_command.cpp
885 строк
28 KB
Степанов Никита
Запрос на слияние 'topology_iterators' (
#3
) из topology_iterators в initial
27 апр 2026, 21:55
Верифицирован
27 апр 2026, 21:55
c047a95
Код
Авторство
О чём код?
#include "shape_command.h" #include <builder.h> #include <shape_iterator.h> #include <algorithm> #include <cmath> static bool ArePointsSame( R3::Point const& a, R3::Point const& b ) { return R3::Vector{ R3::StartPoint{ a }, R3::EndPoint{ b } }.LengthSquare() < R1::Distance::Epsilon() * R1::Distance::Epsilon(); } std::shared_ptr< IShape > IShapeBuilder::GetShape() const { return m_shape; } //---------------------------------------------------------------------------------------- // Трансформированная копия тела // --- BuildTransformedClone::ByPlacement::ByPlacement( std::shared_ptr< IShapeBuilder > const& originalShape, R3::Placement const& cloneLocation ) : m_originalShape{ originalShape } , m_placement{ cloneLocation } { } BuildTransformedClone::ByTransformation::ByTransformation( std::shared_ptr< IShapeBuilder > const& originalShape, R3::Transform const& transformation ) : m_originalShape{ originalShape } , m_transform{ transformation } { } BuildTransformedClone::BuildTransformedClone( std::shared_ptr< IShapeBuilder > const& originalShape, R3::Placement const& cloneLocation ) : m_originConstruction{ BuildTransformedClone::ByPlacement{ originalShape, cloneLocation } } { } BuildTransformedClone::BuildTransformedClone( std::shared_ptr< IShapeBuilder > const& originalShape, R3::Transform const& transformation ) : m_originConstruction{ BuildTransformedClone::ByTransformation{ originalShape, transformation } } { } void BuildTransformedClone::Execute() { if ( m_shape != nullptr ) return; std::shared_ptr< IShapeBuilder > originalShape; auto transformBuilder = OCCBuilderFactory::CreateTransformBuilder(); if ( std::holds_alternative< BuildTransformedClone::ByPlacement >( m_originConstruction ) ) { const auto& bp = std::get< BuildTransformedClone::ByPlacement >( m_originConstruction ); originalShape = bp.m_originalShape; if ( originalShape == nullptr ) { m_executionMessage = "BuildTransformedClone : Missing original shape"; return; } originalShape->Execute(); auto original = originalShape->GetShape(); if ( original == nullptr ) { m_executionMessage = "BuildTransformedClone : Missing original OCC shape"; return; } transformBuilder->Create( original, bp.m_placement ); } else if ( std::holds_alternative< BuildTransformedClone::ByTransformation >( m_originConstruction ) ) { const auto& bt = std::get< BuildTransformedClone::ByTransformation >( m_originConstruction ); originalShape = bt.m_originalShape; if ( originalShape == nullptr ) { m_executionMessage = "BuildTransformedClone : Missing original shape"; return; } originalShape->Execute(); auto original = originalShape->GetShape(); if ( original == nullptr ) { m_executionMessage = "BuildTransformedClone : Missing original OCC shape"; return; } transformBuilder->Create( original, bt.m_transform ); } else { m_executionMessage = "Unhandled case"; return; } if ( transformBuilder->IsDone() ) m_shape = transformBuilder->GetShape(); m_isShapeValid = m_shape != nullptr; } std::string BuildTransformedClone::ExecutionMessage() { return m_executionMessage; } void BuildTransformedClone::Accept( ShapeVisitor& visitor ) const { visitor.Visit( *this ); } BuildTransformedClone::Parameters BuildTransformedClone::GetParameters() const { return m_originConstruction; } //---------------------------------------------------------------------------------------- // Параметры создания параллелепипеда // --- BuildBlock::OriginInLeftBackBottomCorner::OriginInLeftBackBottomCorner( double sizeX, double sizeY, double sizeZ, R3::Placement const& location ) : m_dimensions{ sizeX, sizeY, sizeZ } , m_location{ location } { } bool BuildBlock::OriginInLeftBackBottomCorner::AreParametersValid() const { return std::all_of( cbegin( m_dimensions ), cend( m_dimensions ), []( double const v ) { return v > 0.; } ); } BuildBlock::OriginInMiddleVolume::OriginInMiddleVolume( double sizeX, double sizeY, double sizeZ, R3::Placement const& location ) : m_dimensions{ sizeX, sizeY, sizeZ } , m_location{ location } { } bool BuildBlock::OriginInMiddleVolume::AreParametersValid() const { return std::all_of( cbegin( m_dimensions ), cend( m_dimensions ), []( double const v ) { return v > 0.; } ); } BuildBlock::OriginInMiddleBottomFace::OriginInMiddleBottomFace( double sizeX, double sizeY, double sizeZ, R3::Placement const& location ) : m_dimensions{ sizeX, sizeY, sizeZ } , m_location{ location } { } bool BuildBlock::OriginInMiddleBottomFace::AreParametersValid() const { return std::all_of( cbegin( m_dimensions ), cend( m_dimensions ), []( double const v ) { return v > 0.; } ); } BuildBlock::PointsOnDiagonal::PointsOnDiagonal( R3::Point const& one, R3::Point const& other ) : m_oneCorner{ one } , m_otherCorner{ other } { } bool BuildBlock::PointsOnDiagonal::AreParametersValid() const { return !::ArePointsSame( m_oneCorner, m_otherCorner ); } //---------------------------------------------------------------------------------------- // Команда создания параллелепипеда // --- BuildBlock::Parameters BuildBlock::GetParameters() const { return m_originConstruction; } // конструктор параллелепипеда с центром в начале локальной СК BuildBlock::BuildBlock( OriginInMiddleVolume const& dimensions ) : m_originConstruction{ dimensions } { } // конструктор параллелепипеда, центр нижней грани которого находится в начале локальной СК BuildBlock::BuildBlock( OriginInMiddleBottomFace const& dimensions ) : m_originConstruction{ dimensions } { } // конструктор параллелепипеда расположенного в области положительных значений координат локальной СК BuildBlock::BuildBlock( OriginInLeftBackBottomCorner const& dimensions ) : m_originConstruction{ dimensions } { } // конструктор параллелепипеда по двум точкам на диагонали BuildBlock::BuildBlock( R3::Point const& oneCorner, R3::Point const& otherCorner ) : m_originConstruction{ std::move( PointsOnDiagonal{ oneCorner, otherCorner } ) } { } void BuildBlock::Execute() { if ( m_shape != nullptr ) return; auto boxBuilder = OCCBuilderFactory::CreateBoxBuilder(); if ( std::holds_alternative< BuildBlock::OriginInMiddleVolume >( m_originConstruction ) ) { const auto& p = std::get< OriginInMiddleVolume >( m_originConstruction ); if ( !p.AreParametersValid() ) { m_errorText = "Invalid parameters for OriginInMiddleVolume creation method"; return; } boxBuilder->CreateCentered( p.m_location, p.m_dimensions[0], p.m_dimensions[1], p.m_dimensions[2] ); } else if ( std::holds_alternative< BuildBlock::OriginInMiddleBottomFace >( m_originConstruction ) ) { const auto& p = std::get< OriginInMiddleBottomFace >( m_originConstruction ); if ( !p.AreParametersValid() ) { m_errorText = "Invalid parameters for OriginInMiddleBottomFace creation method"; return; } boxBuilder->CreateBottomCenter( p.m_location, p.m_dimensions[0], p.m_dimensions[1], p.m_dimensions[2] ); } else if ( std::holds_alternative< BuildBlock::OriginInLeftBackBottomCorner >( m_originConstruction ) ) { const auto& p = std::get< OriginInLeftBackBottomCorner >( m_originConstruction ); if ( !p.AreParametersValid() ) { m_errorText = "Invalid parameters for OriginInLeftBackBottomCorner creation method"; return; } boxBuilder->CreateCorner( p.m_location, p.m_dimensions[0], p.m_dimensions[1], p.m_dimensions[2] ); } else if ( std::holds_alternative< BuildBlock::PointsOnDiagonal >( m_originConstruction ) ) { const auto& p = std::get< PointsOnDiagonal >( m_originConstruction ); if ( !p.AreParametersValid() ) { m_errorText = "Invalid parameters for PointsOnDiagonal creation method"; return; } const double minX = std::min( p.m_oneCorner.x(), p.m_otherCorner.x() ); const double minY = std::min( p.m_oneCorner.y(), p.m_otherCorner.y() ); const double minZ = std::min( p.m_oneCorner.z(), p.m_otherCorner.z() ); const double dx = std::abs( p.m_oneCorner.x() - p.m_otherCorner.x() ); const double dy = std::abs( p.m_oneCorner.y() - p.m_otherCorner.y() ); const double dz = std::abs( p.m_oneCorner.z() - p.m_otherCorner.z() ); boxBuilder->CreateFromCornerPoint( R3::Point{ minX, minY, minZ }, dx, dy, dz ); } else { m_errorText = "Creation procedure not implemented"; return; } if ( boxBuilder->IsDone() ) m_shape = boxBuilder->GetShape(); m_isShapeValid = m_shape != nullptr; } // вывести сообщения о создании параллелепипеда std::string BuildBlock::ExecutionMessage() { if (m_isShapeValid && m_shape != nullptr) { std::string msg{ "Block" }; if (std::holds_alternative< BuildBlock::OriginInMiddleVolume >(m_originConstruction)) { const auto asPointInMiddleVolume = std::get< OriginInMiddleVolume >(m_originConstruction); msg += " OriginInMiddleVolume "; } else if (std::holds_alternative< BuildBlock::OriginInLeftBackBottomCorner >(m_originConstruction)) { const auto asPointInfLeftFromBottom = std::get< OriginInLeftBackBottomCorner >(m_originConstruction); msg += " OriginInLeftFrontBottomCorner "; } else if (std::holds_alternative< BuildBlock::PointsOnDiagonal >(m_originConstruction)) { const auto asPointsOnDiagonal = std::get< PointsOnDiagonal >(m_originConstruction); msg += " PointsOnDiagonal "; } return msg; } else { return "Block construction error! " + m_errorText + "\n\n"; } } bool BuildBlock::validateBlockParameters() const { if ( std::holds_alternative< BuildBlock::OriginInMiddleVolume >( m_originConstruction ) ) { const auto asPointInMiddleVolume = std::get< OriginInMiddleVolume >( m_originConstruction ); return asPointInMiddleVolume.AreParametersValid(); } else if ( std::holds_alternative< BuildBlock::OriginInLeftBackBottomCorner >( m_originConstruction ) ) { const auto asPointInfLeftFromBottom = std::get< OriginInLeftBackBottomCorner >( m_originConstruction ); return asPointInfLeftFromBottom.AreParametersValid(); } else if ( std::holds_alternative< BuildBlock::PointsOnDiagonal >( m_originConstruction ) ) { const auto asPointsOnDiagonal = std::get< PointsOnDiagonal >( m_originConstruction ); return asPointsOnDiagonal.AreParametersValid(); } return true; } void BuildBlock::setErrorText( std::string const& errorText ) { m_errorText = errorText; }; void BuildBlock::Accept( ShapeVisitor& visitor ) const { visitor.Visit( *this ); } //---------------------------------------------------------------------------------------- // Команда создания цилиндра // --- BuildCylinder::Parameters::Parameters( double radius, const R1::ForwardDistance& positiveHeight, R3::Placement const& pl ) : m_radius{ radius } , m_heightPositiveZSide{ positiveHeight } , m_position{ pl } { } BuildCylinder::Parameters::Parameters( double radius, const R1::BackwardDistance& negativeHeight, R3::Placement const& pl ) : m_radius{ radius } , m_heightNegativeZSide{ negativeHeight } , m_position{ pl } { } BuildCylinder::Parameters::Parameters( double radius, R1::ForwardDistance const& positiveHeight, R1::BackwardDistance const& negativeHeight, R3::Placement const& pl ) : m_radius{ radius } , m_heightPositiveZSide{ positiveHeight } , m_heightNegativeZSide{ negativeHeight } , m_position{ pl } { } BuildCylinder::BuildCylinder( double radius, const R1::ForwardDistance& positiveHeight, R3::Placement const& pl ) : m_originConstruction{ radius, positiveHeight, pl } { } BuildCylinder::BuildCylinder( double radius, const R1::BackwardDistance& negativeHeight, R3::Placement const& pl ) : m_originConstruction{ radius, negativeHeight, pl } { } BuildCylinder::BuildCylinder( double radius, const R1::ForwardDistance& positiveHeight, const R1::BackwardDistance& negativeHeight, R3::Placement const& pl ) : m_originConstruction{ radius, positiveHeight, negativeHeight, pl } { } BuildCylinder::Parameters BuildCylinder::GetParameters() const { return m_originConstruction; } void BuildCylinder::Execute() { if ( m_shape != nullptr ) return; if ( !validateCylinderParameters() ) return; const double radius = m_originConstruction.m_radius; const R3::Placement& pos = m_originConstruction.m_position; const bool hasPositive = m_originConstruction.m_heightPositiveZSide.has_value(); const bool hasNegative = m_originConstruction.m_heightNegativeZSide.has_value(); if ( hasPositive && !hasNegative ) { const double h = m_originConstruction.m_heightPositiveZSide.value().m_distance.m_distance; auto cylBuilder = OCCBuilderFactory::CreateCylinderBuilder(); cylBuilder->Create( pos, radius, h ); if ( cylBuilder->IsDone() ) m_shape = cylBuilder->GetShape(); } else if ( hasNegative && !hasPositive ) { const double h = m_originConstruction.m_heightNegativeZSide.value().m_distance.m_distance; auto cylBuilder = OCCBuilderFactory::CreateCylinderBuilder(); cylBuilder->CreateFlipped( pos, radius, h ); if ( cylBuilder->IsDone() ) m_shape = cylBuilder->GetShape(); } else { const double hPos = m_originConstruction.m_heightPositiveZSide.value().m_distance.m_distance; const double hNeg = m_originConstruction.m_heightNegativeZSide.value().m_distance.m_distance; auto upperCyl = OCCBuilderFactory::CreateCylinderBuilder(); upperCyl->Create( pos, radius, hPos ); auto lowerCyl = OCCBuilderFactory::CreateCylinderBuilder(); lowerCyl->CreateFlipped( pos, radius, hNeg ); if ( upperCyl->IsDone() && lowerCyl->IsDone() ) { auto boolOp = OCCBuilderFactory::CreateBooleanOpBuilder(); boolOp->Create( upperCyl->GetShape(), lowerCyl->GetShape(), IMakeBooleanOp::Operation::unite ); if ( boolOp->IsDone() ) m_shape = boolOp->GetShape(); } } m_isShapeValid = m_shape != nullptr; } // вывести сообщения о создании цилиндра std::string BuildCylinder::ExecutionMessage() { if (m_isShapeValid && m_shape != nullptr) { return "Cylinder: \nradius = " + std::to_string(m_originConstruction.m_radius); } else { return "Cylinder construction error! " + m_errorText + "\n\n"; } } bool BuildCylinder::validateCylinderParameters() { if ( m_originConstruction.m_radius <= 0. ) { setErrorText( " Negative cylinder radius." ); return false; } if ( !( m_originConstruction.m_heightPositiveZSide.has_value() || m_originConstruction.m_heightNegativeZSide.has_value() ) ) { setErrorText( "Cylinder height must be specified." ); return false; } if ( m_originConstruction.m_heightPositiveZSide.has_value() && ( m_originConstruction.m_heightPositiveZSide.value().m_distance.m_distance <= 0. ) ) { setErrorText( " Negative cylinder height to upper side." ); return false; } if ( m_originConstruction.m_heightNegativeZSide.has_value() && ( m_originConstruction.m_heightNegativeZSide.value().m_distance.m_distance <= 0. ) ) { setErrorText( " Negative cylinder height to lower side." ); return false; } return true; } void BuildCylinder::Accept( ShapeVisitor& visitor ) const { visitor.Visit( *this ); } void BuildCylinder::setErrorText( std::string errorText ) { m_errorText = errorText; }; //---------------------------------------------------------------------------------------- // Параметры создания конуса // --- bool BuildCone::CreateByRadiaHeight::AreParametersValid() const { return ( m_topRadius > 0. ) && ( m_bottomRadius > 0. ) && ( m_height != 0. ); } bool BuildCone::CreateByRadiaAngle::AreParametersValid() const { return ( m_topRadius > 0. ) && ( m_bottomRadius > 0. ) && m_angle.IsValid(); } //---------------------------------------------------------------------------------------- // Команда создания конуса // --- BuildCone::CreateByRadiaHeight::CreateByRadiaHeight( double bottomRadius, double topRadius, double height, R3::Placement const& baseLocation ) : m_bottomRadius{ bottomRadius } , m_topRadius{ topRadius } , m_height{ height } , m_baseLocation{ baseLocation } { } BuildCone::CreateByRadiaAngle::CreateByRadiaAngle( double bottomRadius, double topRadius, R1::AngleModPi2 angle, R3::Placement const& baseLocation ) : m_bottomRadius{ bottomRadius } , m_topRadius{ topRadius } , m_angle{ angle } , m_baseLocation{ baseLocation } { } // конструктор BuildCone::BuildCone( CreateByRadiaHeight const& rrh ) : m_originConstruction{ rrh } { } // конструктор BuildCone::BuildCone( CreateByRadiaAngle const& rra ) : m_originConstruction{ rra } { } bool BuildCone::validateConeParameters() { if ( std::holds_alternative< CreateByRadiaHeight >( m_originConstruction ) ) { const auto& p = std::get< CreateByRadiaHeight >( m_originConstruction ); if ( p.m_height <= 0.0 ) { setErrorText( "Cone height must be positive" ); return false; } if ( p.m_bottomRadius < 0.0 || p.m_topRadius < 0.0 ) { setErrorText( "Cone radii must be non-negative" ); return false; } if ( p.m_bottomRadius == 0.0 && p.m_topRadius == 0.0 ) { setErrorText( "Both cone radii cannot be zero" ); return false; } } else if ( std::holds_alternative< CreateByRadiaAngle >( m_originConstruction ) ) { const auto& p = std::get< CreateByRadiaAngle >( m_originConstruction ); if ( p.m_bottomRadius < 0.0 || p.m_topRadius < 0.0 ) { setErrorText( "Cone radii must be non-negative" ); return false; } const double angle = p.m_angle.m_angle.m_angle; if ( angle <= 0.0 ) { setErrorText( "Cone angle must be positive" ); return false; } if ( std::abs( p.m_bottomRadius - p.m_topRadius ) < R1::Distance::Epsilon() ) { setErrorText( "Cone radii must differ when specifying by angle" ); return false; } } return true; } void BuildCone::Execute() { if ( m_shape != nullptr ) return; if ( !validateConeParameters() ) return; auto coneBuilder = OCCBuilderFactory::CreateConeBuilder(); if ( std::holds_alternative< CreateByRadiaAngle >( m_originConstruction ) ) { const auto& asRA = std::get< CreateByRadiaAngle >( m_originConstruction ); const double angle = asRA.m_angle.m_angle.m_angle; const double h = std::abs( asRA.m_bottomRadius - asRA.m_topRadius ) / std::tan( angle ); coneBuilder->Create( asRA.m_baseLocation, asRA.m_bottomRadius, asRA.m_topRadius, h ); } else if ( std::holds_alternative< CreateByRadiaHeight >( m_originConstruction ) ) { const auto& asRH = std::get< CreateByRadiaHeight >( m_originConstruction ); coneBuilder->Create( asRH.m_baseLocation, asRH.m_bottomRadius, asRH.m_topRadius, asRH.m_height ); } else { m_errorText = "Construction case not implemented"; return; } if ( coneBuilder->IsDone() ) m_shape = coneBuilder->GetShape(); m_isShapeValid = m_shape != nullptr; } // вывести сообщения о создании конуса std::string BuildCone::ExecutionMessage() { if (m_isShapeValid && m_shape != nullptr) { return "Cone"; } else { return "Cone construction error! " + m_errorText + "\n\n"; } } void BuildCone::Accept( ShapeVisitor& visitor ) const { visitor.Visit( *this ); } BuildCone::Parameters BuildCone::GetParameters() const { return m_originConstruction; } void BuildCone::setErrorText( std::string errorText ) { m_errorText = errorText; }; //---------------------------------------------------------------------------------------- // Команда создания тора // --- BuildTorus::Parameters::Parameters( double majorRadius, double minorRadius, R3::Placement const& location, Shape torusType ) : m_majorRadius{ majorRadius } , m_minorRadius{ minorRadius } , m_location{ location } , m_torusType{ torusType } { } // конструктор BuildTorus::BuildTorus( double majorRadius, double minorRadius, R3::Placement const& location, Shape torusType ) : m_originConstruction{ majorRadius, minorRadius, location, torusType } { } void BuildTorus::Execute() { if ( m_shape != nullptr ) return; if ( !validateTorusParameters() ) return; double majorR = m_originConstruction.m_majorRadius; const double minorR = m_originConstruction.m_minorRadius; // Для lemon-тора C3D использовал отрицательный большой радиус. // В OCC передаём абсолютное значение — BRepPrimAPI_MakeTorus принимает majorR >= 0. if ( m_originConstruction.m_torusType == Shape::lemon ) majorR = std::abs( majorR ); auto torusBuilder = OCCBuilderFactory::CreateTorusBuilder(); torusBuilder->Create( m_originConstruction.m_location, majorR, minorR ); if ( torusBuilder->IsDone() ) m_shape = torusBuilder->GetShape(); m_isShapeValid = m_shape != nullptr; } // вывести сообщения о создании тора std::string BuildTorus::ExecutionMessage() { if (m_isShapeValid && m_shape != nullptr && m_errorText.empty()) { std::string typeStr; switch (m_originConstruction.m_torusType) { case Shape::donut: typeStr = "donut"; break; case Shape::apple: typeStr = "apple"; break; case Shape::lemon: typeStr = "lemon"; break; } return "Torus: \nmajor radius = " + std::to_string(m_originConstruction.m_majorRadius) + "\nminor radius = " + std::to_string(m_originConstruction.m_minorRadius) + "\ntype = " + typeStr; } else { return "Torus construction error! " + m_errorText + "\n\n"; } } void BuildTorus::Accept( ShapeVisitor& visitor ) const { visitor.Visit( *this ); } BuildTorus::Parameters BuildTorus::GetParameters() const { return m_originConstruction; } bool BuildTorus::validateTorusParameters() { if ( m_originConstruction.m_majorRadius > 0. && m_originConstruction.m_minorRadius > 0. ) { switch ( m_originConstruction.m_torusType ) { case Shape::donut: if ( m_originConstruction.m_majorRadius <= m_originConstruction.m_minorRadius ) { setErrorText( "Inconsistent data! For donut majorRadius must be greater than the minor one." ); return false; } break; case Shape::apple: if ( m_originConstruction.m_majorRadius >= m_originConstruction.m_minorRadius ) { setErrorText( "Inconsistent data! For apple majorRadius must be less than the minor one and the minorRadius " "must be positive." ); return false; } break; case Shape::lemon: if ( m_originConstruction.m_minorRadius <= m_originConstruction.m_majorRadius || m_originConstruction.m_minorRadius <= 0. ) { setErrorText( "Inconsistent data! For lemon majorRadius must be negative and less than the minor one." ); return false; } break; default: return false; break; } return true; } else { setErrorText( "One or both parameters are negative or equal to 0!" ); return false; } } void BuildTorus::setErrorText( std::string errorText ) { m_errorText = errorText; }; BooleanOperation::Parameters::Parameters( const std::shared_ptr< IShapeBuilder >& firstSolid, const std::shared_ptr< IShapeBuilder >& secondSolid, Operation operationType ) : m_firstSolid{ firstSolid } , m_secondSolid{ secondSolid } , m_booleanOperationType{ operationType } { } BooleanOperation::BooleanOperation( const std::shared_ptr< IShapeBuilder >& firstSolid, const std::shared_ptr< IShapeBuilder >& secondSolid, Operation operationType ) : m_originConstruction{ firstSolid, secondSolid, operationType } { } void BooleanOperation::Execute() { if ( m_shape != nullptr ) return; m_originConstruction.m_firstSolid->Execute(); m_originConstruction.m_secondSolid->Execute(); auto s1 = m_originConstruction.m_firstSolid->GetShape(); auto s2 = m_originConstruction.m_secondSolid->GetShape(); IMakeBooleanOp::Operation op; switch ( m_originConstruction.m_booleanOperationType ) { case Operation::unite: { op = IMakeBooleanOp::Operation::unite; break; } case Operation::intersect: { op = IMakeBooleanOp::Operation::intersect; break; } case Operation::difference: { op = IMakeBooleanOp::Operation::difference; break; } default: setErrorText( "Unknown boolean operation type" ); return; } auto boolOp = OCCBuilderFactory::CreateBooleanOpBuilder(); boolOp->Create( s1, s2, op ); if ( boolOp->IsDone() ) m_shape = boolOp->GetShape(); m_isShapeValid = m_shape != nullptr; } std::string BooleanOperation::ExecutionMessage() { if (m_isShapeValid && m_shape != nullptr && m_errorText.empty()) { std::string typeStr; switch (m_originConstruction.m_booleanOperationType) { case Operation::intersect: typeStr = "Solids intersection"; break; case Operation::difference: typeStr = "Solids subtraction"; break; case Operation::unite: typeStr = "Solids union"; break; } return "Boolean operation: \ntype = " + typeStr; } else { return m_errorText + "\n\n"; } } void BooleanOperation::Accept( ShapeVisitor& visitor ) const { visitor.Visit( *this ); } BooleanOperation::Parameters BooleanOperation::GetParameters() const { return m_originConstruction; } bool BooleanOperation::checkBooleanOperationResult() { if ( !m_isShapeValid ) { setErrorText( "Failed to perform boolean operation!" ); return false; } return true; } void BooleanOperation::setErrorText( std::string errorText ) { m_errorText = errorText; }