mirror of https://github.com/vitalif/openscad
Based on a patch from Xyne, this should be a slightly less verbose way of safely calculating normals. Note that CGAL does have a unit_normal() function, but since the Gmpq kernel doesn't support sqrt(), this cannot be used.
parent
7a044adfb8
commit
47c51d128a
|
@ -83,32 +83,24 @@ void export_stl(CGAL_Nef_polyhedron *root_N, std::ostream &output, QProgressDial
|
||||||
stream.str("");
|
stream.str("");
|
||||||
stream << x3 << " " << y3 << " " << z3;
|
stream << x3 << " " << y3 << " " << z3;
|
||||||
std::string vs3 = stream.str();
|
std::string vs3 = stream.str();
|
||||||
|
CGAL_Polyhedron::Traits::Vector_3 normal(1,0,0);
|
||||||
if (vs1 != vs2 && vs1 != vs3 && vs2 != vs3) {
|
if (vs1 != vs2 && vs1 != vs3 && vs2 != vs3) {
|
||||||
// The above condition ensures that vs1-vs2, vs1-vs3, and their cross
|
// The above condition ensures that there are 3 distinct vertices, but
|
||||||
// product are non-zero. Floating point arithmetic may however truncate
|
// they may be collinear. If they are, the unit normal is meaningless
|
||||||
// small values to 0. This can be avoided by first scaling the components
|
// so the default value of "1 0 0" can be used. If the vertices are not
|
||||||
// of vs1-vs2 and vs1-vs3. This has no effect on the resulting unit
|
// collinear then the unit normal must be calculated from the
|
||||||
// normal vector.
|
// components.
|
||||||
double dn[6] = { x1-x2, y1-y2, z1-z2, x1-x3, y1-y3, z1-z3 };
|
if (!CGAL::collinear(v1.point(),v2.point(),v3.point())) {
|
||||||
double maxdn = 0;
|
// Pseudocode: CGAL kernel must be set up to enable unit_normal and
|
||||||
int i;
|
// Vector type must be declared as Vector_3<Kernel>.
|
||||||
for (i = 0; i < 6; ++i) {
|
// http://www.cgal.org/Manual/latest/doc_html/cgal_manual/Kernel_23_ref/Function_unit_normal.html
|
||||||
double dx = dn[i];
|
normal = CGAL::normal(v1.point(),v2.point(),v3.point());
|
||||||
if (dx < 0) dx = -dx;
|
normal = normal / sqrt(CGAL::to_double(normal.squared_length()));
|
||||||
if (dx > maxdn) maxdn = dx;
|
}
|
||||||
}
|
|
||||||
for (i = 0; i < 6; ++i) dn[i] /= maxdn;
|
|
||||||
double nx = dn[1]*dn[5] - dn[2]*dn[4];
|
|
||||||
double ny = dn[2]*dn[3] - dn[0]*dn[5];
|
|
||||||
double nz = dn[0]*dn[4] - dn[1]*dn[3];
|
|
||||||
double nlength = sqrt(nx*nx + ny*ny + nz*nz);
|
|
||||||
// Avoid generating normals for polygons with zero area
|
|
||||||
double eps = 0.000001;
|
|
||||||
if (nlength < eps) nlength = 1.0;
|
|
||||||
output << " facet normal "
|
output << " facet normal "
|
||||||
<< nx / nlength << " "
|
<< CGAL::to_double(normal.x()) << " "
|
||||||
<< ny / nlength << " "
|
<< CGAL::to_double(normal.y()) << " "
|
||||||
<< nz / nlength << "\n";
|
<< CGAL::to_double(normal.z()) << "\n";
|
||||||
output << " outer loop\n";
|
output << " outer loop\n";
|
||||||
output << " vertex " << vs1 << "\n";
|
output << " vertex " << vs1 << "\n";
|
||||||
output << " vertex " << vs2 << "\n";
|
output << " vertex " << vs2 << "\n";
|
||||||
|
|
Loading…
Reference in New Issue