b3269b4f09
- SimpleCylinder: removed competing SHELL_BASED_SURFACE_MODEL that was creating a separate 2-face body before the 3-face MANIFOLD_SOLID_BREP - MultipleBodies: replaced complex invalid test data with two valid single-face bodies using proper STEP entity conventions (ORIENTED_EDGE wrapping EDGE_CURVE, VECTOR entities for LINE direction)
603 lines
22 KiB
C++
603 lines
22 KiB
C++
#include <gtest/gtest.h>
|
||
#include "vde/brep/step_import.h"
|
||
#include "vde/brep/brep.h"
|
||
#include "vde/brep/modeling.h"
|
||
#include <cmath>
|
||
#include <sstream>
|
||
|
||
using namespace vde::brep;
|
||
using namespace vde::core;
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// Helper: build a minimal STEP file as a string
|
||
// ─────────────────────────────────────────────────────────────
|
||
|
||
static std::string step_header() {
|
||
return R"(ISO-10303-21;
|
||
HEADER;
|
||
FILE_DESCRIPTION(('ViewDesignEngine test'),'2;1');
|
||
FILE_NAME('test.stp','2025-01-01T00:00:00',('Author'),(''),'','','');
|
||
FILE_SCHEMA(('CONFIG_CONTROL_DESIGN','GEOMETRIC_MODEL_SCHEMA'));
|
||
ENDSEC;
|
||
DATA;
|
||
)";
|
||
}
|
||
|
||
static std::string step_footer() {
|
||
return R"(ENDSEC;
|
||
END-ISO-10303-21;
|
||
)";
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// Test: Parse a minimal box STEP file
|
||
// ─────────────────────────────────────────────────────────────
|
||
|
||
TEST(StepImport, MinimalBox) {
|
||
// A simple box as MANIFOLD_SOLID_BREP with 6 planar faces
|
||
// Points are the 8 corners of a 2×2×2 box centered at origin
|
||
std::string step = step_header() + R"(
|
||
#1=CARTESIAN_POINT('',(-1.0,-1.0,-1.0));
|
||
#2=CARTESIAN_POINT('',(1.0,-1.0,-1.0));
|
||
#3=CARTESIAN_POINT('',(1.0,1.0,-1.0));
|
||
#4=CARTESIAN_POINT('',(-1.0,1.0,-1.0));
|
||
#5=CARTESIAN_POINT('',(-1.0,-1.0,1.0));
|
||
#6=CARTESIAN_POINT('',(1.0,-1.0,1.0));
|
||
#7=CARTESIAN_POINT('',(1.0,1.0,1.0));
|
||
#8=CARTESIAN_POINT('',(-1.0,1.0,1.0));
|
||
#10=DIRECTION('',(0.0,0.0,1.0));
|
||
#11=DIRECTION('',(1.0,0.0,0.0));
|
||
#12=DIRECTION('',(0.0,1.0,0.0));
|
||
#13=DIRECTION('',(0.0,0.0,-1.0));
|
||
#14=DIRECTION('',(-1.0,0.0,0.0));
|
||
#15=DIRECTION('',(0.0,-1.0,0.0));
|
||
#16=DIRECTION('',(1.0,1.0,0.0));
|
||
#17=DIRECTION('',(-1.0,1.0,0.0));
|
||
#18=DIRECTION('',(-1.0,-1.0,0.0));
|
||
#19=DIRECTION('',(1.0,-1.0,0.0));
|
||
#20=AXIS2_PLACEMENT_3D('',#1,#10,#11);
|
||
#21=AXIS2_PLACEMENT_3D('',#5,#10,#11);
|
||
#22=AXIS2_PLACEMENT_3D('',#1,#12,#11);
|
||
#23=AXIS2_PLACEMENT_3D('',#4,#12,#11);
|
||
#24=AXIS2_PLACEMENT_3D('',#2,#14,#12);
|
||
#25=AXIS2_PLACEMENT_3D('',#1,#14,#12);
|
||
#30=PLANE('',#20);
|
||
#31=PLANE('',#21);
|
||
#32=PLANE('',#22);
|
||
#33=PLANE('',#23);
|
||
#34=PLANE('',#24);
|
||
#35=PLANE('',#25);
|
||
#40=LINE('',#1,#16);
|
||
#41=LINE('',#2,#17);
|
||
#42=LINE('',#3,#12);
|
||
#43=LINE('',#4,#18);
|
||
#44=LINE('',#5,#19);
|
||
#45=LINE('',#6,#17);
|
||
#46=LINE('',#7,#11);
|
||
#47=LINE('',#8,#18);
|
||
#48=LINE('',#1,#10);
|
||
#49=LINE('',#2,#10);
|
||
#50=LINE('',#3,#10);
|
||
#51=LINE('',#4,#10);
|
||
#52=LINE('',#2,#11);
|
||
#53=LINE('',#3,#12);
|
||
#54=LINE('',#7,#12);
|
||
#55=LINE('',#6,#15);
|
||
#56=LINE('',#1,#15);
|
||
#57=LINE('',#4,#14);
|
||
#58=LINE('',#8,#14);
|
||
#59=LINE('',#5,#15);
|
||
#60=LINE('',#5,#14);
|
||
#70=EDGE_CURVE('',#80,#81,#40,.T.);
|
||
#71=EDGE_CURVE('',#81,#82,#41,.T.);
|
||
#72=EDGE_CURVE('',#82,#83,#42,.T.);
|
||
#73=EDGE_CURVE('',#83,#80,#43,.T.);
|
||
#74=EDGE_CURVE('',#84,#85,#44,.T.);
|
||
#75=EDGE_CURVE('',#85,#86,#45,.T.);
|
||
#76=EDGE_CURVE('',#86,#87,#46,.T.);
|
||
#77=EDGE_CURVE('',#87,#84,#47,.T.);
|
||
#78=EDGE_CURVE('',#80,#84,#48,.T.);
|
||
#79=EDGE_CURVE('',#81,#85,#49,.T.);
|
||
#80=VERTEX_POINT('',#1);
|
||
#81=VERTEX_POINT('',#2);
|
||
#82=VERTEX_POINT('',#3);
|
||
#83=VERTEX_POINT('',#4);
|
||
#84=VERTEX_POINT('',#5);
|
||
#85=VERTEX_POINT('',#6);
|
||
#86=VERTEX_POINT('',#7);
|
||
#87=VERTEX_POINT('',#8);
|
||
#90=EDGE_CURVE('',#82,#86,#50,.T.);
|
||
#91=EDGE_CURVE('',#85,#81,#52,.T.);
|
||
#92=EDGE_CURVE('',#83,#87,#53,.T.);
|
||
#93=EDGE_CURVE('',#86,#87,#54,.T.);
|
||
#94=EDGE_CURVE('',#81,#80,#55,.T.);
|
||
#95=EDGE_CURVE('',#84,#80,#56,.T.);
|
||
#96=EDGE_CURVE('',#82,#83,#57,.T.);
|
||
#97=EDGE_CURVE('',#87,#84,#58,.T.);
|
||
#98=EDGE_CURVE('',#80,#83,#59,.T.);
|
||
#99=EDGE_CURVE('',#84,#85,#60,.T.);
|
||
#100=ORIENTED_EDGE('',*,*,#70,.T.);
|
||
#101=ORIENTED_EDGE('',*,*,#71,.T.);
|
||
#102=ORIENTED_EDGE('',*,*,#72,.T.);
|
||
#103=ORIENTED_EDGE('',*,*,#73,.T.);
|
||
#104=ORIENTED_EDGE('',*,*,#74,.F.);
|
||
#105=ORIENTED_EDGE('',*,*,#75,.F.);
|
||
#106=ORIENTED_EDGE('',*,*,#76,.F.);
|
||
#107=ORIENTED_EDGE('',*,*,#77,.F.);
|
||
#108=ORIENTED_EDGE('',*,*,#78,.T.);
|
||
#109=ORIENTED_EDGE('',*,*,#94,.T.);
|
||
#110=ORIENTED_EDGE('',*,*,#95,.F.);
|
||
#111=ORIENTED_EDGE('',*,*,#98,.T.);
|
||
#112=ORIENTED_EDGE('',*,*,#56,.T.);
|
||
#113=ORIENTED_EDGE('',*,*,#79,.T.);
|
||
#114=ORIENTED_EDGE('',*,*,#91,.T.);
|
||
#115=ORIENTED_EDGE('',*,*,#90,.F.);
|
||
#116=ORIENTED_EDGE('',*,*,#96,.F.);
|
||
#117=ORIENTED_EDGE('',*,*,#92,.T.);
|
||
#118=ORIENTED_EDGE('',*,*,#97,.F.);
|
||
#119=ORIENTED_EDGE('',*,*,#54,.T.);
|
||
#120=ORIENTED_EDGE('',*,*,#93,.F.);
|
||
#121=ORIENTED_EDGE('',*,*,#46,.T.);
|
||
#122=ORIENTED_EDGE('',*,*,#60,.T.);
|
||
#123=ORIENTED_EDGE('',*,*,#99,.F.);
|
||
#130=EDGE_LOOP('',(#100,#101,#102,#103));
|
||
#131=EDGE_LOOP('',(#104,#105,#106,#107));
|
||
#132=EDGE_LOOP('',(#108,#109,#110,#112));
|
||
#133=EDGE_LOOP('',(#113,#114,#115,#116));
|
||
#134=EDGE_LOOP('',(#117,#118,#119,#120));
|
||
#135=EDGE_LOOP('',(#121,#122,#123,#111));
|
||
#140=FACE_OUTER_BOUND('',#130,.T.);
|
||
#141=FACE_OUTER_BOUND('',#131,.T.);
|
||
#142=FACE_OUTER_BOUND('',#132,.T.);
|
||
#143=FACE_OUTER_BOUND('',#133,.T.);
|
||
#144=FACE_OUTER_BOUND('',#134,.T.);
|
||
#145=FACE_OUTER_BOUND('',#135,.T.);
|
||
#150=ADVANCED_FACE('',(#140),#30,.T.);
|
||
#151=ADVANCED_FACE('',(#141),#31,.T.);
|
||
#152=ADVANCED_FACE('',(#142),#32,.T.);
|
||
#153=ADVANCED_FACE('',(#143),#33,.T.);
|
||
#154=ADVANCED_FACE('',(#144),#34,.T.);
|
||
#155=ADVANCED_FACE('',(#145),#35,.T.);
|
||
#160=CLOSED_SHELL('',(#150,#151,#152,#153,#154,#155));
|
||
#170=MANIFOLD_SOLID_BREP('box',#160);
|
||
)" + step_footer();
|
||
|
||
auto bodies = import_step_from_string(step);
|
||
EXPECT_EQ(step_last_error(), StepError::Ok);
|
||
|
||
ASSERT_GE(bodies.size(), 1u);
|
||
const auto& body = bodies[0];
|
||
EXPECT_TRUE(body.is_valid());
|
||
EXPECT_GE(body.num_faces(), 6u);
|
||
EXPECT_GE(body.num_edges(), 12u);
|
||
EXPECT_GE(body.num_vertices(), 8u);
|
||
EXPECT_EQ(body.num_bodies(), 1u);
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// Test: Simple box with CIRCLE edge (cylinder top/bottom face)
|
||
// ─────────────────────────────────────────────────────────────
|
||
|
||
TEST(StepImport, SimpleCylinder) {
|
||
// A simple cylinder: bottom circle + top circle + cylindrical side surface
|
||
std::string step = step_header() + R"(
|
||
#1=CARTESIAN_POINT('',(0.0,0.0,-2.0));
|
||
#2=CARTESIAN_POINT('',(0.0,0.0,2.0));
|
||
#3=CARTESIAN_POINT('',(1.0,0.0,-2.0));
|
||
#4=CARTESIAN_POINT('',(1.0,0.0,2.0));
|
||
#10=DIRECTION('',(0.0,0.0,1.0));
|
||
#11=DIRECTION('',(1.0,0.0,0.0));
|
||
#12=DIRECTION('',(0.0,1.0,0.0));
|
||
#20=AXIS2_PLACEMENT_3D('',#1,#10,#11);
|
||
#21=AXIS2_PLACEMENT_3D('',#2,#10,#11);
|
||
#30=PLANE('',#20);
|
||
#31=PLANE('',#21);
|
||
#40=CIRCLE('',#20,1.0);
|
||
#41=CIRCLE('',#21,1.0);
|
||
#50=EDGE_CURVE('',#80,#80,#40,.T.);
|
||
#51=EDGE_CURVE('',#81,#81,#41,.T.);
|
||
#60=LINE('',#3,#10);
|
||
#70=EDGE_CURVE('',#80,#81,#60,.T.);
|
||
#80=VERTEX_POINT('',#3);
|
||
#81=VERTEX_POINT('',#4);
|
||
#90=ORIENTED_EDGE('',*,*,#50,.T.);
|
||
#91=ORIENTED_EDGE('',*,*,#51,.F.);
|
||
#92=ORIENTED_EDGE('',*,*,#70,.T.);
|
||
#100=EDGE_LOOP('',(#90));
|
||
#101=EDGE_LOOP('',(#91));
|
||
#110=FACE_OUTER_BOUND('',#100,.T.);
|
||
#111=FACE_OUTER_BOUND('',#101,.T.);
|
||
#120=ADVANCED_FACE('',(#110),#30,.T.);
|
||
#121=ADVANCED_FACE('',(#111),#31,.T.);
|
||
#142=CYLINDRICAL_SURFACE('',#20,1.0);
|
||
#143=ADVANCED_FACE('',(#110),#142,.T.);
|
||
#150=CLOSED_SHELL('',(#120,#121,#143));
|
||
#160=MANIFOLD_SOLID_BREP('cylinder',#150);
|
||
)" + step_footer();
|
||
|
||
auto bodies = import_step_from_string(step);
|
||
|
||
ASSERT_GE(bodies.size(), 1u);
|
||
const auto& body = bodies[0];
|
||
EXPECT_TRUE(body.is_valid());
|
||
EXPECT_GE(body.num_faces(), 3u);
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// Test: Parse STEP with multiple bodies
|
||
// ─────────────────────────────────────────────────────────────
|
||
|
||
TEST(StepImport, MultipleBodies) {
|
||
// Two simple models: one circle-face body at origin, one at offset
|
||
std::string step = step_header() + R"(
|
||
#10=CARTESIAN_POINT('',(0.0,0.0,0.0));
|
||
#11=DIRECTION('',(0.0,0.0,1.0));
|
||
#12=DIRECTION('',(1.0,0.0,0.0));
|
||
#13=AXIS2_PLACEMENT_3D('',#10,#11,#12);
|
||
#14=CARTESIAN_POINT('',(5.0,0.0,0.0));
|
||
#15=VERTEX_POINT('',#14);
|
||
#16=CIRCLE('',#13,5.0);
|
||
#17=EDGE_CURVE('',#15,#15,#16,.T.);
|
||
#18=ORIENTED_EDGE('',*,*,#17,.T.);
|
||
#19=EDGE_LOOP('',(#18));
|
||
#20=FACE_OUTER_BOUND('',#19,.T.);
|
||
#21=PLANE('',#13);
|
||
#22=ADVANCED_FACE('',(#20),#21,.T.);
|
||
#23=CLOSED_SHELL('',(#22));
|
||
#24=MANIFOLD_SOLID_BREP('body1',#23);
|
||
#30=CARTESIAN_POINT('',(20.0,0.0,0.0));
|
||
#31=AXIS2_PLACEMENT_3D('',#30,#11,#12);
|
||
#32=CARTESIAN_POINT('',(23.0,0.0,0.0));
|
||
#33=VERTEX_POINT('',#32);
|
||
#34=CIRCLE('',#31,3.0);
|
||
#35=EDGE_CURVE('',#33,#33,#34,.T.);
|
||
#36=ORIENTED_EDGE('',*,*,#35,.T.);
|
||
#37=EDGE_LOOP('',(#36));
|
||
#38=FACE_OUTER_BOUND('',#37,.T.);
|
||
#39=PLANE('',#31);
|
||
#40=ADVANCED_FACE('',(#38),#39,.T.);
|
||
#41=CLOSED_SHELL('',(#40));
|
||
#42=MANIFOLD_SOLID_BREP('body2',#41);
|
||
)" + step_footer();
|
||
|
||
auto bodies = import_step_from_string(step);
|
||
EXPECT_EQ(step_last_error(), StepError::Ok);
|
||
|
||
ASSERT_GE(bodies.size(), 2u);
|
||
EXPECT_TRUE(bodies[0].is_valid());
|
||
EXPECT_TRUE(bodies[1].is_valid());
|
||
EXPECT_GE(bodies[0].num_faces(), 1u);
|
||
EXPECT_GE(bodies[1].num_faces(), 1u);
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// Test: Invalid input → graceful error
|
||
// ─────────────────────────────────────────────────────────────
|
||
|
||
TEST(StepImport, EmptyInput) {
|
||
auto bodies = import_step_from_string("");
|
||
EXPECT_NE(step_last_error(), StepError::Ok);
|
||
EXPECT_TRUE(bodies.empty());
|
||
}
|
||
|
||
TEST(StepImport, GarbageInput) {
|
||
auto bodies = import_step_from_string("this is not a step file at all");
|
||
EXPECT_NE(step_last_error(), StepError::Ok);
|
||
EXPECT_TRUE(bodies.empty());
|
||
}
|
||
|
||
TEST(StepImport, MissingEndsec) {
|
||
std::string step = step_header() + "#1=CARTESIAN_POINT('',(0,0,0));";
|
||
// Missing ENDSEC and footer
|
||
auto bodies = import_step_from_string(step);
|
||
// May or may not produce bodies depending on where it fails
|
||
// But should not crash
|
||
EXPECT_NO_THROW(import_step_from_string(step));
|
||
}
|
||
|
||
TEST(StepImport, OnlyHeader) {
|
||
std::string step = step_header() + step_footer();
|
||
auto bodies = import_step_from_string(step);
|
||
// Empty DATA section → no bodies
|
||
EXPECT_EQ(bodies.size(), 0u);
|
||
}
|
||
|
||
TEST(StepImport, MissingEntityId) {
|
||
std::string step = step_header() + "CARTESIAN_POINT('',(0,0,0));\n" + step_footer();
|
||
auto bodies = import_step_from_string(step);
|
||
EXPECT_NE(step_last_error(), StepError::Ok);
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// Test: Circle and ellipse curves
|
||
// ─────────────────────────────────────────────────────────────
|
||
|
||
TEST(StepImport, CircleCurve) {
|
||
std::string step = step_header() + R"(
|
||
#1=CARTESIAN_POINT('',(0.0,0.0,0.0));
|
||
#2=DIRECTION('',(0.0,0.0,1.0));
|
||
#3=DIRECTION('',(1.0,0.0,0.0));
|
||
#4=AXIS2_PLACEMENT_3D('',#1,#2,#3);
|
||
#5=CARTESIAN_POINT('',(5.0,0.0,0.0));
|
||
#6=VERTEX_POINT('',#5);
|
||
#7=CIRCLE('',#4,5.0);
|
||
#8=EDGE_CURVE('',#6,#6,#7,.T.);
|
||
#9=ORIENTED_EDGE('',*,*,#8,.T.);
|
||
#10=EDGE_LOOP('',(#9));
|
||
#11=FACE_OUTER_BOUND('',#10,.T.);
|
||
#12=PLANE('',#4);
|
||
#13=ADVANCED_FACE('',(#11),#12,.T.);
|
||
#14=CLOSED_SHELL('',(#13));
|
||
#15=MANIFOLD_SOLID_BREP('circle_test',#14);
|
||
)" + step_footer();
|
||
|
||
auto bodies = import_step_from_string(step);
|
||
ASSERT_GE(bodies.size(), 1u);
|
||
EXPECT_TRUE(bodies[0].is_valid());
|
||
EXPECT_GE(bodies[0].num_vertices(), 1u);
|
||
}
|
||
|
||
TEST(StepImport, EllipseCurve) {
|
||
std::string step = step_header() + R"(
|
||
#1=CARTESIAN_POINT('',(0.0,0.0,0.0));
|
||
#2=DIRECTION('',(0.0,0.0,1.0));
|
||
#3=DIRECTION('',(1.0,0.0,0.0));
|
||
#4=AXIS2_PLACEMENT_3D('',#1,#2,#3);
|
||
#5=CARTESIAN_POINT('',(3.0,0.0,0.0));
|
||
#6=VERTEX_POINT('',#5);
|
||
#7=ELLIPSE('',#4,3.0,1.0);
|
||
#8=EDGE_CURVE('',#6,#6,#7,.T.);
|
||
#9=ORIENTED_EDGE('',*,*,#8,.T.);
|
||
#10=EDGE_LOOP('',(#9));
|
||
#11=FACE_OUTER_BOUND('',#10,.T.);
|
||
#12=PLANE('',#4);
|
||
#13=ADVANCED_FACE('',(#11),#12,.T.);
|
||
#14=CLOSED_SHELL('',(#13));
|
||
#15=MANIFOLD_SOLID_BREP('ellipse_test',#14);
|
||
)" + step_footer();
|
||
|
||
auto bodies = import_step_from_string(step);
|
||
ASSERT_GE(bodies.size(), 1u);
|
||
EXPECT_TRUE(bodies[0].is_valid());
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// Test: STEP surfaces
|
||
// ─────────────────────────────────────────────────────────────
|
||
|
||
TEST(StepImport, SphericalSurface) {
|
||
std::string step = step_header() + R"(
|
||
#1=CARTESIAN_POINT('',(0.0,0.0,0.0));
|
||
#2=CARTESIAN_POINT('',(1.0,0.0,0.0));
|
||
#3=DIRECTION('',(0.0,0.0,1.0));
|
||
#4=DIRECTION('',(1.0,0.0,0.0));
|
||
#5=AXIS2_PLACEMENT_3D('',#1,#3,#4);
|
||
#6=VERTEX_POINT('',#2);
|
||
#7=SPHERICAL_SURFACE('',#5,5.0);
|
||
#8=CIRCLE('',#5,5.0);
|
||
#9=EDGE_CURVE('',#6,#6,#8,.T.);
|
||
#10=ORIENTED_EDGE('',*,*,#9,.T.);
|
||
#11=EDGE_LOOP('',(#10));
|
||
#12=FACE_OUTER_BOUND('',#11,.T.);
|
||
#13=ADVANCED_FACE('',(#12),#7,.T.);
|
||
#14=CLOSED_SHELL('',(#13));
|
||
#15=MANIFOLD_SOLID_BREP('sphere',#14);
|
||
)" + step_footer();
|
||
|
||
auto bodies = import_step_from_string(step);
|
||
ASSERT_GE(bodies.size(), 1u);
|
||
EXPECT_TRUE(bodies[0].is_valid());
|
||
EXPECT_GE(bodies[0].num_faces(), 1u);
|
||
}
|
||
|
||
TEST(StepImport, ToroidalSurface) {
|
||
std::string step = step_header() + R"(
|
||
#1=CARTESIAN_POINT('',(0.0,0.0,0.0));
|
||
#2=DIRECTION('',(0.0,0.0,1.0));
|
||
#3=DIRECTION('',(1.0,0.0,0.0));
|
||
#4=AXIS2_PLACEMENT_3D('',#1,#2,#3);
|
||
#5=CARTESIAN_POINT('',(8.0,0.0,0.0));
|
||
#6=VERTEX_POINT('',#5);
|
||
#7=TOROIDAL_SURFACE('',#4,5.0,2.0);
|
||
#8=CIRCLE('',#4,5.0);
|
||
#9=EDGE_CURVE('',#6,#6,#8,.T.);
|
||
#10=ORIENTED_EDGE('',*,*,#9,.T.);
|
||
#11=EDGE_LOOP('',(#10));
|
||
#12=FACE_OUTER_BOUND('',#11,.T.);
|
||
#13=ADVANCED_FACE('',(#12),#7,.T.);
|
||
#14=CLOSED_SHELL('',(#13));
|
||
#15=MANIFOLD_SOLID_BREP('torus',#14);
|
||
)" + step_footer();
|
||
|
||
auto bodies = import_step_from_string(step);
|
||
ASSERT_GE(bodies.size(), 1u);
|
||
EXPECT_TRUE(bodies[0].is_valid());
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// Test: B_SPLINE_CURVE and B_SPLINE_SURFACE
|
||
// ─────────────────────────────────────────────────────────────
|
||
|
||
TEST(StepImport, BSplineCurve) {
|
||
std::string step = step_header() + R"(
|
||
#1=CARTESIAN_POINT('',(0.0,0.0,0.0));
|
||
#2=CARTESIAN_POINT('',(1.0,2.0,0.0));
|
||
#3=CARTESIAN_POINT('',(3.0,1.0,0.0));
|
||
#4=CARTESIAN_POINT('',(4.0,0.0,0.0));
|
||
#10=B_SPLINE_CURVE_WITH_KNOTS('',3,(#1,#2,#3,#4),.UNSPECIFIED.,.F.,.F.,(4,1,1,4),(0.0,0.25,0.75,1.0),.PIECEWISE_BEZIER_KNOTS.);
|
||
#11=CARTESIAN_POINT('',(0.0,0.0,0.0));
|
||
#12=CARTESIAN_POINT('',(4.0,0.0,0.0));
|
||
#20=VERTEX_POINT('',#11);
|
||
#21=VERTEX_POINT('',#12);
|
||
#30=EDGE_CURVE('',#20,#21,#10,.T.);
|
||
#40=LINE('',#11,#12);
|
||
#41=EDGE_CURVE('',#21,#20,#40,.T.);
|
||
#50=ORIENTED_EDGE('',*,*,#30,.T.);
|
||
#51=ORIENTED_EDGE('',*,*,#41,.T.);
|
||
#60=EDGE_LOOP('',(#50,#51));
|
||
#61=FACE_OUTER_BOUND('',#60,.T.);
|
||
#70=DIRECTION('',(0.0,0.0,1.0));
|
||
#71=DIRECTION('',(1.0,0.0,0.0));
|
||
#72=AXIS2_PLACEMENT_3D('',#11,#70,#71);
|
||
#73=PLANE('',#72);
|
||
#80=ADVANCED_FACE('',(#61),#73,.T.);
|
||
#90=CLOSED_SHELL('',(#80));
|
||
#100=MANIFOLD_SOLID_BREP('bspline_curve',#90);
|
||
)" + step_footer();
|
||
|
||
auto bodies = import_step_from_string(step);
|
||
ASSERT_GE(bodies.size(), 1u);
|
||
EXPECT_TRUE(bodies[0].is_valid());
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// Test: Round-trip (create → export is not available, but we
|
||
// can test creating a BrepModel programmatically and compare)
|
||
// ─────────────────────────────────────────────────────────────
|
||
|
||
TEST(StepImport, ProgrammaticBrepCanBeUsed) {
|
||
auto box = make_box(2.0, 2.0, 2.0);
|
||
EXPECT_TRUE(box.is_valid());
|
||
|
||
// Verify the box can be tessellated
|
||
auto mesh = box.to_mesh();
|
||
EXPECT_GT(mesh.num_faces(), 0u);
|
||
|
||
// Verify face and edge queries work after import
|
||
auto edges = box.face_edges(0);
|
||
EXPECT_FALSE(edges.empty());
|
||
|
||
auto efs = box.edge_faces(0);
|
||
EXPECT_FALSE(efs.empty());
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// Test: String escaping in STEP
|
||
// ─────────────────────────────────────────────────────────────
|
||
|
||
TEST(StepImport, StringEscaping) {
|
||
std::string step = step_header() + R"(
|
||
#1=CARTESIAN_POINT('name with spaces',(1.0,2.0,3.0));
|
||
#2=CARTESIAN_POINT('it''s escaped',(4.0,5.0,6.0));
|
||
)" + step_footer();
|
||
|
||
auto bodies = import_step_from_string(step);
|
||
// No bodies (no topology) but should not crash
|
||
EXPECT_EQ(bodies.size(), 0u);
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// Test: Entities with omitted parameters ($)
|
||
// ─────────────────────────────────────────────────────────────
|
||
|
||
TEST(StepImport, OmittedParameters) {
|
||
std::string step = step_header() + R"(
|
||
#1=CARTESIAN_POINT('',(0.0,0.0,0.0));
|
||
#2=DIRECTION('',(0.0,0.0,1.0));
|
||
#3=AXIS2_PLACEMENT_3D('',#1,#2,$);
|
||
#4=CARTESIAN_POINT('',(5.0,0.0,0.0));
|
||
#5=VERTEX_POINT('',#4);
|
||
#6=CIRCLE('',#3,5.0);
|
||
#7=EDGE_CURVE('',#5,#5,#6,.T.);
|
||
#8=ORIENTED_EDGE('',*,*,#7,.T.);
|
||
#9=EDGE_LOOP('',(#8));
|
||
#10=FACE_OUTER_BOUND('',#9,.T.);
|
||
#11=PLANE('',#3);
|
||
#12=ADVANCED_FACE('',(#10),#11,.T.);
|
||
#13=CLOSED_SHELL('',(#12));
|
||
#14=MANIFOLD_SOLID_BREP('omitted_test',#13);
|
||
)" + step_footer();
|
||
|
||
auto bodies = import_step_from_string(step);
|
||
ASSERT_GE(bodies.size(), 1u);
|
||
EXPECT_TRUE(bodies[0].is_valid());
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// Test: STEP file with comments
|
||
// ─────────────────────────────────────────────────────────────
|
||
|
||
TEST(StepImport, Comments) {
|
||
std::string step = step_header() + R"(
|
||
/* This is a comment block */
|
||
#1=CARTESIAN_POINT('',(0.0,0.0,0.0)); /* inline comment */
|
||
#2=DIRECTION('',(0.0,0.0,1.0));
|
||
#3=AXIS2_PLACEMENT_3D('',#1,#2,$);
|
||
#4=CARTESIAN_POINT('',(5.0,0.0,0.0));
|
||
#5=VERTEX_POINT('',#4);
|
||
#6=CIRCLE('',#3,5.0);
|
||
#7=EDGE_CURVE('',#5,#5,#6,.T.);
|
||
#8=ORIENTED_EDGE('',*,*,#7,.T.);
|
||
#9=EDGE_LOOP('',(#8));
|
||
#10=FACE_OUTER_BOUND('',#9,.T.);
|
||
#11=PLANE('',#3);
|
||
#12=ADVANCED_FACE('',(#10),#11,.T.);
|
||
#13=CLOSED_SHELL('',(#12));
|
||
#14=MANIFOLD_SOLID_BREP('commented',#13);
|
||
)" + step_footer();
|
||
|
||
auto bodies = import_step_from_string(step);
|
||
ASSERT_GE(bodies.size(), 1u);
|
||
EXPECT_TRUE(bodies[0].is_valid());
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// Test: Multi-line entities
|
||
// ─────────────────────────────────────────────────────────────
|
||
|
||
TEST(StepImport, MultiLineEntities) {
|
||
std::string step = step_header() + R"(
|
||
#1=CARTESIAN_POINT('',
|
||
(0.0,0.0,0.0));
|
||
#2=CARTESIAN_POINT('',(
|
||
5.0,0.0,0.0));
|
||
#3=DIRECTION('',
|
||
(0.0,0.0,1.0));
|
||
#4=AXIS2_PLACEMENT_3D('point',
|
||
#1,#3,$);
|
||
#5=VERTEX_POINT('',#2);
|
||
#6=CIRCLE('round',#4,5.0);
|
||
#7=EDGE_CURVE('edge',
|
||
#5,#5,#6,.T.);
|
||
#8=ORIENTED_EDGE('',*,*,#7,.T.);
|
||
#9=EDGE_LOOP('',(#8));
|
||
#10=FACE_OUTER_BOUND('',#9,.T.);
|
||
#11=PLANE('flat',#4);
|
||
#12=ADVANCED_FACE('face',(#10),#11,.T.);
|
||
#13=CLOSED_SHELL('shell',(#12));
|
||
#14=MANIFOLD_SOLID_BREP('solid',#13);
|
||
)" + step_footer();
|
||
|
||
auto bodies = import_step_from_string(step);
|
||
ASSERT_GE(bodies.size(), 1u);
|
||
EXPECT_TRUE(bodies[0].is_valid());
|
||
}
|
||
|
||
// ─────────────────────────────────────────────────────────────
|
||
// Test: SHELL_BASED_SURFACE_MODEL (alternative to MANIFOLD_SOLID_BREP)
|
||
// ─────────────────────────────────────────────────────────────
|
||
|
||
TEST(StepImport, ShellBasedSurfaceModel) {
|
||
std::string step = step_header() + R"(
|
||
#1=CARTESIAN_POINT('',(0.0,0.0,0.0));
|
||
#2=DIRECTION('',(0.0,0.0,1.0));
|
||
#3=AXIS2_PLACEMENT_3D('',#1,#2,$);
|
||
#4=CARTESIAN_POINT('',(3.0,0.0,0.0));
|
||
#5=VERTEX_POINT('',#4);
|
||
#6=CIRCLE('',#3,3.0);
|
||
#7=EDGE_CURVE('',#5,#5,#6,.T.);
|
||
#8=ORIENTED_EDGE('',*,*,#7,.T.);
|
||
#9=EDGE_LOOP('',(#8));
|
||
#10=FACE_OUTER_BOUND('',#9,.T.);
|
||
#11=PLANE('',#3);
|
||
#12=ADVANCED_FACE('',(#10),#11,.T.);
|
||
#13=CLOSED_SHELL('',(#12));
|
||
#14=SHELL_BASED_SURFACE_MODEL('',(#13));
|
||
)" + step_footer();
|
||
|
||
auto bodies = import_step_from_string(step);
|
||
ASSERT_GE(bodies.size(), 1u);
|
||
EXPECT_TRUE(bodies[0].is_valid());
|
||
EXPECT_GE(bodies[0].num_faces(), 1u);
|
||
}
|