Skip to content

Commit 1d7bca6

Browse files
committed
resolve numerical rounding bug that occurred when calculating polygon normals; fix equality operator bug in numeric.h
1 parent 6f711e0 commit 1d7bca6

File tree

7 files changed

+77
-35
lines changed

7 files changed

+77
-35
lines changed

include/mcut/internal/hmesh.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,7 @@ typedef halfedge_descriptor_t hd_t;
455455
typedef edge_descriptor_t ed_t;
456456
typedef face_descriptor_t fd_t;
457457

458-
void write_off(const char* fpath, const hmesh_t& mesh);
458+
void write_off(const char* fpath, const hmesh_t& mesh, const double multiplier);
459459
void read_off(hmesh_t& mesh, const char* fpath);
460460

461461
template <typename V = face_array_t>

include/mcut/internal/math.h

+28-9
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,19 @@
5050

5151
#include "nfg/numerics.h" // Indirect_Predicates
5252

53+
// Shewchuk predicates : shewchuk.c
54+
extern "C"
55+
{
56+
// void exactinit();
57+
double orient2d(const double* pa, const double* pb, const double* pc);
58+
double orient3d(const double* pa, const double* pb, const double* pc, const double* pd);
59+
double orient3dfast(const double* pa, const double* pb, const double* pc, const double* pd);
60+
double incircle(const double* pa, const double* pb, const double* pc, const double* pd);
61+
double insphere(
62+
const double* pa, const double* pb, const double* pc, const double* pd, const double* pe);
63+
}
64+
65+
5366
class rational_number : public bigrational
5467
{
5568
public:
@@ -786,6 +799,21 @@ void project_to_2d(std::vector<vec2>& out, const std::vector<vec3>& polygon_vert
786799
bool coplaner(const vec3& pa, const vec3& pb, const vec3& pc,
787800
const vec3& pd);
788801

802+
static bool collinear(const vec2_<double>& a,
803+
const vec2_<double>& b,
804+
const vec2_<double>& c,
805+
double& predResult)
806+
{
807+
const double pa_[2] = {a.x(), a.y()};
808+
const double pb_[2] = {b.x(), b.y()};
809+
const double pc_[2] = {c.x(), c.y()};
810+
811+
predResult = orient2d(pa_, pb_, pc_); // shewchuk predicate
812+
813+
//predResult = orient2d(a, b, c);
814+
return predResult == double(0.);
815+
}
816+
789817
bool collinear(const vec2& a, const vec2& b, const vec2& c, scalar_t& predResult);
790818

791819
bool collinear(const vec2& a, const vec2& b, const vec2& c);
@@ -909,15 +937,6 @@ void make_bbox(bounding_box_t<vector_type>& bbox, const vector_type* vertices, c
909937
}
910938
}
911939

912-
// Shewchuk predicates : shewchuk.c
913-
extern "C" {
914-
// void exactinit();
915-
double orient2d(const double* pa, const double* pb, const double* pc);
916-
double orient3d(const double* pa, const double* pb, const double* pc, const double* pd);
917-
double orient3dfast(const double* pa, const double* pb, const double* pc, const double* pd);
918-
double incircle(const double* pa, const double* pb, const double* pc, const double* pd);
919-
double insphere(const double* pa, const double* pb, const double* pc, const double* pd, const double* pe);
920-
}
921940

922941
# ifdef MCUT_WITH_ARBITRARY_PRECISION_NUMBERS
923942
static scalar_t orient2d(const scalar_t* pa, const scalar_t* pb, const scalar_t* pc)

include/mcut/internal/nfg/numerics.hpp

+3-3
Original file line numberDiff line numberDiff line change
@@ -732,14 +732,14 @@ inline void bignatural::operator>>=(uint32_t n) {
732732

733733
inline bool bignatural::operator==(const bignatural& b) const {
734734
if (size() != b.size()) return false;
735-
for (uint32_t i = 0; i < size(); i++) if (digits[i] == b.digits[i]) return false;
735+
for (uint32_t i = 0; i < size(); i++) if (digits[i] != b.digits[i]) return false;
736736
return true;
737737
}
738738

739739
inline bool bignatural::operator!=(const bignatural& b) const {
740740
if (size() != b.size()) return true;
741-
for (uint32_t i = 0; i < size(); i++) if (digits[i] == b.digits[i]) return true;
742-
return false;
741+
for (uint32_t i = 0; i < size(); i++) if (digits[i] == b.digits[i]) return false;
742+
return true;
743743
}
744744

745745
inline bool bignatural::operator>=(const bignatural& b) const {

source/hmesh.cpp

+5-2
Original file line numberDiff line numberDiff line change
@@ -1263,7 +1263,7 @@ const face_array_iterator_t hmesh_t::elements_begin_(id_<array_iterator_t<face_a
12631263
return faces_begin(account_for_removed_elems);
12641264
}
12651265

1266-
void write_off(const char* fpath, const hmesh_t& mesh)
1266+
void write_off(const char* fpath, const hmesh_t& mesh, const double multiplier)
12671267
{
12681268

12691269
std::ofstream outfile(fpath);
@@ -1289,7 +1289,10 @@ void write_off(const char* fpath, const hmesh_t& mesh)
12891289
for (vertex_array_iterator_t iter = mesh.vertices_begin(); iter != mesh.vertices_end(); ++iter) {
12901290
// const vertex_data_t& vdata = iter.second;
12911291
const vec3& point = mesh.vertex(*iter);
1292-
outfile << (double)point.x() << " " << (double)point.y() << " " << (double)point.z() << "\n";
1292+
outfile << (double)scalar_t::dequantize(point.x(), multiplier) << " "
1293+
<< (double)scalar_t::dequantize(point.y(), multiplier) << " "
1294+
<< (double)scalar_t::dequantize(point.z(), multiplier)
1295+
<< "\n";
12931296
}
12941297

12951298
//

source/kernel.cpp

+32-12
Original file line numberDiff line numberDiff line change
@@ -157,7 +157,7 @@ bool inline ps_is_cutmesh_face(const fd_t& ps_fd, const int sm_face_count)
157157
return ((int)ps_fd) >= sm_face_count;
158158
}
159159

160-
void dump_mesh(const hmesh_t& mesh, const char* fbasename)
160+
void dump_mesh(const hmesh_t& mesh, const char* fbasename, const double multiplier)
161161
{
162162
const std::string name = std::string(fbasename) + ".off";
163163

@@ -184,7 +184,7 @@ void dump_mesh(const hmesh_t& mesh, const char* fbasename)
184184
}
185185
}
186186

187-
write_off(name.c_str(), mesh);
187+
write_off(name.c_str(), mesh, multiplier);
188188
}
189189

190190
#if 0
@@ -1576,8 +1576,8 @@ void dispatch(output_t& output, const input_t& input)
15761576
const hmesh_t& cs = (*input.cut_mesh);
15771577

15781578
if (input.verbose) {
1579-
dump_mesh(sm, "src-mesh");
1580-
dump_mesh(cs, "cut-mesh");
1579+
dump_mesh(sm, "src-mesh", input.multiplier);
1580+
dump_mesh(cs, "cut-mesh", input.multiplier);
15811581
}
15821582

15831583
const int sm_vtx_cnt = sm.number_of_vertices();
@@ -1736,7 +1736,7 @@ void dispatch(output_t& output, const input_t& input)
17361736
// cs_to_ps_vtx.clear();
17371737

17381738
if (input.verbose) {
1739-
dump_mesh(ps, "polygon-soup");
1739+
dump_mesh(ps, "polygon-soup", input.multiplier);
17401740
}
17411741

17421742
const int ps_vtx_cnt = ps.number_of_vertices();
@@ -3236,7 +3236,11 @@ void dispatch(output_t& output, const input_t& input)
32363236
}
32373237

