Merge pull request #574 from openscad/planar

Planar - see  issue #349
vector-concat
Marius Kintel 2013-12-15 15:21:51 -08:00
commit dced79fb2d
21 changed files with 411 additions and 46 deletions

View File

@ -680,16 +680,32 @@ CGAL_Nef_polyhedron CGALEvaluator::evaluateCGALMesh(const PolySet &ps)
else // not (this->is2d)
{
CGAL_Nef_polyhedron3 *N = NULL;
bool plane_error = false;
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
try {
// FIXME: Are we leaking memory for the CGAL_Polyhedron object?
CGAL_Polyhedron *P = createPolyhedronFromPolySet(ps);
if (P) {
N = new CGAL_Nef_polyhedron3(*P);
}
CGAL_Polyhedron P;
bool err = createPolyhedronFromPolySet(ps,P);
if (!err) N = new CGAL_Nef_polyhedron3(P);
}
catch (const CGAL::Assertion_exception &e) {
PRINTB("CGAL error in CGAL_Nef_polyhedron3(): %s", e.what());
if (std::string(e.what()).find("Plane_constructor")!=std::string::npos) {
if (std::string(e.what()).find("has_on")!=std::string::npos) {
PRINT("PolySet has nonplanar faces. Attempting alternate construction");
plane_error=true;
}
} else {
PRINTB("CGAL error in CGAL_Nef_polyhedron3(): %s", e.what());
}
}
if (plane_error) try {
PolySet ps2;
CGAL_Polyhedron P;
tessellate_3d_faces( ps, ps2 );
bool err = createPolyhedronFromPolySet(ps2,P);
if (!err) N = new CGAL_Nef_polyhedron3(P);
}
catch (const CGAL::Assertion_exception &e) {
PRINTB("Alternate construction failed. CGAL error in CGAL_Nef_polyhedron3(): %s", e.what());
}
CGAL::set_error_behaviour(old_behaviour);
return CGAL_Nef_polyhedron(N);

View File

@ -96,6 +96,7 @@ PolySet *CGAL_Nef_polyhedron::convertToPolyset()
}
else if (this->dim == 3) {
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
ps = new PolySet();
bool err = true;
std::string errmsg("");
CGAL_Polyhedron P;
@ -107,11 +108,11 @@ PolySet *CGAL_Nef_polyhedron::convertToPolyset()
err = true;
errmsg = std::string(e.what());
}
if (!err) err = createPolySetFromPolyhedron(P, *ps);
if (err) {
PRINT("ERROR: CGAL NefPolyhedron->Polyhedron conversion failed.");
if (errmsg!="") PRINTB("ERROR: %s",errmsg);
} else {
ps = createPolySetFromPolyhedron(P);
delete ps; ps = NULL;
}
CGAL::set_error_behaviour(old_behaviour);
}

View File

@ -8,10 +8,9 @@
#include <map>
PolySet *createPolySetFromPolyhedron(const CGAL_Polyhedron &p)
bool createPolySetFromPolyhedron(const CGAL_Polyhedron &p, PolySet &ps)
{
PolySet *ps = new PolySet();
bool err = false;
typedef CGAL_Polyhedron::Vertex Vertex;
typedef CGAL_Polyhedron::Vertex_const_iterator VCI;
typedef CGAL_Polyhedron::Facet_const_iterator FCI;
@ -35,13 +34,13 @@ PolySet *createPolySetFromPolyhedron(const CGAL_Polyhedron &p)
double x3 = CGAL::to_double(v3.point().x());
double y3 = CGAL::to_double(v3.point().y());
double z3 = CGAL::to_double(v3.point().z());
ps->append_poly();
ps->append_vertex(x1, y1, z1);
ps->append_vertex(x2, y2, z2);
ps->append_vertex(x3, y3, z3);
ps.append_poly();
ps.append_vertex(x1, y1, z1);
ps.append_vertex(x2, y2, z2);
ps.append_vertex(x3, y3, z3);
} while (hc != hc_end);
}
return ps;
return err;
}
#undef GEN_SURFACE_DEBUG
@ -127,22 +126,20 @@ public:
}
};
CGAL_Polyhedron *createPolyhedronFromPolySet(const PolySet &ps)
bool createPolyhedronFromPolySet(const PolySet &ps, CGAL_Polyhedron &p)
{
CGAL_Polyhedron *P = NULL;
bool err = false;
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
try {
P = new CGAL_Polyhedron;
CGAL_Build_PolySet builder(ps);
P->delegate(builder);
p.delegate(builder);
}
catch (const CGAL::Assertion_exception &e) {
PRINTB("CGAL error in CGAL_Build_PolySet: %s", e.what());
delete P;
P = NULL;
err = true;
}
CGAL::set_error_behaviour(old_behaviour);
return P;
return err;
}
CGAL_Iso_cuboid_3 bounding_box( const CGAL_Nef_polyhedron3 &N )

