29 #define _unused(x) ((void)(x)) 34 #include <SketchUpAPI/model/edge.h> 36 #include "SUAPI-CppWrapper/model/Face.hpp" 38 #include "SUAPI-CppWrapper/Geometry.hpp" 39 #include "SUAPI-CppWrapper/model/Material.hpp" 40 #include "SUAPI-CppWrapper/model/Vertex.hpp" 41 #include "SUAPI-CppWrapper/model/Edge.hpp" 42 #include "SUAPI-CppWrapper/model/Loop.hpp" 43 #include "SUAPI-CppWrapper/model/LoopInput.hpp" 50 SUFaceRef Face::create_face(std::vector<Point3D>& outer_points) {
52 for (
size_t i=0; i < outer_points.size(); ++i) {
53 loop_input.add_vertex_index(i);
55 return create_face(outer_points, loop_input);
59 SUFaceRef Face::create_face(std::vector<Point3D>& outer_points, LoopInput& loop_input) {
60 SUFaceRef face = SU_INVALID;
61 SULoopInputRef loop_input_ref = loop_input.ref();
62 std::vector<SUPoint3D> su_points(outer_points.size());
63 std::transform(outer_points.begin(), outer_points.end(), su_points.begin(),
64 [](
const Point3D& value){
65 return (SUPoint3D)value;
67 SUResult res = SUFaceCreate(&face, su_points.data(), &loop_input_ref);
68 if (res != SU_ERROR_NONE) {
72 loop_input.m_attached =
true;
77 SUFaceRef Face::copy_reference(
const Face& other) {
78 if (other.m_attached || !other) {
82 Loop other_outer_loop = other.outer_loop();
83 std::vector<Point3D> other_outer_points = other_outer_loop.points();
84 LoopInput outer_loop_input = other_outer_loop.loop_input();
85 SUFaceRef new_face = create_face(other_outer_points, outer_loop_input);
99 Face(create_face(outer_loop),
false)
104 Face(create_face(outer_loop, loop_input),
false)
115 DrawingElement(other, SUFaceToDrawingElement(copy_reference(other)))
129 this->back_material(other.back_material());
136 SUFaceRef face = this->ref();
137 SUResult res = SUFaceRelease(&face);
138 assert(res == SU_ERROR_NONE); _unused(res);
148 SUFaceRef face = this->ref();
149 SUResult res = SUFaceRelease(&face);
150 assert(res == SU_ERROR_NONE); _unused(res);
152 m_entity = SUFaceToEntity(copy_reference(other));
154 this->back_material(other.back_material());
162 SUFaceRef Face::ref()
const {
return SUFaceFromEntity(
m_entity); }
165 Face::operator SUFaceRef()
const {
return this->ref();}
176 double Face::area()
const {
178 throw std::logic_error(
"CW::Face::area(): Face is null");
181 SUResult res = SUFaceGetArea(this->ref(), &area);
182 assert(res == SU_ERROR_NONE); _unused(res);
189 throw std::logic_error(
"CW::Face::add_inner_loop(): Face is null");
191 if (points.size() != loop_input.m_edge_num) {
192 throw std::invalid_argument(
"CW::Face::add_inner_loop(): Unequal number of vertices between given Point3D vector and LoopInput object");
194 SUResult res = SUFaceAddInnerLoop(this->ref(), points[0], loop_input);
195 if (res == SU_ERROR_INVALID_INPUT) {
196 throw std::invalid_argument(
"CW::Face::add_inner_loop(): Arguments are invalid");
198 assert(res == SU_ERROR_NONE); _unused(res);
202 Material Face::back_material()
const {
204 throw std::logic_error(
"CW::Face::back_material(): Face is null");
206 SUMaterialRef material = SU_INVALID;
207 SUResult res = SUFaceGetBackMaterial(this->ref(), &material);
208 if (res == SU_ERROR_NO_DATA) {
211 assert(res == SU_ERROR_NONE); _unused(res);
218 throw std::logic_error(
"CW::Face::back_material(): Face is null");
220 SUResult res = SUFaceSetBackMaterial(this->ref(), material.ref());
221 assert(res == SU_ERROR_NONE); _unused(res);
236 FacePointClass Face::classify_point(
const Point3D& point) {
238 throw std::logic_error(
"CW::Face::classify_point(): Face is null");
241 throw std::invalid_argument(
"CW::Face::classify_point(): Given Point3D object is null");
243 Loop outer_loop = this->outer_loop();
245 switch (outer_class) {
246 case (PointLoopClassify::PointUnknown):
247 return FacePointClass::PointUnknown;
248 case (PointLoopClassify::PointNotOnPlane):
249 return FacePointClass::PointNotOnPlane;
250 case (PointLoopClassify::PointOnEdge):
251 return FacePointClass::PointOnEdge;
252 case (PointLoopClassify::PointOnVertex):
253 return FacePointClass::PointOnVertex;
254 case (PointLoopClassify::PointOutside):
255 return FacePointClass::PointOutside;
256 case (PointLoopClassify::PointInside): {
258 for (
size_t i=0; i < inner_loops.size(); i++) {
259 PointLoopClassify inner_class = inner_loops[i].classify_point(point);
260 switch (inner_class) {
261 case (PointLoopClassify::PointOnEdge):
262 return FacePointClass::PointOnEdge;
263 case (PointLoopClassify::PointOnVertex):
264 return FacePointClass::PointOnVertex;
265 case (PointLoopClassify::PointOutside):
267 case (PointLoopClassify::PointInside):
268 return FacePointClass::PointOutside;
270 case (PointLoopClassify::PointNotOnPlane):
271 case (PointLoopClassify::PointUnknown):
275 return FacePointClass::PointOutside;
278 return FacePointClass::PointUnknown;
282 std::vector<Edge> Face::edges() {
284 throw std::logic_error(
"CW::Face::edges(): Face is null");
286 std::vector<Edge> total_edges = outer_loop().edges();
287 std::vector<Loop> all_loops = loops();
288 size_t total_edge_num = 0;
289 for (
size_t i=0; i < all_loops.size(); i++) {
290 total_edge_num += all_loops[i].size();
292 total_edges.reserve(total_edge_num);
293 for (
size_t i=0; i < all_loops.size(); i++) {
294 std::vector<Edge> loop_edges = all_loops[i].edges();
295 total_edges.insert(total_edges.end(), loop_edges.begin(), loop_edges.end());
317 throw std::logic_error(
"CW::Face::inner_loops(): Face is null");
319 size_t num_loops = 0;
320 SUFaceGetNumInnerLoops(this->ref(), &num_loops);
321 std::vector<SULoopRef>
inner_loops(num_loops, SU_INVALID);
322 SUFaceGetInnerLoops(this->ref(), num_loops, inner_loops.data(), &num_loops);
323 std::vector<Loop> loops(num_loops);
324 std::transform(inner_loops.begin(), inner_loops.end(), loops.begin(),
325 [](
const SULoopRef& value){
332 std::vector<Loop> Face::loops()
const {
334 throw std::logic_error(
"CW::Face::loops(): Face is null");
336 std::vector<Loop> all_loops;
337 all_loops.push_back(outer_loop());
339 all_loops.reserve(all_loops.size() + inner_ls.size());
340 all_loops.insert(all_loops.end(), inner_ls.begin(), inner_ls.end());
352 throw std::logic_error(
"CW::Face::normal(): Face is null");
359 Loop Face::outer_loop()
const {
361 throw std::logic_error(
"CW::Face::outer_loop(): Face is null");
363 SULoopRef lp = SU_INVALID;
364 SUResult res = SUFaceGetOuterLoop(this->ref(), &lp);
365 assert(res == SU_ERROR_NONE); _unused(res);
372 throw std::logic_error(
"CW::Face::plane(): Face is null");
374 SUPlane3D plane = SU_INVALID;
375 SUFaceGetPlane(this->ref(), &plane);
386 throw std::logic_error(
"CW::Face::reverse(): Face is null");
388 SUResult res = SUFaceReverse(this->ref());
389 assert(res == SU_ERROR_NONE); _unused(res);
410 throw std::logic_error(
"CW::Face::vertices(): Face is null");
412 size_t num_vertices = 0;
413 SUFaceGetNumVertices(this->ref(), &num_vertices);
414 std::vector<SUVertexRef> vertex_refs(num_vertices, SU_INVALID);
415 SUFaceGetVertices(this->ref(), num_vertices, vertex_refs.data(), &num_vertices);
416 std::vector<Vertex>
vertices(num_vertices);
417 std::transform(vertex_refs.begin(), vertex_refs.end(), vertices.begin(),
418 [](
const SUVertexRef& value){
bool m_attached
Indicates whether the Entity has been attached to a model.
bool attached() const
Returns true if the entity is attached to another object.
void add_inner_loop(std::vector< Point3D > &points, LoopInput &loop_input)
std::vector< Loop > inner_loops() const
DrawingElement & operator=(const DrawingElement &other)
SUEntityRef m_entity
The C SUEntityRef that this class wraps.
Face & operator=(const Face &other)
PointLoopClassify classify_point(const Point3D &point) const
std::vector< Vertex > vertices() const