32383238
if (input.verbose) {
3239-
dump_mesh(m0, "m0.v"); // containing only vertices (polygon soup vertices and newly computed intersection points)
3239+
dump_mesh(
3240+
m0,
3241+
"m0.v",
3242+
input
3243+
.multiplier); // containing only vertices (polygon soup vertices and newly computed intersection points)
32403244
}
32413245

32423246
if (partial_cut_detected) {
@@ -3594,7 +3598,7 @@ void dispatch(output_t& output, const input_t& input)
35943598
// intersecting faces in the polygon-soup ("ps").
35953599

35963600
if (input.verbose) {
3597-
dump_mesh(m0, "m0.v.e"); // containing only vertices & edges
3601+
dump_mesh(m0, "m0.v.e", input.multiplier); // containing only vertices & edges
35983602
}
35993603

36003604
const uint32_t m0_num_cutpath_edges = (uint32_t)m0_cutpath_edges.size();
@@ -6332,7 +6336,9 @@ void dispatch(output_t& output, const input_t& input)
63326336
output.seamed_src_mesh->data_maps = std::move(separated_src_mesh_fragments.begin()->second.front().second.data_maps);
63336337

63346338
if (input.verbose) {
6335-
dump_mesh(output.seamed_src_mesh->mesh.get()[0], "src-mesh-traced-poly");
6339+
dump_mesh(output.seamed_src_mesh->mesh.get()[0],
6340+
"src-mesh-traced-poly",
6341+
input.multiplier);
63366342
}
63376343
}
63386344
} // if (input.include_seam_srcmesh) {
@@ -6382,7 +6388,8 @@ void dispatch(output_t& output, const input_t& input)
63826388
output.seamed_cut_mesh->data_maps = std::move(separated_cut_mesh_fragments.begin()->second.front().second.data_maps);
63836389