View File

@ -2,8 +2,9 @@
#define CGALUTILS_H_
#include <cgal.h>
class PolySet *createPolySetFromPolyhedron(const CGAL_Polyhedron &p);
CGAL_Polyhedron *createPolyhedronFromPolySet(const class PolySet &ps);
#include "polyset.h"
bool createPolySetFromPolyhedron(const CGAL_Polyhedron &p, PolySet &ps);
bool createPolyhedronFromPolySet(const PolySet &ps, CGAL_Polyhedron &p);
CGAL_Iso_cuboid_3 bounding_box( const CGAL_Nef_polyhedron3 &N );
CGAL_Iso_rectangle_2e bounding_box( const CGAL_Nef_polyhedron2 &N );

View File

@ -335,3 +335,178 @@ void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, Vector2d scale, bool u
dxf.paths[path[2]].is_inner = !up;
}
}
/* Tessellation of 3d PolySet faces
This code is for tessellating the faces of a 3d PolySet, assuming that
the faces are near-planar polygons.
We do the tessellation by projecting each polygon of the Polyset onto a
2-d plane, then running a 2d tessellation algorithm on the projected 2d
polygon. Then we project each of the newly generated 2d 'tiles' (the
polygons used for tessellation, typically triangles) back up into 3d
space.
(in reality as of writing, we dont need to do a back-projection from 2d->3d
because the algorithm we are using doesn't create any new points, and we can
just use a 'map' to associate 3d points with 2d points).
The code assumes the input polygons are simple, non-intersecting, without
holes, without duplicate input points, and with proper orientation.
The purpose of this code is originally to fix github issue 349. Our CGAL
kernel does not accept polygons for Nef_Polyhedron_3 if each of the
points is not exactly coplanar. "Near-planar" or "Almost planar" polygons
often occur due to rounding issues on, for example, polyhedron() input.
By tessellating the 3d polygon into individual smaller tiles that
are perfectly coplanar (triangles, for example), we can get CGAL to accept
the polyhedron() input.
*/
typedef enum { XYPLANE, YZPLANE, XZPLANE, NONE } projection_t;
// this is how we make 3d points appear as though they were 2d points to
//the tessellation algorithm.
Vector2d get_projected_point( Vector3d v, projection_t projection ) {
Vector2d v2(0,0);
if (projection==XYPLANE) { v2.x() = v.x(); v2.y() = v.y(); }
else if (projection==XZPLANE) { v2.x() = v.x(); v2.y() = v.z(); }
else if (projection==YZPLANE) { v2.x() = v.y(); v2.y() = v.z(); }
return v2;
}
CGAL_Point_3 cgp( Vector3d v ) { return CGAL_Point_3( v.x(), v.y(), v.z() ); }
/* Find a 'good' 2d projection for a given 3d polygon. the XY, YZ, or XZ
plane. This is needed because near-planar polygons in 3d can have 'bad'
projections into 2d. For example if the square 0,0,0 0,1,0 0,1,1 0,0,1
is projected onto the XY plane you will not get a polygon, you wil get
a skinny line thing. It's better to project that square onto the yz
plane.*/
projection_t find_good_projection( PolySet::Polygon pgon ) {
// step 1 - find 3 non-collinear points in the input
if (pgon.size()<3) return NONE;
Vector3d v1,v2,v3;
v1 = v2 = v3 = pgon[0];
for (size_t i=0;i<pgon.size();i++) {
if (pgon[i]!=v1) { v2=pgon[i]; break; }
}
if (v1==v2) return NONE;
for (size_t i=0;i<pgon.size();i++) {
if (!CGAL::collinear( cgp(v1), cgp(v2), cgp(pgon[i]) )) {
v3=pgon[i]; break;
}
}
if (CGAL::collinear( cgp(v1), cgp(v2), cgp(v3) ) ) return NONE;
// step 2 - find which direction is best for projection. planes use
// the equation ax+by+cz+d = 0. a,b, and c determine the direction the
// plane is in. we want to find which projection of the 'normal vector'
// would make the smallest shadow if projected onto the XY, YZ, or XZ
// plane. 'quadrance' (distance squared) can tell this w/o using sqrt.
CGAL::Plane_3<CGAL_Kernel3> pl( cgp(v1), cgp(v2), cgp(v3) );
NT3 qxy = pl.a()*pl.a()+pl.b()*pl.b();
NT3 qyz = pl.b()*pl.b()+pl.c()*pl.c();
NT3 qxz = pl.c()*pl.c()+pl.a()*pl.a();
NT3 min = std::min(qxy,std::min(qyz,qxz));
if (min==qxy) return XYPLANE;
else if (min==qyz) return YZPLANE;
return XZPLANE;
}
/* triangulate the given 3d polygon using CGAL's 2d Constrained Delaunay
algorithm. Project the polygon's points into 2d using the given projection
before performing the triangulation. This code assumes input polygon is
simple, no holes, no self-intersections, no duplicate points, and is
properly oriented. output is a sequence of 3d triangles. */
bool triangulate_polygon( const PolySet::Polygon &pgon, std::vector<PolySet::Polygon> &triangles, projection_t projection )
{
bool err = false;
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
try {
CDT cdt;
std::vector<Vertex_handle> vhandles;
std::map<CDTPoint,Vector3d> vertmap;
CGAL::Orientation original_orientation;
std::vector<CDTPoint> orienpgon;
for (size_t i = 0; i < pgon.size(); i++) {
Vector3d v3 = pgon.at(i);
Vector2d v2 = get_projected_point( v3, projection );
CDTPoint cdtpoint = CDTPoint(v2.x(),v2.y());
vertmap[ cdtpoint ] = v3;
Vertex_handle vh = cdt.insert( cdtpoint );
vhandles.push_back(vh);
orienpgon.push_back( cdtpoint );
}
original_orientation = CGAL::orientation_2( orienpgon.begin(),orienpgon.end() );
for (size_t i = 0; i < vhandles.size(); i++ ) {
int vindex1 = (i+0);
int vindex2 = (i+1)%vhandles.size();
cdt.insert_constraint( vhandles[vindex1], vhandles[vindex2] );
}
std::list<CDTPoint> list_of_seeds;
CGAL::refine_Delaunay_mesh_2_without_edge_refinement(cdt,
list_of_seeds.begin(), list_of_seeds.end(), DummyCriteria<CDT>());
CDT::Finite_faces_iterator fit;
for( fit=cdt.finite_faces_begin(); fit!=cdt.finite_faces_end(); fit++ )
{
if(fit->is_in_domain()) {
CDTPoint p1 = cdt.triangle( fit )[0];
CDTPoint p2 = cdt.triangle( fit )[1];
CDTPoint p3 = cdt.triangle( fit )[2];
Vector3d v1 = vertmap[p1];
Vector3d v2 = vertmap[p2];
Vector3d v3 = vertmap[p3];
PolySet::Polygon pgon;
if (CGAL::orientation(p1,p2,p3)==original_orientation) {
pgon.push_back(v1);
pgon.push_back(v2);
pgon.push_back(v3);
} else {
pgon.push_back(v3);
pgon.push_back(v2);
pgon.push_back(v1);
}
triangles.push_back( pgon );
}
}
} catch (const CGAL::Assertion_exception &e) {
PRINTB("CGAL error in dxftess triangulate_polygon: %s", e.what());
err = true;
}
CGAL::set_error_behaviour(old_behaviour);
return err;
}
/* Given a 3d PolySet with 'near planar' polygonal faces, Tessellate the
faces. As of writing, our only tessellation method is Triangulation
using CGAL's Constrained Delaunay algorithm. This code assumes the input
polyset has simple polygon faces with no holes, no self intersections, no
duplicate points, and proper orientation. */
void tessellate_3d_faces( const PolySet &inps, PolySet &outps ) {
for (size_t i = 0; i < inps.polygons.size(); i++) {
const PolySet::Polygon pgon = inps.polygons[i];
if (pgon.size()<3) {
PRINT("WARNING: PolySet has polygon with <3 points");
continue;
}
projection_t goodproj = find_good_projection( pgon );
if (goodproj==NONE) {
PRINT("WARNING: PolySet has degenerate polygon");
continue;
}
std::vector<PolySet::Polygon> triangles;
bool err = triangulate_polygon( pgon, triangles, goodproj );
if (!err) for (size_t j=0;j<triangles.size();j++) {
PolySet::Polygon t = triangles[j];
outps.append_poly();
outps.append_vertex(t[0].x(),t[0].y(),t[0].z());
outps.append_vertex(t[1].x(),t[1].y(),t[1].z());
outps.append_vertex(t[2].x(),t[2].y(),t[2].z());
}
}
}
// End of PolySet face tessellation code

