384 std::vector<VertexPlaneLocation> vertex_locations_local;
385 std::vector<VertexPlaneLocation>& vertex_locations = vertex_locations_ptr ? *vertex_locations_ptr : vertex_locations_local;
386 std::vector<T> vertex_signed_distances;
387 compute_vertex_locations(split_plane, vertex_locations, epsilon, &vertex_signed_distances);
390 std::vector<FacePlaneLocation> face_locations;
391 if (!check_face_locations(si, vertex_locations, face_locations)) {
392 if (!ensure_vertex_location_consistency(si, vertex_signed_distances, vertex_locations, face_locations)) {
393 std::cerr <<
"found case that could not be made consistent" << std::endl;
401 if (shell_location == VPL_INSIDE) {
403 if (!keep_original_shell)
404 return std::pair<int, int>(si, -1);
406 int new_si = add_shell();
407 copy_shell(si, new_si);
408 return std::pair<int, int>(new_si, -1);
411 if (shell_location == VPL_OUTSIDE) {
413 if (!keep_original_shell)
414 return std::pair<int, int>(-1, si);
416 int new_si = add_shell();
417 copy_shell(si, new_si);
418 return std::pair<int, int>(-1, new_si);
422 std::vector<std::pair<int, int> > new_face_halfedges;
424 std::map<std::pair<int, int>,
int> edge_vertex_indices;
429 int si_inside = add_shell();
430 int si_outside = add_shell();
432 for (
unsigned fi = 0; fi < get_nr_faces(si); ++fi) {
433 switch (face_locations[fi]) {
435 case FPL_OUTSIDE + FPL_TOUCH_EDGE:
438 std::pair<int, int> halfedge = extract_touching_halfedge(face(fi,si), vertex_locations);
439 std::pair<int, int> edge(std::min(halfedge.first, halfedge.second), std::max(halfedge.first, halfedge.second));
440 auto ete_iter = edge_touch_events.find(edge);
442 if (ete_iter != edge_touch_events.end()) {
444 if (ete_iter->second == FPL_INSIDE + FPL_TOUCH_EDGE)
445 new_face_halfedges.push_back(std::pair<int, int>(halfedge.second, halfedge.first));
447 edge_touch_events.erase(ete_iter);
453 case FPL_OUTSIDE + FPL_TOUCH_NOTHING:
454 case FPL_OUTSIDE + FPL_TOUCH_VERTEX:
456 int fi_outside = add_face(si_outside);
457 face(fi_outside, si_outside) = face(fi, si);
458 face_plane(fi_outside, si_outside) = face_plane(fi, si);
462 case FPL_INSIDE + FPL_TOUCH_EDGE:
465 std::pair<int, int> halfedge = extract_touching_halfedge(face(fi, si), vertex_locations);
466 std::pair<int, int> edge(std::min(halfedge.first, halfedge.second), std::max(halfedge.first, halfedge.second));
467 auto ete_iter = edge_touch_events.find(edge);
469 if (ete_iter != edge_touch_events.end()) {
471 if (ete_iter->second == FPL_OUTSIDE + FPL_TOUCH_EDGE)
472 new_face_halfedges.push_back(halfedge);
474 edge_touch_events.erase(ete_iter);
480 case FPL_INSIDE + FPL_TOUCH_NOTHING:
481 case FPL_INSIDE + FPL_TOUCH_VERTEX:
483 int fi_inside = add_face(si_inside);
484 face(fi_inside, si_inside) = face(fi, si);
485 face_plane(fi_inside, si_inside) = face_plane(fi, si);
491 int fi_outside = add_face(si_outside);
492 int fi_inside = add_face(si_inside);
493 face(fi_outside, si_outside) = face(fi_inside, si_inside) = face(fi, si);
494 face_plane(fi_outside, si_outside) = -face_plane(fi, si);
495 face_plane(fi_inside, si_inside) = face_plane(fi, si);
496 if (orientation_match(split_plane, face_plane(fi, si)))
497 change_orientation(face(fi_outside, si_outside));
499 change_orientation(face(fi_inside, si_inside));
503 case FPL_SPLIT_TWO_VERTICES:
504 case FPL_SPLIT_VERTEX_EDGE:
505 case FPL_SPLIT_TWO_EDGES:
509 int fi_outside = add_face(si_outside);
510 int fi_inside = add_face(si_inside);
511 face_type& F_outside = face(fi_outside, si_outside);
512 face_type& F_inside = face(fi_inside, si_inside);
514 face_plane(fi_outside, si_outside) = face_plane(fi_inside, si_inside) = face_plane(fi, si);
516 std::vector<int> split_vis;
517 int last_vi = F.back();
519 for (
unsigned i = 0; i < F.size(); ++i) {
523 if (vertex_location == VPL_TOUCH) {
524 F_outside.push_back(vi);
525 F_inside.push_back(vi);
526 split_vis.push_back(vi);
527 if (split_vis.size() == 2 && last_vertex_location == VPL_INSIDE)
528 std::swap(split_vis[0], split_vis[1]);
532 if (last_vertex_location != VPL_TOUCH && vertex_location != last_vertex_location) {
534 std::pair<int, int> edge(std::min(last_vi, vi), std::max(last_vi, vi));
535 auto evi_iter = edge_vertex_indices.find(edge);
538 if (evi_iter != edge_vertex_indices.end()) {
539 split_vi = evi_iter->second;
540 edge_vertex_indices.erase(evi_iter);
544 split_vi = (int)vertices.size();
545 T distance = abs(vertex_signed_distances[vi]);
546 T last_distance = abs(vertex_signed_distances[last_vi]);
547 T lambda = last_distance / (last_distance + distance);
549 split_vertex.position = (T(1) - lambda) * position(last_vi) + lambda * position(vi);
550 split_vertex.texcoord = (T(1) - lambda) * texcoord(last_vi) + lambda * texcoord(vi);
551 vertices.push_back(split_vertex);
552 vertex_locations.push_back(VPL_TOUCH);
553 edge_vertex_indices[edge] = split_vi;
555 split_vis.push_back(split_vi);
556 if (split_vis.size() == 2 && last_vertex_location == VPL_INSIDE)
557 std::swap(split_vis[0], split_vis[1]);
560 F_outside.push_back(split_vi);
561 F_inside.push_back(split_vi);
564 if (vertex_location == VPL_INSIDE)
565 F_inside.push_back(vi);
567 F_outside.push_back(vi);
570 last_vertex_location = vertex_location;
572 if (split_vis.size() != 2) {
573 std::cerr <<
"expected two split vertices but found " << split_vis.size() << std::endl;
576 new_face_halfedges.push_back(std::pair<int, int>(split_vis[0], split_vis[1]));
580 std::cerr <<
"did not expect face plane location " << face_locations[fi] << std::endl;
587 int fi_outside = add_face(si_outside);
588 int fi_inside = add_face(si_inside);
589 face_type& F_outside = face(fi_outside, si_outside);
590 face_type& F_inside = face(fi_inside, si_inside);
591 face_plane(fi_outside, si_outside) = -split_plane;
592 face_plane(fi_inside, si_inside) = split_plane;
595 F_outside.resize(new_face_halfedges.size());
596 F_outside[0] = new_face_halfedges[0].first;
597 int last_vi = F_outside[1] = new_face_halfedges[0].second;
599 for (
unsigned i = 2; i < F_outside.size(); ++i) {
601 for (
unsigned k = k0; k < new_face_halfedges.size(); ++k) {
602 if (new_face_halfedges[k].first == last_vi) {
603 last_vi = F_outside[i] = new_face_halfedges[k].second;
605 std::swap(new_face_halfedges[k0], new_face_halfedges[k]);
612 std::cerr <<
"loop of new face not complete" << std::endl;
616 if (k0 < new_face_halfedges.size()-1) {
617 std::cerr <<
"loop of new face does not use all new halfedges" << std::endl;
620 if (new_face_halfedges.back().first != F_outside.back() ||
621 new_face_halfedges.back().second != F_outside.front()) {
622 std::cerr <<
"loop of new face does is not closed by last new halfedge" << std::endl;
626 std::copy(F_outside.rbegin(), F_outside.rend(), std::back_inserter(F_inside));
629 if (keep_original_shell)
630 return std::pair<int, int>(si_inside, si_outside);
632 copy_shell(si_outside, si);
633 del_shell(si_outside);
634 return std::pair<int, int>(si_inside, si);
642 std::vector<VertexPlaneLocation> vertex_locations;
643 std::vector<T> vertex_signed_distances;
644 compute_vertex_locations(
plane, vertex_locations, epsilon, &vertex_signed_distances);
647 std::vector<FacePlaneLocation> face_locations;
648 if (!check_face_locations(si, vertex_locations, face_locations)) {
649 std::cerr <<
"no valid face locations found" << std::endl;
650 return std::vector<vertex_type>();
654 if (shell_location_side(face_locations) != VPL_TOUCH)
655 return std::vector<vertex_type>();
658 for (
unsigned fi = 0; fi < face_locations.size(); ++fi) {
659 if (face_locations[fi] == FPL_TOUCH_FACE) {
660 std::vector<vertex_type> intersection;
662 if (orientation_match(face_plane(fi, si),
plane)) {
663 for (
auto v = F.begin(); v != F.end(); ++v)
664 intersection.push_back(vertices[*v]);
667 for (
auto v = F.rbegin(); v != F.rend(); ++v)
668 intersection.push_back(vertices[*v]);
674 std::vector<std::pair<int, int> > new_face_halfedges;
676 std::map<std::pair<int, int>,
int> edge_vertex_indices;
680 std::vector<vertex_type> split_vertices;
683 for (
unsigned fi = 0; fi < get_nr_faces(si); ++fi) {
684 switch (face_locations[fi]) {
686 case FPL_OUTSIDE + FPL_TOUCH_EDGE:
687 case FPL_INSIDE + FPL_TOUCH_EDGE:
690 std::pair<int, int> halfedge = extract_touching_halfedge(face(fi, si), vertex_locations);
691 std::pair<int, int> edge(std::min(halfedge.first, halfedge.second), std::max(halfedge.first, halfedge.second));
692 auto ete_iter = edge_touch_events.find(edge);
694 if (ete_iter != edge_touch_events.end()) {
696 if (ete_iter->second != face_locations[fi]) {
697 if (ete_iter->second == FPL_OUTSIDE + FPL_TOUCH_EDGE)
698 std::swap(halfedge.first, halfedge.second);
699 new_face_halfedges.push_back(halfedge);
702 edge_touch_events.erase(ete_iter);
706 edge_touch_events[edge] = face_locations[fi];
710 case FPL_SPLIT_TWO_VERTICES:
711 case FPL_SPLIT_VERTEX_EDGE:
712 case FPL_SPLIT_TWO_EDGES:
714 std::vector<int> split_vis;
716 int last_vi = F.back();
721 if (vertex_location == VPL_TOUCH) {
722 split_vis.push_back(vi);
723 if (split_vis.size() == 2 && last_vertex_location == VPL_OUTSIDE)
724 std::swap(split_vis[0], split_vis[1]);
728 if (last_vertex_location != VPL_TOUCH && vertex_location != last_vertex_location) {
730 std::pair<int, int> edge(std::min(last_vi, vi), std::max(last_vi, vi));
731 auto evi_iter = edge_vertex_indices.find(edge);
734 if (evi_iter != edge_vertex_indices.end()) {
735 split_vi = evi_iter->second;
736 edge_vertex_indices.erase(evi_iter);
740 split_vi = -1-(int)split_vertices.size();
741 T distance = abs(vertex_signed_distances[vi]);
742 T last_distance = abs(vertex_signed_distances[last_vi]);
743 T lambda = last_distance / (last_distance + distance);
745 split_vertex.position = (T(1) - lambda) * position(last_vi) + lambda * position(vi);
746 split_vertex.texcoord = (T(1) - lambda) * texcoord(last_vi) + lambda * texcoord(vi);
747 split_vertices.push_back(split_vertex);
748 edge_vertex_indices[edge] = split_vi;
750 split_vis.push_back(split_vi);
751 if (split_vis.size() == 2 && last_vertex_location == VPL_OUTSIDE)
752 std::swap(split_vis[0], split_vis[1]);
756 last_vertex_location = vertex_location;
758 if (split_vis.size() != 2) {
759 std::cerr <<
"expected two split vertices but found " << split_vis.size() << std::endl;
762 new_face_halfedges.push_back(std::pair<int, int>(split_vis[0], split_vis[1]));
765 case FPL_INSIDE + FPL_TOUCH_NOTHING:
766 case FPL_INSIDE + FPL_TOUCH_VERTEX:
767 case FPL_OUTSIDE + FPL_TOUCH_NOTHING:
768 case FPL_OUTSIDE + FPL_TOUCH_VERTEX:
771 std::cerr <<
"did not expect face plane location " << face_locations[fi] << std::endl;
776 std::vector<vertex_type> intersection;
779 intersection.resize(new_face_halfedges.size());
780 int fst_vi = new_face_halfedges[0].first;
781 int last_vi = new_face_halfedges[0].second;
782 intersection[0] = fst_vi < 0 ? split_vertices[-fst_vi-1] : vertices[fst_vi];
783 intersection[1] = last_vi < 0 ? split_vertices[-last_vi-1] : vertices[last_vi];
785 for (
unsigned i = 2; i < intersection.size(); ++i) {
787 for (
unsigned k = k0; k < new_face_halfedges.size(); ++k) {
788 if (new_face_halfedges[k].first == last_vi) {
789 last_vi = new_face_halfedges[k].second;
790 intersection[i] = last_vi < 0 ? split_vertices[-last_vi-1] : vertices[last_vi];
792 std::swap(new_face_halfedges[k0], new_face_halfedges[k]);
799 std::cerr <<
"loop of new face not complete" << std::endl;
803 if (k0 < new_face_halfedges.size() - 1) {
804 std::cerr <<
"loop of new face does not use all new halfedges" << std::endl;
807 if (new_face_halfedges.back().first != last_vi ||
808 new_face_halfedges.back().second != fst_vi) {
809 std::cerr <<
"loop of new face does is not closed by last new halfedge" << std::endl;