63846390
if (input.verbose) {
6385-
dump_mesh(output.seamed_cut_mesh->mesh.get()[0], "cut-mesh-traced-poly");
6391+
dump_mesh(
6392+
output.seamed_cut_mesh->mesh.get()[0], "cut-mesh-traced-poly", input.multiplier);
63866393
}
63876394
}
63886395
}
@@ -7755,7 +7762,11 @@ void dispatch(output_t& output, const input_t& input)
77557762
// is empty before calling "extract_connected_components"
77567763
MCUT_ASSERT(mesh_data.size() == 1);
77577764
if (input.verbose) {
7758-
dump_mesh(mesh_data.front().first.get()[0], ("fragment.unsealed." + std::to_string(cc_id) + "." + to_string(mesh_data.front().second.location)).c_str());
7765+
dump_mesh(mesh_data.front().first.get()[0],
7766+
("fragment.unsealed." + std::to_string(cc_id) + "." +
7767+
to_string(mesh_data.front().second.location))
7768+
.c_str(),
7769+
input.multiplier);
77597770
}
77607771
std::pair<std::shared_ptr<hmesh_t>, connected_component_info_t>& md = mesh_data.front();
77617772
std::shared_ptr<output_mesh_info_t> omi = std::shared_ptr<output_mesh_info_t>(new output_mesh_info_t);
@@ -9167,7 +9178,11 @@ void dispatch(output_t& output, const input_t& input)
91679178
#endif // #if defined(MCUT_WITH_COMPUTE_HELPER_THREADPOOL)
91689179

91699180
if (input.verbose) {
9170-
dump_mesh(patch_mesh.get()[0], ("patch" + std::to_string(cur_patch_idx) + "." + to_string(patch_location) + "." + cs_patch_descriptor_str).c_str());
9181+
dump_mesh(patch_mesh.get()[0],
9182+
("patch" + std::to_string(cur_patch_idx) + "." +
9183+
to_string(patch_location) + "." + cs_patch_descriptor_str)
9184+
.c_str(),
9185+
input.multiplier);
91719186
}
91729187