View File

@ -7,5 +7,6 @@ class DxfData;
class PolySet;
void dxf_tesselate(PolySet *ps, DxfData &dxf, double rot, Vector2d scale, bool up, bool do_triangle_splitting, double h);
void dxf_border_to_ps(PolySet *ps, const DxfData &dxf);
void tessellate_3d_faces( const PolySet &inps, PolySet &outps );
#endif

View File

@ -284,7 +284,9 @@ PolySet *ImportNode::evaluate_polyset(class PolySetEvaluator *) const
file >> poly;
file.close();
p = createPolySetFromPolyhedron(poly);
p = new PolySet();
bool err = createPolySetFromPolyhedron(poly, *p);
if (err) delete p;
}
#else
PRINT("WARNING: OFF import requires CGAL.");

View File

@ -26,7 +26,7 @@ public:
void append_vertex(double x, double y, double z = 0.0);
void insert_vertex(double x, double y, double z = 0.0);
size_t memsize() const;
BoundingBox getBoundingBox() const;
#define CSGMODE_DIFFERENCE_FLAG 0x10

View File

@ -103,7 +103,7 @@ public:
double fn, fs, fa;
primitive_type_e type;
int convexity;
Value points, paths, triangles;
Value points, paths, faces;
virtual PolySet *evaluate_polyset(class PolySetEvaluator *) const;
};
@ -156,7 +156,7 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta
args += Assignment("h", NULL), Assignment("r1", NULL), Assignment("r2", NULL), Assignment("center", NULL);
break;
case POLYHEDRON:
args += Assignment("points", NULL), Assignment("triangles", NULL), Assignment("convexity", NULL);
args += Assignment("points", NULL), Assignment("triangles", NULL), Assignment("convexity", NULL), Assignment("faces", NULL);
break;
case SQUARE:
args += Assignment("size", NULL), Assignment("center", NULL);
@ -235,7 +235,11 @@ AbstractNode *PrimitiveModule::instantiate(const Context *ctx, const ModuleInsta
if (type == POLYHEDRON) {
node->points = c.lookup_variable("points");
node->triangles = c.lookup_variable("triangles");
node->faces = c.lookup_variable("faces");
if (node->faces.type() == Value::UNDEFINED) {
// backwards compatable
node->faces = c.lookup_variable("triangles");
}
}
if (type == SQUARE) {
@ -480,11 +484,11 @@ sphere_next_r2:
if (this->type == POLYHEDRON)
{
p->convexity = this->convexity;
for (size_t i=0; i<this->triangles.toVector().size(); i++)
for (size_t i=0; i<this->faces.toVector().size(); i++)
{
p->append_poly();
for (size_t j=0; j<this->triangles.toVector()[i].toVector().size(); j++) {
size_t pt = this->triangles.toVector()[i].toVector()[j].toDouble();
for (size_t j=0; j<this->faces.toVector()[i].toVector().size(); j++) {
size_t pt = this->faces.toVector()[i].toVector()[j].toDouble();
if (pt < this->points.toVector().size()) {
double px, py, pz;
if (this->points.toVector()[pt].getVec3(px, py, pz))
@ -610,7 +614,7 @@ std::string PrimitiveNode::toString() const
break;
case POLYHEDRON:
stream << "(points = " << this->points
<< ", triangles = " << this->triangles
<< ", faces = " << this->faces
<< ", convexity = " << this->convexity << ")";
break;
case SQUARE:

View File

@ -0,0 +1,157 @@
// Used to cause issue #349
// Very slightly non-planar polyhedron
polyhedron(faces=[[3,2,1,0],[7,6,5,4],[0,1,6,7],[1,2,5,6],[2,3,4,5],[3,0,7,4]],
points=[
[0.0174497,-0.0174524,0.999695],
[1.0173,-0.0174524,0.982243],
[1.0176,0.982395,0.999693],
[0.0177543,0.982395,1.01715],
[0.000304586,0.999848,0.0174497],
[1.00015,0.999848,-0.00000265809],
[0.999848,-0.0000000000000271051,-0.0174524],
[0,0,0]]);
// Really non-planar polyhedron
translate([2,0,0]) polyhedron(faces=[[3,2,1,0],[7,6,5,4],[0,1,6,7],[1,2,5,6],[2,3,4,5],[3,0,7,4]],
points=[
[0,0,1],
[1,0.2,1],
[1,1,1],
[0,1,1],
[0,1,0],
[1,1,0],
[1,0,0],
[0,0,0]]);
// Real-world example: truncated icosidodecahedron
translate([4.5,0.5,0.5]) scale(0.02) polyhedron(points = [
[-10., -13.090169943749475, -34.270509831248425],
[-10., -13.090169943749475, 34.270509831248425],
[-10., 13.090169943749475, -34.270509831248425],
[-10., 13.090169943749475, 34.270509831248425],
[-5., -5., -37.3606797749979], [-5., -5., 37.3606797749979],
[-5., 5., -37.3606797749979], [-5., 5., 37.3606797749979],
[-5., -37.3606797749979, -5.], [-5., -37.3606797749979, 5.],
[-5., -21.18033988749895, -31.18033988749895],
[-5., -21.18033988749895, 31.18033988749895], [-5., 37.3606797749979, -5.],
[-5., 37.3606797749979, 5.], [-5., 21.18033988749895, -31.18033988749895],
[-5., 21.18033988749895, 31.18033988749895], [5., -5., -37.3606797749979],
[5., -5., 37.3606797749979], [5., 5., -37.3606797749979],
[5., 5., 37.3606797749979], [5., -37.3606797749979, -5.],
[5., -37.3606797749979, 5.], [5., -21.18033988749895, -31.18033988749895],
[5., -21.18033988749895, 31.18033988749895], [5., 37.3606797749979, -5.],
[5., 37.3606797749979, 5.], [5., 21.18033988749895, -31.18033988749895],
[5., 21.18033988749895, 31.18033988749895], [10., -13.090169943749475,
-34.270509831248425], [10., -13.090169943749475, 34.270509831248425],
[10., 13.090169943749475, -34.270509831248425],
[10., 13.090169943749475, 34.270509831248425],
[-34.270509831248425, -10., -13.090169943749475],
[-34.270509831248425, -10., 13.090169943749475],
[-34.270509831248425, 10., -13.090169943749475],
[-34.270509831248425, 10., 13.090169943749475],
[-29.270509831248425, -18.090169943749473, -16.18033988749895],
[-29.270509831248425, -18.090169943749473, 16.18033988749895],
[-29.270509831248425, 18.090169943749473, -16.18033988749895],
[-29.270509831248425, 18.090169943749473, 16.18033988749895],
[-18.090169943749473, -16.18033988749895, -29.270509831248425],
[-18.090169943749473, -16.18033988749895, 29.270509831248425],
[-18.090169943749473, 16.18033988749895, -29.270509831248425],
[-18.090169943749473, 16.18033988749895, 29.270509831248425],
[-13.090169943749475, -34.270509831248425, -10.],
[-13.090169943749475, -34.270509831248425, 10.],
[-13.090169943749475, -24.270509831248425, -26.18033988749895],
[-13.090169943749475, -24.270509831248425, 26.18033988749895],
[-13.090169943749475, 24.270509831248425, -26.18033988749895],
[-13.090169943749475, 24.270509831248425, 26.18033988749895],
[-13.090169943749475, 34.270509831248425, -10.],
[-13.090169943749475, 34.270509831248425, 10.],
[-26.18033988749895, -13.090169943749475, -24.270509831248425],
[-26.18033988749895, -13.090169943749475, 24.270509831248425],
[-26.18033988749895, 13.090169943749475, -24.270509831248425],
[-26.18033988749895, 13.090169943749475, 24.270509831248425],
[-37.3606797749979, -5., -5.], [-37.3606797749979, -5., 5.],
[-37.3606797749979, 5., -5.], [-37.3606797749979, 5., 5.],
[-16.18033988749895, -29.270509831248425, -18.090169943749473],
[-16.18033988749895, -29.270509831248425, 18.090169943749473],
[-16.18033988749895, 29.270509831248425, -18.090169943749473],
[-16.18033988749895, 29.270509831248425, 18.090169943749473],
[-31.18033988749895, -5., -21.18033988749895],
[-31.18033988749895, -5., 21.18033988749895],
[-31.18033988749895, 5., -21.18033988749895],
[-31.18033988749895, 5., 21.18033988749895],
[-21.18033988749895, -31.18033988749895, -5.],
[-21.18033988749895, -31.18033988749895, 5.],
[-21.18033988749895, 31.18033988749895, -5.],
[-21.18033988749895, 31.18033988749895, 5.],
[-24.270509831248425, -26.18033988749895, -13.090169943749475],
[-24.270509831248425, -26.18033988749895, 13.090169943749475],
[-24.270509831248425, 26.18033988749895, -13.090169943749475],
[-24.270509831248425, 26.18033988749895, 13.090169943749475],
[16.18033988749895, -29.270509831248425, -18.090169943749473],
[16.18033988749895, -29.270509831248425, 18.090169943749473],
[16.18033988749895, 29.270509831248425, -18.090169943749473],
[16.18033988749895, 29.270509831248425, 18.090169943749473],
[24.270509831248425, -26.18033988749895, -13.090169943749475],
[24.270509831248425, -26.18033988749895, 13.090169943749475],
[24.270509831248425, 26.18033988749895, -13.090169943749475],
[24.270509831248425, 26.18033988749895, 13.090169943749475],
[37.3606797749979, -5., -5.], [37.3606797749979, -5., 5.],
[37.3606797749979, 5., -5.], [37.3606797749979, 5., 5.],
[21.18033988749895, -31.18033988749895, -5.],
[21.18033988749895, -31.18033988749895, 5.],
[21.18033988749895, 31.18033988749895, -5.],
[21.18033988749895, 31.18033988749895, 5.],
[13.090169943749475, -34.270509831248425, -10.],
[13.090169943749475, -34.270509831248425, 10.],
[13.090169943749475, -24.270509831248425, -26.18033988749895],
[13.090169943749475, -24.270509831248425, 26.18033988749895],
[13.090169943749475, 24.270509831248425, -26.18033988749895],
[13.090169943749475, 24.270509831248425, 26.18033988749895],
[13.090169943749475, 34.270509831248425, -10.],
[13.090169943749475, 34.270509831248425, 10.],
[26.18033988749895, -13.090169943749475, -24.270509831248425],
[26.18033988749895, -13.090169943749475, 24.270509831248425],
[26.18033988749895, 13.090169943749475, -24.270509831248425],
[26.18033988749895, 13.090169943749475, 24.270509831248425],
[31.18033988749895, -5., -21.18033988749895],
[31.18033988749895, -5., 21.18033988749895],
[31.18033988749895, 5., -21.18033988749895],
[31.18033988749895, 5., 21.18033988749895],
[18.090169943749473, -16.18033988749895, -29.270509831248425],
[18.090169943749473, -16.18033988749895, 29.270509831248425],
[18.090169943749473, 16.18033988749895, -29.270509831248425],
[18.090169943749473, 16.18033988749895, 29.270509831248425],
[29.270509831248425, -18.090169943749473, -16.18033988749895],
[29.270509831248425, -18.090169943749473, 16.18033988749895],
[29.270509831248425, 18.090169943749473, -16.18033988749895],
[29.270509831248425, 18.090169943749473, 16.18033988749895],
[34.270509831248425, -10., -13.090169943749475],
[34.270509831248425, -10., 13.090169943749475],
[34.270509831248425, 10., -13.090169943749475],
[34.270509831248425, 10., 13.090169943749475]],faces =
[[41, 53, 65, 67, 55, 43, 3, 7, 5, 1], [100, 104, 106, 102, 110, 30, 18, 16,
28, 108], [11, 1, 5, 17, 29, 23], [18, 30, 26, 14, 2, 6],
[33, 37, 73, 69, 68, 72, 36, 32, 56, 57], [91, 90, 82, 114, 118, 86, 87,
119, 115, 83], [81, 113, 117, 85, 84, 116, 112, 80, 88, 89],
[59, 58, 34, 38, 74, 70, 71, 75, 39, 35], [0, 10, 22, 28, 16, 4],
[15, 27, 31, 19, 7, 3], [64, 52, 40, 0, 4, 6, 2, 42, 54, 66],
[19, 31, 111, 103, 107, 105, 101, 109, 29, 17], [96, 110, 102, 114, 82, 78],
[53, 41, 47, 61, 73, 37], [43, 49, 15, 3], [94, 108, 28, 22],
[23, 29, 109, 95], [2, 14, 48, 42], [36, 72, 60, 46, 40, 52],
[79, 83, 115, 103, 111, 97], [69, 45, 9, 8, 44, 68],
[24, 98, 90, 91, 99, 25], [77, 95, 109, 101, 113, 81],
[42, 48, 62, 74, 38, 54], [40, 46, 10, 0], [97, 111, 31, 27],
[44, 8, 20, 92, 76, 94, 22, 10, 46, 60], [63, 51, 13, 25, 99, 79, 97, 27,
15, 49], [26, 30, 110, 96], [1, 11, 47, 41], [55, 39, 75, 63, 49, 43],
[80, 112, 100, 108, 94, 76], [48, 14, 26, 96, 78, 98, 24, 12, 50, 62],
[61, 47, 11, 23, 95, 77, 93, 21, 9, 45], [71, 70, 50, 12, 13, 51],
[93, 89, 88, 92, 20, 21], [102, 106, 118, 114], [65, 53, 37, 33],
[74, 62, 50, 70], [77, 81, 89, 93], [101, 105, 117, 113], [66, 54, 38, 34],
[73, 61, 45, 69], [78, 82, 90, 98], [32, 36, 52, 64], [115, 119, 107, 103],
[92, 88, 80, 76], [71, 51, 63, 75], [56, 32, 64, 66, 34, 58],
[107, 119, 87, 85, 117, 105], [35, 39, 55, 67], [112, 116, 104, 100],
[99, 91, 83, 79], [68, 44, 60, 72], [57, 59, 35, 67, 65, 33],
[116, 84, 86, 118, 106, 104], [4, 16, 18, 6], [7, 19, 17, 5],
[12, 24, 25, 13], [9, 21, 20, 8], [56, 58, 59, 57], [85, 87, 86, 84]]
);

View File

@ -831,8 +831,8 @@ list(APPEND DUMPTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/escape-test
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/localfiles_dir/localfiles-compatibility-test.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allexpressions.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allfunctions.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/stl-cgal-convert_to_Polyhedron-crash.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allmodules.scad)
${CMAKE_SOURCE_DIR}/../testdata/scad/misc/allmodules.scad
${CMAKE_SOURCE_DIR}/../testdata/scad/bugs/stl-cgal-convert_to_Polyhedron-crash.scad)
list(APPEND CGALPNGTEST_FILES ${FEATURES_FILES} ${SCAD_DXF_FILES} ${EXAMPLE_FILES})
list(APPEND CGALPNGTEST_FILES ${CMAKE_SOURCE_DIR}/../testdata/scad/misc/include-tests.scad

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.5 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

@ -26,7 +26,7 @@ group() {
cube(size = [1, 1, 1], center = false);
sphere($fn = 0, $fa = 12, $fs = 2, r = 1);
cylinder($fn = 0, $fa = 12, $fs = 2, h = 1, r1 = 1, r2 = 1, center = false);
polyhedron(points = undef, triangles = undef, convexity = 1);
polyhedron(points = undef, faces = undef, convexity = 1);
square(size = [1, 1], center = false);
circle($fn = 0, $fa = 12, $fs = 2, r = 1);
polygon(points = undef, paths = undef, convexity = 1);

View File

@ -1,3 +1,3 @@
group() {
polyhedron(points = [[10, 0, 0], [0, 10, 0], [-10, 0, 0], [0, -10, 0], [0, 0, 10]], triangles = [[0, 1, 2, 3], [4, 1, 0], [4, 2, 1], [4, 3, 2], [4, 0, 3]], convexity = 1);
polyhedron(points = [[10, 0, 0], [0, 10, 0], [-10, 0, 0], [0, -10, 0], [0, 0, 10]], faces = [[0, 1, 2, 3], [4, 1, 0], [4, 2, 1], [4, 3, 2], [4, 0, 3]], convexity = 1);
}

File diff suppressed because one or more lines are too long

View File

@ -1,28 +1,28 @@
group() {
group() {
polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], triangles = [[0, 4, 2], [0, 2, 5], [0, 3, 4], [0, 5, 3], [1, 2, 4], [1, 5, 2], [1, 4, 3], [1, 3, 5]], convexity = 1);
polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], faces = [[0, 4, 2], [0, 2, 5], [0, 3, 4], [0, 5, 3], [1, 2, 4], [1, 5, 2], [1, 4, 3], [1, 3, 5]], convexity = 1);
multmatrix([[1, 0, 0, 2], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], triangles = [[0, 4, 2], [0, 2, 5], [0, 3, 4], [0, 5, 3], [1, 2, 4], [1, 5, 2], [1, 3, 4], [1, 3, 5]], convexity = 1);
polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], faces = [[0, 4, 2], [0, 2, 5], [0, 3, 4], [0, 5, 3], [1, 2, 4], [1, 5, 2], [1, 3, 4], [1, 3, 5]], convexity = 1);
}
multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], triangles = [[0, 2, 4], [0, 5, 2], [0, 4, 3], [0, 3, 5], [1, 4, 2], [1, 2, 5], [1, 3, 4], [1, 5, 3]], convexity = 1);
polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], faces = [[0, 2, 4], [0, 5, 2], [0, 4, 3], [0, 3, 5], [1, 4, 2], [1, 2, 5], [1, 3, 4], [1, 5, 3]], convexity = 1);
}
multmatrix([[1, 0, 0, 6], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
polyhedron(points = [[-0.8, -0.8, -0.8], [0, 0, -0.8], [0.8, -0.8, -0.8], [0.8, 0.8, -0.8], [-0.8, 0.8, -0.8], [-0.8, -0.8, 0.8], [0, 0, 0.8], [0.8, -0.8, 0.8], [0.8, 0.8, 0.8], [-0.8, 0.8, 0.8]], triangles = [[0, 1, 2, 3, 4], [5, 6, 1, 0], [6, 7, 2, 1], [7, 8, 3, 2], [8, 9, 4, 3], [9, 5, 0, 4], [9, 8, 7, 6, 5]], convexity = 2);
polyhedron(points = [[-0.8, -0.8, -0.8], [0, 0, -0.8], [0.8, -0.8, -0.8], [0.8, 0.8, -0.8], [-0.8, 0.8, -0.8], [-0.8, -0.8, 0.8], [0, 0, 0.8], [0.8, -0.8, 0.8], [0.8, 0.8, 0.8], [-0.8, 0.8, 0.8]], faces = [[0, 1, 2, 3, 4], [5, 6, 1, 0], [6, 7, 2, 1], [7, 8, 3, 2], [8, 9, 4, 3], [9, 5, 0, 4], [9, 8, 7, 6, 5]], convexity = 2);
}
}
multmatrix([[1, 0, 0, 0], [0, 1, 0, 2], [0, 0, 1, 0], [0, 0, 0, 1]]) {
difference() {
group() {
polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], triangles = [[0, 4, 2], [0, 2, 5], [0, 3, 4], [0, 5, 3], [1, 2, 4], [1, 5, 2], [1, 4, 3], [1, 3, 5]], convexity = 1);
polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], faces = [[0, 4, 2], [0, 2, 5], [0, 3, 4], [0, 5, 3], [1, 2, 4], [1, 5, 2], [1, 4, 3], [1, 3, 5]], convexity = 1);
multmatrix([[1, 0, 0, 2], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], triangles = [[0, 4, 2], [0, 2, 5], [0, 3, 4], [0, 5, 3], [1, 2, 4], [1, 5, 2], [1, 3, 4], [1, 3, 5]], convexity = 1);
polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], faces = [[0, 4, 2], [0, 2, 5], [0, 3, 4], [0, 5, 3], [1, 2, 4], [1, 5, 2], [1, 3, 4], [1, 3, 5]], convexity = 1);
}
multmatrix([[1, 0, 0, 4], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], triangles = [[0, 2, 4], [0, 5, 2], [0, 4, 3], [0, 3, 5], [1, 4, 2], [1, 2, 5], [1, 3, 4], [1, 5, 3]], convexity = 1);
polyhedron(points = [[1, 0, 0], [-1, 0, 0], [0, 1, 0], [0, -1, 0], [0, 0, 1], [0, 0, -1]], faces = [[0, 2, 4], [0, 5, 2], [0, 4, 3], [0, 3, 5], [1, 4, 2], [1, 2, 5], [1, 3, 4], [1, 5, 3]], convexity = 1);
}
multmatrix([[1, 0, 0, 6], [0, 1, 0, 0], [0, 0, 1, 0], [0, 0, 0, 1]]) {
polyhedron(points = [[-0.8, -0.8, -0.8], [0, 0, -0.8], [0.8, -0.8, -0.8], [0.8, 0.8, -0.8], [-0.8, 0.8, -0.8], [-0.8, -0.8, 0.8], [0, 0, 0.8], [0.8, -0.8, 0.8], [0.8, 0.8, 0.8], [-0.8, 0.8, 0.8]], triangles = [[0, 1, 2, 3, 4], [5, 6, 1, 0], [6, 7, 2, 1], [7, 8, 3, 2], [8, 9, 4, 3], [9, 5, 0, 4], [9, 8, 7, 6, 5]], convexity = 2);
polyhedron(points = [[-0.8, -0.8, -0.8], [0, 0, -0.8], [0.8, -0.8, -0.8], [0.8, 0.8, -0.8], [-0.8, 0.8, -0.8], [-0.8, -0.8, 0.8], [0, 0, 0.8], [0.8, -0.8, 0.8], [0.8, 0.8, 0.8], [-0.8, 0.8, 0.8]], faces = [[0, 1, 2, 3, 4], [5, 6, 1, 0], [6, 7, 2, 1], [7, 8, 3, 2], [8, 9, 4, 3], [9, 5, 0, 4], [9, 8, 7, 6, 5]], convexity = 2);
}
}
multmatrix([[1, 0, 0, 3], [0, 1, 0, 0], [0, 0, 1, 2], [0, 0, 0, 1]]) {

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.7 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 6.9 KiB