@@ -594,3 +594,160 @@ void ifcopenshell::geometry::taxonomy::extrusion::print(std::ostream& o, int ind
594594 direction->print (o, indent + 4 );
595595 basis->print (o, indent + 4 );
596596}
597+
598+ boost::optional<face::ptr> ifcopenshell::geometry::taxonomy::loop_to_face_upgrade_impl (ptr item) {
599+ boost::optional<face::ptr> face_;
600+ auto loop_ = dcast<loop>(item);
601+ if (loop_) {
602+ loop_->external = true ;
603+
604+ face_ = make<face>();
605+ (*face_)->instance = loop_->instance ;
606+ (*face_)->matrix = loop_->matrix ;
607+ (*face_)->children = { clone (loop_) };
608+ }
609+ return face_;
610+ }
611+
612+ boost::optional<edge::ptr> ifcopenshell::geometry::taxonomy::curve_to_edge_upgrade_impl (ptr item) {
613+ boost::optional<edge::ptr> edge_;
614+ auto circle_ = dcast<circle>(item);
615+ auto ellipse_ = dcast<ellipse>(item);
616+ auto line_ = dcast<line>(item);
617+ auto bspline_curve_ = dcast<bspline_curve>(item);
618+ if (circle_ || ellipse_ || line_ || bspline_curve_) {
619+ edge_ = make<edge>();
620+ if (circle_) {
621+ (*edge_)->basis = circle_;
622+ (*edge_)->instance = circle_->instance ;
623+ } else if (ellipse_) {
624+ (*edge_)->basis = ellipse_;
625+ (*edge_)->instance = ellipse_->instance ;
626+ } else if (line_) {
627+ (*edge_)->basis = line_;
628+ (*edge_)->instance = line_->instance ;
629+ } else if (bspline_curve_) {
630+ (*edge_)->basis = bspline_curve_;
631+ (*edge_)->instance = bspline_curve_->instance ;
632+ }
633+
634+ if (circle_ || ellipse_) {
635+ // @todo
636+ (*edge_)->start = 0 .;
637+ (*edge_)->end = 2 * boost::math::constants::pi<double >();
638+ }
639+ }
640+ return edge_;
641+ }
642+
643+ boost::optional<loop::ptr> ifcopenshell::geometry::taxonomy::curve_to_loop_upgrade_impl (ptr item) {
644+ boost::optional<loop::ptr> loop_;
645+ auto circle_ = dcast<circle>(item);
646+ auto ellipse_ = dcast<ellipse>(item);
647+ auto line_ = dcast<line>(item);
648+ auto bspline_curve_ = dcast<bspline_curve>(item);
649+ if (circle_ || ellipse_ || line_ || bspline_curve_) {
650+ auto edge_ = make<edge>();
651+ if (circle_) {
652+ edge_->basis = circle_;
653+ } else if (ellipse_) {
654+ edge_->basis = ellipse_;
655+ } else if (line_) {
656+ edge_->basis = line_;
657+ } else if (bspline_curve_) {
658+ edge_->basis = bspline_curve_;
659+ }
660+
661+ if (circle_ || ellipse_) {
662+ // @todo
663+ edge_->start = 0 .;
664+ edge_->end = 2 * boost::math::constants::pi<double >();
665+ }
666+
667+ loop_ = make<loop>();
668+ (*loop_)->children .push_back (edge_);
669+ }
670+ return loop_;
671+ }
672+
673+ boost::optional<loop::ptr> ifcopenshell::geometry::taxonomy::edge_to_loop_upgrade_impl (ptr item) {
674+ boost::optional<loop::ptr> loop_;
675+ auto edge_ = dcast<edge>(item);
676+ if (edge_) {
677+ loop_ = make<loop>();
678+ (*loop_)->children .push_back (edge_);
679+ }
680+ return loop_;
681+ }
682+
683+ boost::optional<face::ptr> ifcopenshell::geometry::taxonomy::curve_to_face_upgrade_impl (ptr item) {
684+ boost::optional<face::ptr> face_;
685+ auto circle_ = dcast<circle>(item);
686+ auto ellipse_ = dcast<ellipse>(item);
687+ auto line_ = dcast<line>(item);
688+ auto bspline_curve_ = dcast<bspline_curve>(item);
689+
690+ if (circle_ || ellipse_ || line_ || bspline_curve_) {
691+ auto edge_ = make<edge>();
692+ if (circle_) {
693+ edge_->basis = circle_;
694+ } else if (ellipse_) {
695+ edge_->basis = ellipse_;
696+ } else if (line_) {
697+ edge_->basis = line_;
698+ } else if (bspline_curve_) {
699+ edge_->basis = bspline_curve_;
700+ }
701+
702+ if (circle_ || ellipse_) {
703+ // @todo
704+ edge_->start = 0 .;
705+ edge_->end = 2 * boost::math::constants::pi<double >();
706+ }
707+
708+ auto loop_ = make<loop>();
709+ loop_->children .push_back (edge_);
710+
711+ face_ = make<face>();
712+ (*face_)->instance = loop_->instance ;
713+ (*face_)->matrix = loop_->matrix ;
714+ (*face_)->children = { clone (loop_) };
715+ }
716+ return face_;
717+ }
718+
719+
720+ boost::optional<piecewise_function::ptr> ifcopenshell::geometry::taxonomy::loop_to_piecewise_function_upgrade_impl (ptr item) {
721+ boost::optional<piecewise_function::ptr> pwf_;
722+ auto loop_ = dcast<loop>(item);
723+ if (loop_) {
724+ if (loop_->pwf .is_initialized ()) {
725+ pwf_ = loop_->pwf ;
726+ } else {
727+ piecewise_function::spans_t spans;
728+ spans.reserve (loop_->children .size ());
729+ for (auto & edge_ : loop_->children ) {
730+ // the edge could be an arc or trimmed circle in the case of IfcIndexPolyCurve - support for this isn't implemented yet
731+ if (edge_->basis ) {
732+ Logger::Message (Logger::Severity::LOG_NOTICE, " Shape of basis curve ignored - edge is treated as a straight line edge" );
733+ }
734+
735+ const auto & s = boost::get<point3::ptr>(edge_->start )->ccomponents ();
736+ const auto & e = boost::get<point3::ptr>(edge_->end )->ccomponents ();
737+ Eigen::Vector3d v = e - s;
738+ auto l = v.norm (); // the norm of a vector is a measure of its length
739+ v.normalize (); // normalize the vector so that it is a unit direction vector
740+ std::function<Eigen::Matrix4d (double )> fn = [s, v](double u) {
741+ Eigen::Vector3d o (s + u * v), axis (0 , 0 , 1 ), refDirection (v);
742+ auto Y = axis.cross (refDirection).normalized ();
743+ axis = refDirection.cross (Y).normalized ();
744+ return make<matrix4>(o, axis, refDirection)->components ();
745+ };
746+ spans.emplace_back (l, fn);
747+ }
748+ pwf_ = make<piecewise_function>(0.0 ,spans);
749+ loop_->pwf = pwf_;
750+ }
751+ }
752+ return pwf_;
753+ }
0 commit comments