91739188
std::shared_ptr<output_mesh_info_t> omi = std::shared_ptr<output_mesh_info_t>(new output_mesh_info_t);
@@ -10700,7 +10715,12 @@ void dispatch(output_t& output, const input_t& input)
1070010715

1070110716
if (input.verbose) {
1070210717
// const int idx = (int)std::distance(cc_instances.begin(), cc_instance_iter);
10703-
dump_mesh(cc_instance.first.get()[0], (std::string("cc") + std::to_string(idx++) + "." + to_string(cc_instance.second.location) + "." + to_string(patchLocation)).c_str());
10718+
dump_mesh(cc_instance.first.get()[0],
10719+
(std::string("cc") + std::to_string(idx++) + "." +
10720+
to_string(cc_instance.second.location) + "." +
10721+
to_string(patchLocation))
10722+
.c_str(),
10723+
input.multiplier);
1070410724
}
1070510725

1070610726
std::shared_ptr<output_mesh_info_t> omi = std::shared_ptr<output_mesh_info_t>(new output_mesh_info_t);

source/math.cpp

+6-4
Original file line numberDiff line numberDiff line change
@@ -151,7 +151,7 @@
151151
scalar_t::dequantize(vec1[2], multiplier));
152152

153153
auto cross_ = cross_product(vec0_, vec1_);
154-
if(squared_length(cross_) > 0.)
154+
if(squared_length(cross_) > 1e-7)
155155
{
156156
auto cross_n = normalize(cross_);
157157
vec3 cross = vec3(scalar_t::quantize(cross_n[0], multiplier),
@@ -782,12 +782,13 @@
782782
const vec3& x = polygon_vertices[i];
783783
out[i] = P * x; // vertex in xz plane
784784
}
785-
#else // This code is not reliable because it shadow-projects a polygons which can skew computations
785+
#else // This code is not reliable because it shadow-projects a polygon
786786
for (int i = 0; i < polygon_vertex_count; ++i) { // for each vertex
787787
vec2& Tp = out[i];
788788
int k = 0;
789789
for (int j = 0; j < 3; j++) { // for each component
790-
if (j != polygon_plane_normal_largest_component) { /* skip largest coordinate */
790+
if(j != polygon_normal_largest_component)
791+
{ /* skip largest coordinate */
791792
792793
Tp[k] = polygon_vertices[i][j];
793794
k++;
@@ -969,7 +970,8 @@
969970
num = a[0] * (d[1] - c[1]) + //
970971
c[0] * (a[1] - d[1]) + //
971972
d[0] * (c[1] - a[1]);
972-
973+
std::cout << "test\n";
974+
std::cout << num.get_str() << std::endl << denom.get_str() << std::endl;
973975
if ((num == scalar_t(0.0)) || (num == denom)) {
974976
code = 'v';
975977
}

source/preproc.cpp

+2-4
Original file line numberDiff line numberDiff line change
@@ -1079,16 +1079,14 @@ void resolve_floating_polygons(
10791079
it != polyVerts.cend();
10801080
++it)
10811081
{
1082-
// TODO: call "collinear" with vec3_<double> not vec3. That is the only way to
1083-
// get a reliable measure because with double everything is in the same space/units
1084-
// (lengths areas etc).
1082+
10851083
bool are_collinear = collinear(segStart, segEnd, (*it), predResult);
10861084
// last ditch attempt to prevent the possibility of creating a partitioning
10871085
// edge that more-or-less passes through a vertex (of origin-face or the floatig poly itself)
10881086
// see: test41
10891087
const double epsilon = 1e-6;
10901088
#if MCUT_WITH_ARBITRARY_PRECISION_NUMBERS
1091-
if(are_collinear || epsilon > scalar_t::dequantize(absolute_value(predResult),multiplier))
1089+
if(are_collinear || (scalar_t::quantize(epsilon, multiplier) > absolute_value(predResult)))
10921090
#else
10931091
if(are_collinear || (!are_collinear && epsilon > std::fabs(predResult)))
10941092
#endif

0 commit comments

Comments
 (0)