29 #define _unused(x) ((void)(x)) 31 #include "SUAPI-CppWrapper/model/Loop.hpp" 33 #include "SUAPI-CppWrapper/model/LoopInput.hpp" 34 #include "SUAPI-CppWrapper/model/Vertex.hpp" 35 #include "SUAPI-CppWrapper/model/Edge.hpp" 36 #include "SUAPI-CppWrapper/model/Material.hpp" 37 #include "SUAPI-CppWrapper/model/Layer.hpp" 52 Entity(SULoopToEntity(loop),
true)
75 throw std::logic_error(
"CW::Loop::loop_input(): Loop is null");
78 std::vector<InputEdgeProperties> edge_properties;
79 edge_properties.reserve(edges.size());
80 for (
size_t i=0; i < edges.size(); i++) {
82 edge_prop.hidden = edges[i].hidden();
83 edge_prop.soft = edges[i].soft();
84 edge_prop.smooth = edges[i].smooth();
85 edge_prop.material = edges[i].material();
86 edge_prop.layer = edges[i].layer();
87 edge_properties.push_back(edge_prop);
95 throw std::logic_error(
"CW::Loop::edges(): Loop is null");
98 SUResult res = SULoopGetNumVertices(this->
ref(), &count);
99 assert(res == SU_ERROR_NONE);
100 std::vector<SUEdgeRef> edge_refs(count, SU_INVALID);
101 res = SULoopGetEdges(this->
ref(), count, edge_refs.data(), &count);
102 assert(res == SU_ERROR_NONE); _unused(res);
103 std::vector<Edge>
edges(count);
104 std::transform(edge_refs.begin(), edge_refs.end(), edges.begin(),
105 [](
const SUEdgeRef& value){
114 throw std::logic_error(
"CW::Loop::vertices(): Loop is null");
117 SUResult res = SULoopGetNumVertices(this->
ref(), &count);
118 assert(res == SU_ERROR_NONE);
119 std::vector<SUVertexRef> verts_array(count, SU_INVALID);
120 res = SULoopGetVertices(this->
ref(), count, verts_array.data(), &count);
121 assert(res == SU_ERROR_NONE); _unused(res);
122 std::vector<Vertex>
vertices(count);
123 std::transform(verts_array.begin(), verts_array.end(), vertices.begin(),
124 [](
const SUVertexRef& value){
133 throw std::logic_error(
"CW::Loop::points(): Loop is null");
135 std::vector<Vertex> verts =
vertices();
136 std::vector<Point3D>
points;
137 points.reserve(verts.size());
138 for (
size_t i=0; i < verts.size(); ++i) {
139 points.push_back(verts[i].position());
147 throw std::logic_error(
"CW::Loop::classify_point(): Loop is null");
150 throw std::invalid_argument(
"CW::Loop::classify_point(): Point3D given is null");
158 throw std::logic_error(
"CW::Loop::size(): Loop is null");
161 SUResult res = SULoopGetNumVertices(this->
ref(), &count);
162 assert(res == SU_ERROR_NONE); _unused(res);
168 if(loop_points.size() < 3) {
169 throw std::invalid_argument(
"CW::Loop::classify_point(): Fewer than 3 points given - not a valid loop.");
172 throw std::invalid_argument(
"CW::Loop::classify_point(): Point3D given is null");
178 throw std::invalid_argument(
"CW::Loop::classify_point(): Points given does not form a valid loop.");
180 else if (!loop_plane.
on_plane(test_point)) {
181 return PointLoopClassify::PointNotOnPlane;
184 for (
size_t i=0; i < loop_points.size(); i++) {
185 if (loop_points[i] == test_point) {
186 return PointLoopClassify::PointOnVertex;
190 for (
size_t i=0; i < loop_points.size(); i++) {
192 if (i == loop_points.size()-1) {
193 next_point = loop_points[0];
196 next_point = loop_points[i+1];
199 return PointLoopClassify::PointOnEdge;
206 assert(loop_points[0] != loop_points[1]);
213 std::vector<LoopPoint> red_loop_points;
214 red_loop_points.reserve(loop_points.size());
215 for (
size_t i=0; i < loop_points.size(); i++) {
217 if (i == loop_points.size()-1) {
218 next_point = loop_points[0];
220 next_point = loop_points[i+1];
222 Vector3D next_vector = next_point - loop_points[i];
223 if (next_vector.unit() != ray.unit() && next_vector.unit() != -ray.unit()) {
224 red_loop_points.push_back(LoopPoint{loop_points[i], next_vector});
228 size_t num_intersections = 0;
229 for (
size_t i=0; i < red_loop_points.size(); i++) {
231 if (!!intersection) {
233 if (intersection == red_loop_points[i].point) {
235 LoopPoint prev_point;
237 prev_point = red_loop_points[red_loop_points.size()-1];
240 prev_point = red_loop_points[i-1];
243 Vector3D next_cross = ray.
cross(red_loop_points[i].vector_to_next);
244 assert(fabs(next_cross.length()) > Vector3D::EPSILON);
245 if (prev_cross.unit() != next_cross.unit()) {
255 if (num_intersections % 2 == 0) {
257 return PointLoopClassify::PointOutside;
260 return PointLoopClassify::PointInside;
266 SUResult res = SULoopIsOuterLoop(this->
ref(), &is_outer);
267 assert(res == SU_ERROR_NONE); _unused(res);
bool m_attached
Indicates whether the Entity has been attached to a model.
static Point3D ray_line_intersection(const Point3D &point_a, const Vector3D &vector_a, const Point3D &point_b, const Vector3D &ray_b, bool return_colinear=false)
std::vector< Edge > edges() const
Entity()
Constructor representing a null objject.
static bool on_line_segment(const Point3D &point_a, const Point3D &point_b, const Point3D &test_point)
Loop & operator=(const Loop &other)
SUEntityRef m_entity
The C SUEntityRef that this class wraps.
std::vector< Point3D > points() const
PointLoopClassify classify_point(const Point3D &point) const
bool on_plane(const Point3D &point) const
Vector3D cross(const Vector3D &vector2) const
std::vector< Vertex > vertices() const
bool is_outer_loop() const
static Plane3D plane_from_loop(const std::vector< Point3D > &loop_points)