mirror of https://github.com/vitalif/openscad
Use CLipperLib's PolyTree to identify negative contours
parent
1c8221004a
commit
5a4ff8e39a
|
@ -63,6 +63,7 @@ PolySet *CGAL_Nef_polyhedron::convertToPolyset() const
|
|||
if (this->dim == 3) {
|
||||
CGAL::Failure_behaviour old_behaviour = CGAL::set_error_behaviour(CGAL::THROW_EXCEPTION);
|
||||
ps = new PolySet();
|
||||
ps->setConvexity(this->convexity);
|
||||
bool err = true;
|
||||
std::string errmsg("");
|
||||
CGAL_Polyhedron P;
|
||||
|
|
|
@ -157,7 +157,7 @@ Polygon2d *GeometryEvaluator::applyHull2D(const AbstractNode &node)
|
|||
std::list<CGAL_Nef_polyhedron2::Point> points;
|
||||
BOOST_FOREACH(const Polygon2d *p, children) {
|
||||
BOOST_FOREACH(const Outline2d &o, p->outlines()) {
|
||||
BOOST_FOREACH(const Vector2d &v, o) {
|
||||
BOOST_FOREACH(const Vector2d &v, o.vertices) {
|
||||
points.push_back(CGAL_Nef_polyhedron2::Point(v[0], v[1]));
|
||||
}
|
||||
}
|
||||
|
@ -170,7 +170,7 @@ Polygon2d *GeometryEvaluator::applyHull2D(const AbstractNode &node)
|
|||
// Construct Polygon2d
|
||||
Outline2d outline;
|
||||
BOOST_FOREACH(const CGAL_Nef_polyhedron2::Point &p, result) {
|
||||
outline.push_back(Vector2d(CGAL::to_double(p[0]), CGAL::to_double(p[1])));
|
||||
outline.vertices.push_back(Vector2d(CGAL::to_double(p[0]), CGAL::to_double(p[1])));
|
||||
}
|
||||
geometry = new Polygon2d();
|
||||
geometry->addOutline(outline);
|
||||
|
@ -251,14 +251,14 @@ Polygon2d *GeometryEvaluator::applyMinkowski2D(const AbstractNode &node)
|
|||
// The results may contain holes due to ClipperLib failing to maintain
|
||||
// solidity of minkowski results:
|
||||
// https://sourceforge.net/p/polyclipping/discussion/1148419/thread/8488d4e8/
|
||||
ClipperLib::Clipper clipper;
|
||||
ClipperLib::Paths paths;
|
||||
BOOST_FOREACH(ClipperLib::Path &p, result) {
|
||||
if (ClipperLib::Orientation(p)) std::reverse(p.begin(), p.end());
|
||||
clipper.AddPath(p, ClipperLib::ptSubject, true);
|
||||
paths.push_back(p);
|
||||
}
|
||||
clipper.Execute(ClipperLib::ctUnion, result, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
|
||||
|
||||
return ClipperUtils::toPolygon2d(result);
|
||||
std::vector<ClipperLib::Paths> pathsvector;
|
||||
pathsvector.push_back(paths);
|
||||
return ClipperUtils::apply(pathsvector, ClipperLib::ctUnion);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
@ -416,19 +416,34 @@ Response GeometryEvaluator::visit(State &state, const AbstractNode &node)
|
|||
return ContinueTraversal;
|
||||
}
|
||||
|
||||
/*
|
||||
FIXME: Where do we handle nodes which should be sent to CGAL?
|
||||
|
||||
/*!
|
||||
RenderNodes just pass on convexity
|
||||
*/
|
||||
Response GeometryEvaluator::visit(State &state, const RenderNode &node)
|
||||
{
|
||||
if (state.isPrefix() && isCached(node)) return PruneTraversal;
|
||||
if (state.isPostfix()) {
|
||||
shared_ptr<const Geometry> geom;
|
||||
shared_ptr<const class Geometry> geom;
|
||||
if (!isCached(node)) {
|
||||
CGAL_Nef_polyhedron N = this->cgalevaluator->evaluateCGALMesh(node);
|
||||
CGALCache::instance()->insert(this->tree.getIdString(node), N);
|
||||
ResultObject res = applyToChildren(node, OPENSCAD_UNION);
|
||||
|
||||
PolySet *ps = NULL;
|
||||
if (!N.isNull()) ps = N.convertToPolyset();
|
||||
geom.reset(ps);
|
||||
geom = res.constptr();
|
||||
if (shared_ptr<const PolySet> ps = dynamic_pointer_cast<const PolySet>(geom)) {
|
||||
// If we got a const object, make a copy
|
||||
shared_ptr<PolySet> newps;
|
||||
if (res.isConst()) newps.reset(new PolySet(*ps));
|
||||
else newps = dynamic_pointer_cast<PolySet>(res.ptr());
|
||||
newps->setConvexity(node.convexity);
|
||||
geom = newps;
|
||||
}
|
||||
else if (shared_ptr<const CGAL_Nef_polyhedron> N = dynamic_pointer_cast<const CGAL_Nef_polyhedron>(geom)) {
|
||||
// If we got a const object, make a copy
|
||||
shared_ptr<CGAL_Nef_polyhedron> newN;
|
||||
if (res.isConst()) newN.reset(new CGAL_Nef_polyhedron(*N));
|
||||
else newN = dynamic_pointer_cast<CGAL_Nef_polyhedron>(res.ptr());
|
||||
newN->setConvexity(node.convexity);
|
||||
geom = newN;
|
||||
}
|
||||
}
|
||||
else {
|
||||
geom = GeometryCache::instance()->get(this->tree.getIdString(node));
|
||||
|
@ -436,8 +451,7 @@ Response GeometryEvaluator::visit(State &state, const AbstractNode &node)
|
|||
addToParent(state, node, geom);
|
||||
}
|
||||
return ContinueTraversal;
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
/*!
|
||||
Leaf nodes can create their own geometry, so let them do that
|
||||
|
@ -579,14 +593,15 @@ static void add_slice(PolySet *ps, const Polygon2d &poly,
|
|||
// FIXME: If scale2 == 0 we need to handle tessellation separately
|
||||
bool splitfirst = sin(rot1 - rot2) >= 0.0;
|
||||
BOOST_FOREACH(const Outline2d &o, poly.outlines()) {
|
||||
Vector2d prev1 = trans1 * o[0];
|
||||
Vector2d prev2 = trans2 * o[0];
|
||||
for (size_t i=1;i<=o.size();i++) {
|
||||
Vector2d curr1 = trans1 * o[i % o.size()];
|
||||
Vector2d curr2 = trans2 * o[i % o.size()];
|
||||
Vector2d prev1 = trans1 * o.vertices[0];
|
||||
Vector2d prev2 = trans2 * o.vertices[0];
|
||||
for (size_t i=1;i<=o.vertices.size();i++) {
|
||||
Vector2d curr1 = trans1 * o.vertices[i % o.vertices.size()];
|
||||
Vector2d curr2 = trans2 * o.vertices[i % o.vertices.size()];
|
||||
ps->append_poly();
|
||||
|
||||
if (splitfirst) {
|
||||
// Make sure to split negative outlines correctly
|
||||
if (splitfirst xor !o.positive) {
|
||||
ps->insert_vertex(prev1[0], prev1[1], h1);
|
||||
ps->insert_vertex(curr2[0], curr2[1], h2);
|
||||
ps->insert_vertex(curr1[0], curr1[1], h1);
|
||||
|
@ -617,6 +632,13 @@ static void add_slice(PolySet *ps, const Polygon2d &poly,
|
|||
/*!
|
||||
Input to extrude should be clean. This means non-intersecting, correct winding order
|
||||
etc., the input coming from a library like Clipper.
|
||||
|
||||
We need to split quads in the same way (for e.g. thin shells). To do
|
||||
this, we need to know which contours are negative vs. positive:
|
||||
o Flag per contour (when sanitized)?
|
||||
o Hierarchy of contours?
|
||||
|
||||
FIXME: This is probably also important for rotate_extrude()
|
||||
*/
|
||||
static Geometry *extrudePolygon(const LinearExtrudeNode &node, const Polygon2d &poly)
|
||||
{
|
||||
|
@ -712,10 +734,10 @@ Response GeometryEvaluator::visit(State &state, const LinearExtrudeNode &node)
|
|||
|
||||
static void fill_ring(std::vector<Vector3d> &ring, const Outline2d &o, double a)
|
||||
{
|
||||
for (int i=0;i<o.size();i++) {
|
||||
ring[i][0] = o[i][0] * sin(a);
|
||||
ring[i][1] = o[i][0] * cos(a);
|
||||
ring[i][2] = o[i][1];
|
||||
for (int i=0;i<o.vertices.size();i++) {
|
||||
ring[i][0] = o.vertices[i][0] * sin(a);
|
||||
ring[i][1] = o.vertices[i][0] * cos(a);
|
||||
ring[i][2] = o.vertices[i][1];
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -731,7 +753,7 @@ static Geometry *rotatePolygon(const RotateExtrudeNode &node, const Polygon2d &p
|
|||
BOOST_FOREACH(const Outline2d &o, poly.outlines()) {
|
||||
double min_x = 0;
|
||||
double max_x = 0;
|
||||
BOOST_FOREACH(const Vector2d &v, o) {
|
||||
BOOST_FOREACH(const Vector2d &v, o.vertices) {
|
||||
min_x = fmin(min_x, v[0]);
|
||||
max_x = fmax(max_x, v[0]);
|
||||
|
||||
|
@ -744,23 +766,23 @@ static Geometry *rotatePolygon(const RotateExtrudeNode &node, const Polygon2d &p
|
|||
int fragments = get_fragments_from_r(max_x - min_x, node.fn, node.fs, node.fa);
|
||||
|
||||
std::vector<Vector3d> rings[2];
|
||||
rings[0].reserve(o.size());
|
||||
rings[1].reserve(o.size());
|
||||
rings[0].resize(o.vertices.size());
|
||||
rings[1].resize(o.vertices.size());
|
||||
|
||||
fill_ring(rings[0], o, -M_PI/2); // first ring
|
||||
for (int j = 0; j < fragments; j++) {
|
||||
double a = ((j+1)%fragments*2*M_PI) / fragments - M_PI/2; // start on the X axis
|
||||
fill_ring(rings[(j+1)%2], o, a);
|
||||
|
||||
for (size_t i=0;i<o.size();i++) {
|
||||
for (size_t i=0;i<o.vertices.size();i++) {
|
||||
ps->append_poly();
|
||||
ps->insert_vertex(rings[j%2][i]);
|
||||
ps->insert_vertex(rings[(j+1)%2][(i+1)%o.size()]);
|
||||
ps->insert_vertex(rings[j%2][(i+1)%o.size()]);
|
||||
ps->insert_vertex(rings[(j+1)%2][(i+1)%o.vertices.size()]);
|
||||
ps->insert_vertex(rings[j%2][(i+1)%o.vertices.size()]);
|
||||
ps->append_poly();
|
||||
ps->insert_vertex(rings[j%2][i]);
|
||||
ps->insert_vertex(rings[(j+1)%2][i]);
|
||||
ps->insert_vertex(rings[(j+1)%2][(i+1)%o.size()]);
|
||||
ps->insert_vertex(rings[(j+1)%2][(i+1)%o.vertices.size()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -884,11 +906,11 @@ Response GeometryEvaluator::visit(State &state, const ProjectionNode &node)
|
|||
sumclipper.AddPaths(result, ClipperLib::ptSubject, true);
|
||||
}
|
||||
}
|
||||
ClipperLib::Paths sumresult;
|
||||
ClipperLib::PolyTree sumresult;
|
||||
// This is key - without StrictlySimple, we tend to get self-intersecting results
|
||||
sumclipper.StrictlySimple(true);
|
||||
sumclipper.Execute(ClipperLib::ctUnion, sumresult, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
|
||||
if (sumresult.size() > 0) geom.reset(ClipperUtils::toPolygon2d(sumresult));
|
||||
if (sumresult.Total() > 0) geom.reset(ClipperUtils::toPolygon2d(sumresult));
|
||||
}
|
||||
else {
|
||||
shared_ptr<const Geometry> newgeom = applyToChildren3D(node, OPENSCAD_UNION).constptr();
|
||||
|
|
|
@ -30,6 +30,7 @@ public:
|
|||
virtual Response visit(State &state, const CsgNode &node);
|
||||
virtual Response visit(State &state, const CgaladvNode &node);
|
||||
virtual Response visit(State &state, const ProjectionNode &node);
|
||||
virtual Response visit(State &state, const RenderNode &node);
|
||||
|
||||
const Tree &getTree() const { return this->tree; }
|
||||
|
||||
|
|
|
@ -113,8 +113,8 @@ PolySet *Polygon2d::tessellate() const
|
|||
// Adds all vertices, and add all contours as constraints.
|
||||
BOOST_FOREACH(const Outline2d &outline, this->outlines()) {
|
||||
// Start with last point
|
||||
Polygon2DCGAL::CDT::Vertex_handle prev = cdt.insert(Polygon2DCGAL::Point(outline[outline.size()-1][0], outline[outline.size()-1][1]));
|
||||
BOOST_FOREACH(const Vector2d &v, outline) {
|
||||
Polygon2DCGAL::CDT::Vertex_handle prev = cdt.insert(Polygon2DCGAL::Point(outline.vertices[outline.vertices.size()-1][0], outline.vertices[outline.vertices.size()-1][1]));
|
||||
BOOST_FOREACH(const Vector2d &v, outline.vertices) {
|
||||
Polygon2DCGAL::CDT::Vertex_handle curr = cdt.insert(Polygon2DCGAL::Point(v[0], v[1]));
|
||||
if (prev != curr) { // Ignore duplicate vertices
|
||||
cdt.insert_constraint(prev, curr);
|
||||
|
|
|
@ -17,7 +17,7 @@ size_t Polygon2d::memsize() const
|
|||
{
|
||||
size_t mem = 0;
|
||||
BOOST_FOREACH(const Outline2d &o, this->outlines()) {
|
||||
mem += o.size() * sizeof(Vector2d) + sizeof(Outline2d);
|
||||
mem += o.vertices.size() * sizeof(Vector2d) + sizeof(Outline2d);
|
||||
}
|
||||
mem += sizeof(Polygon2d);
|
||||
return mem;
|
||||
|
@ -27,7 +27,7 @@ BoundingBox Polygon2d::getBoundingBox() const
|
|||
{
|
||||
BoundingBox bbox;
|
||||
BOOST_FOREACH(const Outline2d &o, this->outlines()) {
|
||||
BOOST_FOREACH(const Vector2d &v, o) {
|
||||
BOOST_FOREACH(const Vector2d &v, o.vertices) {
|
||||
bbox.extend(Vector3d(v[0], v[1], 0));
|
||||
}
|
||||
}
|
||||
|
@ -39,7 +39,7 @@ std::string Polygon2d::dump() const
|
|||
std::stringstream out;
|
||||
BOOST_FOREACH(const Outline2d &o, this->theoutlines) {
|
||||
out << "contour:\n";
|
||||
BOOST_FOREACH(const Vector2d &v, o) {
|
||||
BOOST_FOREACH(const Vector2d &v, o.vertices) {
|
||||
out << " " << v.transpose();
|
||||
}
|
||||
out << "\n";
|
||||
|
@ -49,8 +49,8 @@ std::string Polygon2d::dump() const
|
|||
|
||||
void Polygon2d::transform(const Transform2d &mat)
|
||||
{
|
||||
BOOST_FOREACH(Outline2d &outline, this->theoutlines) {
|
||||
BOOST_FOREACH(Vector2d &v, outline) {
|
||||
BOOST_FOREACH(Outline2d &o, this->theoutlines) {
|
||||
BOOST_FOREACH(Vector2d &v, o.vertices) {
|
||||
v = mat * v;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,7 +5,11 @@
|
|||
#include "linalg.h"
|
||||
#include <vector>
|
||||
|
||||
typedef std::vector<Vector2d> Outline2d;
|
||||
struct Outline2d {
|
||||
Outline2d() : positive(true) {}
|
||||
std::vector<Vector2d> vertices;
|
||||
bool positive;
|
||||
};
|
||||
|
||||
class Polygon2d : public Geometry
|
||||
{
|
||||
|
|
|
@ -126,11 +126,11 @@ namespace CGALUtils {
|
|||
CGAL_For_all(fcirc, fend) {
|
||||
if (E.is_standard(E.target(fcirc))) {
|
||||
Explorer::Point ep = E.point(E.target(fcirc));
|
||||
outline.push_back(Vector2d(to_double(ep.x()),
|
||||
outline.vertices.push_back(Vector2d(to_double(ep.x()),
|
||||
to_double(ep.y())));
|
||||
}
|
||||
}
|
||||
if (outline.size() > 0) poly->addOutline(outline);
|
||||
if (outline.vertices.size() > 0) poly->addOutline(outline);
|
||||
}
|
||||
return poly;
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ namespace ClipperUtils {
|
|||
|
||||
ClipperLib::Path fromOutline2d(const Outline2d &outline, bool keep_orientation) {
|
||||
ClipperLib::Path p;
|
||||
BOOST_FOREACH(const Vector2d &v, outline) {
|
||||
BOOST_FOREACH(const Vector2d &v, outline.vertices) {
|
||||
p.push_back(ClipperLib::IntPoint(v[0]*CLIPPER_SCALE, v[1]*CLIPPER_SCALE));
|
||||
}
|
||||
// Make sure all polygons point up, since we project also
|
||||
|
@ -27,25 +27,30 @@ namespace ClipperUtils {
|
|||
return toPolygon2d(sanitize(ClipperUtils::fromPolygon2d(poly)));
|
||||
}
|
||||
|
||||
ClipperLib::Paths sanitize(const ClipperLib::Paths &paths) {
|
||||
return ClipperUtils::process(paths,
|
||||
ClipperLib::ctUnion,
|
||||
ClipperLib::pftEvenOdd);
|
||||
ClipperLib::PolyTree sanitize(const ClipperLib::Paths &paths) {
|
||||
ClipperLib::PolyTree result;
|
||||
ClipperLib::Clipper clipper;
|
||||
clipper.AddPaths(paths, ClipperLib::ptSubject, true);
|
||||
clipper.Execute(ClipperLib::ctUnion, result, ClipperLib::pftEvenOdd);
|
||||
return result;
|
||||
}
|
||||
|
||||
Polygon2d *toPolygon2d(const ClipperLib::Paths &poly) {
|
||||
Polygon2d *toPolygon2d(const ClipperLib::PolyTree &poly) {
|
||||
Polygon2d *result = new Polygon2d;
|
||||
BOOST_FOREACH(const ClipperLib::Path &p, poly) {
|
||||
const ClipperLib::PolyNode *node = poly.GetFirst();
|
||||
while (node) {
|
||||
Outline2d outline;
|
||||
outline.positive = !node->IsHole();
|
||||
const Vector2d *lastv = NULL;
|
||||
BOOST_FOREACH(const ClipperLib::IntPoint &ip, p) {
|
||||
BOOST_FOREACH(const ClipperLib::IntPoint &ip, node->Contour) {
|
||||
Vector2d v(1.0*ip.X/CLIPPER_SCALE, 1.0*ip.Y/CLIPPER_SCALE);
|
||||
// Ignore too close vertices. This is to be nice to subsequent processes.
|
||||
if (lastv && (v-*lastv).squaredNorm() < 0.001) continue;
|
||||
outline.push_back(v);
|
||||
lastv = &outline.back();
|
||||
outline.vertices.push_back(v);
|
||||
lastv = &outline.vertices.back();
|
||||
}
|
||||
result->addOutline(outline);
|
||||
node = node->GetNext();
|
||||
}
|
||||
result->setSanitized(true);
|
||||
return result;
|
||||
|
@ -62,24 +67,34 @@ namespace ClipperUtils {
|
|||
return result;
|
||||
}
|
||||
|
||||
Polygon2d *apply(std::vector<const Polygon2d*> polygons,
|
||||
Polygon2d *apply(const std::vector<ClipperLib::Paths> &pathsvector,
|
||||
ClipperLib::ClipType clipType)
|
||||
{
|
||||
ClipperLib::Clipper clipper;
|
||||
bool first = true;
|
||||
BOOST_FOREACH(const Polygon2d *polygon, polygons) {
|
||||
ClipperLib::Paths paths = fromPolygon2d(*polygon);
|
||||
if (!polygon->isSanitized()) paths = sanitize(paths);
|
||||
BOOST_FOREACH(const ClipperLib::Paths &paths, pathsvector) {
|
||||
clipper.AddPaths(paths, first ? ClipperLib::ptSubject : ClipperLib::ptClip, true);
|
||||
if (first) first = false;
|
||||
}
|
||||
ClipperLib::Paths sumresult;
|
||||
ClipperLib::PolyTree sumresult;
|
||||
clipper.Execute(clipType, sumresult, ClipperLib::pftNonZero, ClipperLib::pftNonZero);
|
||||
if (sumresult.size() == 0) return NULL;
|
||||
if (sumresult.Total() == 0) return NULL;
|
||||
// The returned result will have outlines ordered according to whether
|
||||
// they're positive or negative: Positive outlines counter-clockwise and
|
||||
// negative outlines clockwise.
|
||||
return ClipperUtils::toPolygon2d(sumresult);
|
||||
}
|
||||
|
||||
Polygon2d *apply(const std::vector<const Polygon2d*> &polygons,
|
||||
ClipperLib::ClipType clipType)
|
||||
{
|
||||
std::vector<ClipperLib::Paths> pathsvector;
|
||||
BOOST_FOREACH(const Polygon2d *polygon, polygons) {
|
||||
ClipperLib::Paths polypaths = fromPolygon2d(*polygon);
|
||||
if (!polygon->isSanitized()) ClipperLib::PolyTreeToPaths(sanitize(polypaths), polypaths);
|
||||
pathsvector.push_back(polypaths);
|
||||
}
|
||||
return apply(pathsvector, clipType);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -10,14 +10,14 @@ namespace ClipperUtils {
|
|||
|
||||
ClipperLib::Path fromOutline2d(const Outline2d &poly, bool keep_orientation);
|
||||
ClipperLib::Paths fromPolygon2d(const Polygon2d &poly);
|
||||
ClipperLib::Paths sanitize(const ClipperLib::Paths &paths);
|
||||
ClipperLib::PolyTree sanitize(const ClipperLib::Paths &paths);
|
||||
Polygon2d *sanitize(const Polygon2d &poly);
|
||||
Polygon2d *toPolygon2d(const ClipperLib::Path &poly);
|
||||
Polygon2d *toPolygon2d(const ClipperLib::Paths &poly);
|
||||
Polygon2d *toPolygon2d(const ClipperLib::PolyTree &poly);
|
||||
ClipperLib::Paths process(const ClipperLib::Paths &polygons,
|
||||
ClipperLib::ClipType, ClipperLib::PolyFillType);
|
||||
|
||||
Polygon2d *apply(std::vector<const Polygon2d*> polygons, ClipperLib::ClipType);
|
||||
Polygon2d *apply(const std::vector<const Polygon2d*> &polygons, ClipperLib::ClipType);
|
||||
Polygon2d *apply(const std::vector<ClipperLib::Paths> &pathsvector, ClipperLib::ClipType);
|
||||
|
||||
};
|
||||
|
||||
|
|
|
@ -592,7 +592,7 @@ Polygon2d *DxfData::toPolygon2d() const
|
|||
if (!path.is_closed) continue; // We don't support open paths for now
|
||||
Outline2d outline;
|
||||
for (size_t j = 1; j < path.indices.size(); j++) {
|
||||
outline.push_back(Vector2d(this->points[path.indices[path.indices.size()-j]]));
|
||||
outline.vertices.push_back(Vector2d(this->points[path.indices[path.indices.size()-j]]));
|
||||
}
|
||||
poly->addOutline(outline);
|
||||
}
|
||||
|
|
|
@ -221,9 +221,9 @@ void export_dxf(const Polygon2d &poly, std::ostream &output)
|
|||
<< "ENTITIES\n";
|
||||
|
||||
BOOST_FOREACH(const Outline2d &o, poly.outlines()) {
|
||||
for (int i=0;i<o.size();i++) {
|
||||
const Vector2d &p1 = o[i];
|
||||
const Vector2d &p2 = o[(i+1)%o.size()];
|
||||
for (int i=0;i<o.vertices.size();i++) {
|
||||
const Vector2d &p1 = o.vertices[i];
|
||||
const Vector2d &p2 = o.vertices[(i+1)%o.vertices.size()];
|
||||
double x1 = p1[0];
|
||||
double y1 = p1[1];
|
||||
double x2 = p2[0];
|
||||
|
|
|
@ -58,7 +58,7 @@ namespace PolysetUtils {
|
|||
BOOST_FOREACH(const PolySet::Polygon &p, ps.polygons) {
|
||||
Outline2d outline;
|
||||
BOOST_FOREACH(const Vector3d &v, p) {
|
||||
outline.push_back(Vector2d(v[0], v[1]));
|
||||
outline.vertices.push_back(Vector2d(v[0], v[1]));
|
||||
}
|
||||
poly->addOutline(outline);
|
||||
}
|
||||
|
|
|
@ -214,11 +214,11 @@ void PolySet::render_surface(Renderer::csgmode_e csgmode, const Transform3d &m,
|
|||
// Render sides
|
||||
if (polygon.outlines().size() > 0) {
|
||||
BOOST_FOREACH(const Outline2d &o, polygon.outlines()) {
|
||||
for (size_t j = 1; j <= o.size(); j++) {
|
||||
Vector3d p1(o[j-1][0], o[j-1][1], -zbase/2);
|
||||
Vector3d p2(o[j-1][0], o[j-1][1], zbase/2);
|
||||
Vector3d p3(o[j % o.size()][0], o[j % o.size()][1], -zbase/2);
|
||||
Vector3d p4(o[j % o.size()][0], o[j % o.size()][1], zbase/2);
|
||||
for (size_t j = 1; j <= o.vertices.size(); j++) {
|
||||
Vector3d p1(o.vertices[j-1][0], o.vertices[j-1][1], -zbase/2);
|
||||
Vector3d p2(o.vertices[j-1][0], o.vertices[j-1][1], zbase/2);
|
||||
Vector3d p3(o.vertices[j % o.vertices.size()][0], o.vertices[j % o.vertices.size()][1], -zbase/2);
|
||||
Vector3d p4(o.vertices[j % o.vertices.size()][0], o.vertices[j % o.vertices.size()][1], zbase/2);
|
||||
gl_draw_triangle(shaderinfo, p2, p1, p3, true, true, false, 0, mirrored);
|
||||
gl_draw_triangle(shaderinfo, p2, p3, p4, false, true, true, 0, mirrored);
|
||||
}
|
||||
|
@ -285,7 +285,7 @@ void PolySet::render_edges(Renderer::csgmode_e csgmode) const
|
|||
// Render only outlines
|
||||
BOOST_FOREACH(const Outline2d &o, polygon.outlines()) {
|
||||
glBegin(GL_LINE_LOOP);
|
||||
BOOST_FOREACH(const Vector2d &v, o) {
|
||||
BOOST_FOREACH(const Vector2d &v, o.vertices) {
|
||||
glVertex3d(v[0], v[1], -0.1);
|
||||
}
|
||||
glEnd();
|
||||
|
@ -299,14 +299,14 @@ void PolySet::render_edges(Renderer::csgmode_e csgmode) const
|
|||
// Render top+bottom outlines
|
||||
for (double z = -zbase/2; z < zbase; z += zbase) {
|
||||
glBegin(GL_LINE_LOOP);
|
||||
BOOST_FOREACH(const Vector2d &v, o) {
|
||||
BOOST_FOREACH(const Vector2d &v, o.vertices) {
|
||||
glVertex3d(v[0], v[1], z);
|
||||
}
|
||||
glEnd();
|
||||
}
|
||||
// Render sides
|
||||
glBegin(GL_LINES);
|
||||
BOOST_FOREACH(const Vector2d &v, o) {
|
||||
BOOST_FOREACH(const Vector2d &v, o.vertices) {
|
||||
glVertex3d(v[0], v[1], -zbase/2);
|
||||
glVertex3d(v[0], v[1], +zbase/2);
|
||||
}
|
||||
|
|
|
@ -515,12 +515,14 @@ sphere_next_r2:
|
|||
v2 -= Vector2d(this->x/2, this->y/2);
|
||||
}
|
||||
|
||||
Outline2d o(4);
|
||||
o[0] = v1;
|
||||
o[1] = Vector2d(v2[0], v1[1]);
|
||||
o[2] = v2;
|
||||
o[3] = Vector2d(v1[0], v2[1]);
|
||||
Outline2d o;
|
||||
o.vertices.resize(4);
|
||||
o.vertices[0] = v1;
|
||||
o.vertices[1] = Vector2d(v2[0], v1[1]);
|
||||
o.vertices[2] = v2;
|
||||
o.vertices[3] = Vector2d(v1[0], v2[1]);
|
||||
p->addOutline(o);
|
||||
p->setSanitized(true);
|
||||
}
|
||||
|
||||
if (this->type == CIRCLE && this->r1 > 0)
|
||||
|
@ -529,12 +531,14 @@ sphere_next_r2:
|
|||
g = p;
|
||||
int fragments = Calc::get_fragments_from_r(this->r1, this->fn, this->fs, this->fa);
|
||||
|
||||
Outline2d o(fragments);
|
||||
Outline2d o;
|
||||
o.vertices.resize(fragments);
|
||||
for (int i=0; i < fragments; i++) {
|
||||
double phi = (M_PI*2*i) / fragments;
|
||||
o[i] = Vector2d(this->r1*cos(phi), this->r1*sin(phi));
|
||||
o.vertices[i] = Vector2d(this->r1*cos(phi), this->r1*sin(phi));
|
||||
}
|
||||
p->addOutline(o);
|
||||
p->setSanitized(true);
|
||||
}
|
||||
|
||||
if (this->type == POLYGON)
|
||||
|
@ -542,7 +546,7 @@ sphere_next_r2:
|
|||
Polygon2d *p = new Polygon2d();
|
||||
g = p;
|
||||
|
||||
std::vector<Vector2d> vertices;
|
||||
Outline2d outline;
|
||||
double x,y;
|
||||
const Value::VectorType &vec = this->points.toVector();
|
||||
for (int i=0;i<vec.size();i++) {
|
||||
|
@ -553,19 +557,19 @@ sphere_next_r2:
|
|||
delete p;
|
||||
return NULL;
|
||||
}
|
||||
vertices.push_back(Vector2d(x, y));
|
||||
outline.vertices.push_back(Vector2d(x, y));
|
||||
}
|
||||
|
||||
if (this->paths.toVector().size() == 0 && vertices.size() > 2) {
|
||||
p->addOutline(vertices);
|
||||
if (this->paths.toVector().size() == 0 && outline.vertices.size() > 2) {
|
||||
p->addOutline(outline);
|
||||
}
|
||||
else {
|
||||
BOOST_FOREACH(const Value &polygon, this->paths.toVector()) {
|
||||
Outline2d curroutline;
|
||||
BOOST_FOREACH(const Value &index, polygon.toVector()) {
|
||||
unsigned int idx = index.toDouble();
|
||||
if (idx < vertices.size()) {
|
||||
curroutline.push_back(vertices[idx]);
|
||||
if (idx < outline.vertices.size()) {
|
||||
curroutline.vertices.push_back(outline.vertices[idx]);
|
||||
}
|
||||
// FIXME: Warning on out of bounds?
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue