651{
652 assert(debug::verify_twin_halfedges_successive(vd, lines));
653
655
656#ifdef VORONOI_DEBUG_OUT
658 {
662 }
663 static int irun = 0;
664 ++ irun;
665 dump_voronoi_to_svg(
debug_out_path(
"voronoi-offset-initial-%d.svg", irun).c_str(), vd,
Points(), lines);
666#endif
667
668
669 auto annotate_vertex = [](const VD::vertex_type *vertex, VertexCategory new_vertex_category) {
670#ifndef NDEBUG
671 VertexCategory vc = vertex_category(vertex);
672 assert(vc == VertexCategory::Unknown || vc == new_vertex_category);
673 assert(new_vertex_category == VertexCategory::Inside ||
674 new_vertex_category == VertexCategory::Outside ||
675 new_vertex_category == VertexCategory::OnContour);
676#endif
677 set_vertex_category(const_cast<VD::vertex_type*>(vertex), new_vertex_category);
678 };
679
680
681 auto annotate_edge = [](const VD::edge_type *edge, EdgeCategory new_edge_category) {
682#ifndef NDEBUG
683 EdgeCategory ec = edge_category(edge);
684 assert(ec == EdgeCategory::Unknown || ec == new_edge_category);
685 switch (new_edge_category) {
686 case EdgeCategory::PointsInside:
687 assert(edge->vertex0() != nullptr);
688 assert(edge->vertex1() != nullptr);
689 break;
690 case EdgeCategory::PointsOutside:
691
692 break;
693 case EdgeCategory::PointsToContour:
694 assert(edge->vertex1() != nullptr);
695 break;
696 default:
697 assert(false);
698 }
699#endif
701 };
702
703
704
705
706 auto annotate_cell = [](
const VD::cell_type *cell,
CellCategory new_cell_category) ->
bool {
708 assert(cc == CellCategory::Inside || cc == CellCategory::Outside || cc == CellCategory::Boundary || cc == CellCategory::Unknown);
709 assert(new_cell_category == CellCategory::Inside || new_cell_category == CellCategory::Outside || new_cell_category == CellCategory::Boundary);
710 switch (cc) {
711 case CellCategory::Unknown:
712
713 break;
714 case CellCategory::Outside:
715 if (new_cell_category == CellCategory::Inside)
716 new_cell_category = CellCategory::Boundary;
717 break;
718 case CellCategory::Inside:
719 if (new_cell_category == CellCategory::Outside)
720 new_cell_category = CellCategory::Boundary;
721 break;
722 case CellCategory::Boundary:
723 return false;
724 }
725 if (cc != new_cell_category) {
727 return true;
728 }
729 return false;
730 };
731
732
733
734
735
736 for (
const VD::edge_type &edge : vd.
edges()) {
737 const VD::vertex_type *v = edge.vertex0();
738 if (v != nullptr) {
739 bool on_contour = detail::on_site(lines, *edge.cell(),
vertex_point(v));
740#ifndef NDEBUG
741 bool on_contour2 = detail::on_site(lines, *edge.twin()->cell(),
vertex_point(v));
742 assert(on_contour == on_contour2);
743#endif
744 if (on_contour)
745 annotate_vertex(v, VertexCategory::OnContour);
746 }
747 }
748
749
750
751 for (
const VD::edge_type &edge : vd.
edges()) {
752 if (edge.is_secondary() && edge.vertex0() != nullptr) {
753 assert(edge.is_linear());
754 assert(edge.cell()->contains_point() != edge.twin()->cell()->contains_point());
755
757 auto on_contour = [&pt_on_contour](const VD::vertex_type *v) { return detail::vertex_equal_to_point(v, pt_on_contour); };
758 if (edge.vertex1() == nullptr) {
759 assert(on_contour(edge.vertex0()));
760 annotate_vertex(edge.vertex0(), VertexCategory::OnContour);
761 } else {
762
763 const VD::vertex_type *v0 = edge.vertex0();
764 const VD::vertex_type *v1 = edge.vertex1();
765#ifndef NDEBUG
768 assert(v0_category != VertexCategory::OnContour || v1_category != VertexCategory::OnContour);
769 assert(! (on_contour(v0) && on_contour(v1)));
770#endif
771 if (on_contour(v0))
772 annotate_vertex(v0, VertexCategory::OnContour);
773 else {
774 assert(on_contour(v1));
775 annotate_vertex(v1, VertexCategory::OnContour);
776 }
777 }
778 }
779 }
780
781 assert(debug::verify_vertices_on_contour(vd, lines));
782
783 for (
const VD::edge_type &edge : vd.
edges())
784 if (edge.vertex1() == nullptr) {
785
786
787 assert(edge.is_infinite());
788 assert(edge.is_linear());
789 assert(edge.vertex0() != nullptr);
790 const VD::cell_type *cell = edge.cell();
791 const VD::cell_type *cell2 = edge.twin()->cell();
792
793
794 assert(edge.is_secondary() ? (cell->contains_segment() != cell2->contains_segment()) :
795 (cell->contains_point() == cell2->contains_point()));
796 annotate_edge(&edge, EdgeCategory::PointsOutside);
797
799 annotate_vertex(edge.vertex0(), edge.is_secondary() ? VertexCategory::OnContour :
VertexCategory::
Outside);
800
801 if (cell->contains_segment())
802 std::swap(cell, cell2);
803
804 assert(cell->contains_point());
805 annotate_cell(cell, CellCategory::Outside);
806 assert(edge.is_secondary() == cell2->contains_segment());
808 } else if (edge.vertex0() != nullptr) {
809 assert(edge.is_finite());
810 const VD::cell_type *cell = edge.cell();
811 const Line *line = cell->contains_segment() ? &lines[cell->source_index()] : nullptr;
812 if (line == nullptr) {
813 cell = edge.twin()->cell();
814 line = cell->contains_segment() ? &lines[cell->source_index()] : nullptr;
815 }
816
817 assert(! edge.is_linear() ||
vertex_category(edge.vertex0()) != VertexCategory::OnContour ||
vertex_category(edge.vertex1()) != VertexCategory::OnContour);
818
819
820
821
822 if (line) {
823 const VD::vertex_type *v1 = edge.vertex1();
824 const VD::cell_type *cell2 = (cell == edge.cell()) ? edge.twin()->cell() : edge.cell();
825 assert(v1 != nullptr);
828 bool on_contour = v0_category == VertexCategory::OnContour || v1_category == VertexCategory::OnContour;
829#ifndef NDEBUG
830 if (! on_contour && cell == edge.cell() && edge.twin()->cell()->contains_segment()) {
831
832
833 assert(edge.is_linear());
834
835 const Point *pt_on_contour =
nullptr;
836
837
838 const Line &line2 = lines[cell2->source_index()];
839 if (line->a == line2.b)
840 pt_on_contour = &line->a;
841 else if (line->b == line2.a)
842 pt_on_contour = &line->b;
843 if (pt_on_contour) {
844 const VD::vertex_type *v0 = edge.vertex0();
845 auto on_contour = [&pt_on_contour](const VD::vertex_type *v) {
846 return std::abs(v->x() - pt_on_contour->x()) < 0.5001 &&
847 std::abs(v->y() - pt_on_contour->y()) < 0.5001;
848 };
849 assert(! on_contour(v0) && ! on_contour(v1));
850 }
851 }
852#endif
853 if (on_contour && v1_category == VertexCategory::OnContour) {
854
855 annotate_edge(&edge, EdgeCategory::PointsToContour);
856 } else {
857
858
859
860 Vec2d l0(line->a.cast<
double>());
861 Vec2d lv((line->b - line->a).cast<
double>());
862 double side =
cross2(
Vec2d(v1->x(), v1->y()) - l0, lv);
863
864 assert(side != 0.);
865 auto vc = side > 0. ? VertexCategory::Outside : VertexCategory::Inside;
866 annotate_vertex(v1, vc);
867 auto ec = vc == VertexCategory::Outside ? EdgeCategory::PointsOutside : EdgeCategory::PointsInside;
868 annotate_edge(&edge, ec);
869
870
871 annotate_vertex(edge.vertex0(), on_contour ? VertexCategory::OnContour : vc);
872 annotate_edge(edge.twin(), on_contour ? EdgeCategory::PointsToContour : ec);
873 assert(cell->contains_segment());
874 annotate_cell(cell, on_contour ? CellCategory::Boundary :
876 annotate_cell(cell2, (on_contour && cell2->contains_segment()) ? CellCategory::Boundary :
878 }
879 }
880 }
881
882 assert(debug::verify_vertices_on_contour(vd, lines));
883
884
885
886
887 std::vector<const VD::cell_type*> cell_queue;
888 for (
const VD::edge_type &edge : vd.
edges()) {
891 assert(edge.is_finite());
892 const VD::cell_type &cell = *edge.cell();
893 const VD::cell_type &cell2 = *edge.twin()->cell();
894 assert(cell.contains_point() && cell2.contains_point());
897 assert(cc != CellCategory::Boundary && cc2 != CellCategory::Boundary);
899 if (cc_new == CellCategory::Unknown)
900 cc_new = cc2;
901 else
902 assert(cc2 == CellCategory::Unknown || cc == cc2);
903 if (cc_new == CellCategory::Unknown) {
905 assert(vc != VertexCategory::OnContour);
906 if (vc != VertexCategory::Unknown)
907 cc_new = (vc == VertexCategory::Outside) ? CellCategory::Outside :
CellCategory::
Inside;
908 }
909 if (cc_new != CellCategory::Unknown) {
911 annotate_vertex(edge.vertex0(), vc);
912 annotate_vertex(edge.vertex1(), vc);
914 annotate_edge(&edge, ec_new);
915 annotate_edge(edge.twin(), ec_new);
916 if (cc != cc_new) {
917 annotate_cell(&cell, cc_new);
918 cell_queue.emplace_back(&cell);
919 }
920 if (cc2 != cc_new) {
921 annotate_cell(&cell2, cc_new);
922 cell_queue.emplace_back(&cell2);
923 }
924 }
925 }
926 }
927
928 assert(debug::verify_vertices_on_contour(vd, lines));
929
930
931 while (! cell_queue.empty()) {
932 const VD::cell_type *cell = cell_queue.back();
934 assert(cc == CellCategory::Outside || cc == CellCategory::Inside);
935 cell_queue.pop_back();
936 const VD::edge_type *first_edge = cell->incident_edge();
937 const VD::edge_type *edge = first_edge;
939 do {
941 if (ec == EdgeCategory::Unknown) {
942 assert(edge->cell()->contains_point() && edge->twin()->cell()->contains_point());
943 annotate_edge(edge, ec_new);
944 annotate_edge(edge->twin(), ec_new);
945 const VD::cell_type *cell2 = edge->twin()->cell();
947 assert(cc2 == CellCategory::Unknown || cc2 == cc);
948 if (cc2 != cc) {
949 annotate_cell(cell2, cc);
950 cell_queue.emplace_back(cell2);
951 }
952 } else {
953 assert(edge->vertex0() ==
nullptr ||
vertex_category(edge->vertex0()) != VertexCategory::Unknown);
954 assert(edge->vertex1() ==
nullptr ||
vertex_category(edge->vertex1()) != VertexCategory::Unknown);
955 assert(
edge_category(edge->twin()) != EdgeCategory::Unknown);
956 assert(
cell_category(edge->cell()) != CellCategory::Unknown);
957 assert(
cell_category(edge->twin()->cell()) != CellCategory::Unknown);
958 }
959 edge = edge->next();
960 } while (edge != first_edge);
961 }
962
963 assert(debug::verify_vertices_on_contour(vd, lines));
964 assert(debug::verify_inside_outside_annotations(vd));
965}
PointType max
Definition BoundingBox.hpp:17
void merge(const PointType &point)
Definition BoundingBox.cpp:62
PointType size() const
Definition BoundingBox.cpp:144
PointType min
Definition BoundingBox.hpp:16
Definition BoundingBox.hpp:181
if(!(yy_init))
Definition lexer.c:1190
int32_t coord_t
Definition libslic3r.h:39
void set_edge_category(VD::edge_type &e, EdgeCategory c)
Definition VoronoiOffset.hpp:85
EdgeCategory
Definition VoronoiOffset.hpp:48
void set_cell_category(const VD::cell_type &v, CellCategory c)
Definition VoronoiOffset.hpp:94
CellCategory
Definition VoronoiOffset.hpp:61
CellCategory cell_category(const VD::cell_type &v)
Definition VoronoiOffset.hpp:90
VertexCategory vertex_category(const VD::vertex_type &v)
Definition VoronoiOffset.hpp:72
VertexCategory
Definition VoronoiOffset.hpp:31
void reset_inside_outside_annotations(VD &vd)
Definition VoronoiOffset.cpp:640
EdgeCategory edge_category(const VD::edge_type &e)
Definition VoronoiOffset.hpp:81
Vec2d vertex_point(const VD::vertex_type &v)
Definition VoronoiOffset.hpp:26
const Point & contour_point(const VD::cell_type &cell, const Line &line)
Definition VoronoiOffset.hpp:16
std::string debug_out_path(const char *name,...)
Definition utils.cpp:218
Derived::Scalar cross2(const Eigen::MatrixBase< Derived > &v1, const Eigen::MatrixBase< Derived2 > &v2)
Definition Point.hpp:93
Eigen::Matrix< double, 2, 1, Eigen::DontAlign > Vec2d
Definition Point.hpp:51
BoundingBox get_extents(const ExPolygon &expolygon)
Definition ExPolygon.cpp:352
std::vector< Point, PointsAllocator< Point > > Points
Definition Point.hpp:58
IGL_INLINE void edges(const Eigen::MatrixBase< DerivedF > &F, Eigen::PlainObjectBase< DerivedE > &E)
Definition edges.cpp:13
Kernel::Point_2 Point
Definition point_areas.cpp:20