bool Shape::getPolygonsAtZ(const Matrix4d &T, double z, vector<Poly> &polys, double &max_gradient, vector<Poly> &supportpolys, double max_supportangle, double thickness) const { vector<Vector2d> vertices; vector<Triangle> support_triangles; vector<Segment> lines = getCutlines(T, z, vertices, max_gradient, support_triangles, max_supportangle, thickness); //cerr << vertices.size() << " " << lines.size() << endl; if (!CleanupSharedSegments(lines)) return false; //cerr << vertices.size() << " " << lines.size() << endl; if (!CleanupConnectSegments(vertices,lines,true)) return false; //cerr << vertices.size() << " " << lines.size() << endl; vector< vector<uint> > connectedlines; // sequence of connected lines indices if (!getLineSequences(lines, connectedlines)) return false; for (uint i=0; i<connectedlines.size();i++){ Poly poly(z); for (uint j = 0; j < connectedlines[i].size();j++){ poly.addVertex(vertices[lines[connectedlines[i][j]].start]); } if (lines[connectedlines[i].back()].end != lines[connectedlines[i].front()].start ) poly.addVertex(vertices[lines[connectedlines[i].back()].end]); //cerr << "poly size " << poly.size() << endl; poly.calcHole(); polys.push_back(poly); } for (uint i = 0; i < support_triangles.size(); i++) { Poly p(z); // keep only part of triangle above z Vector2d lineStart; Vector2d lineEnd; // support_triangles are already transformed int num_cutpoints = support_triangles[i].CutWithPlane(z, Matrix4d::IDENTITY, lineStart, lineEnd); if (num_cutpoints == 0) { for (uint j = 0; j < 3; j++) { p.addVertex(Vector2d(support_triangles[i][j].x(), support_triangles[i][j].y())); } } else if (num_cutpoints > 1) { // add points of triangle above z for (uint j = 0; j < 3; j++) { if (support_triangles[i][j].z() > z) { p.addVertex(Vector2d(support_triangles[i][j].x(), support_triangles[i][j].y())); } } bool reverse = false; // test for order if we get 4 points (2 until now) if (p.size() > 1) { Vector2d i0, i1; const int is = intersect2D_Segments(p[1], lineStart, lineEnd, p[0], i0, i1); if (is > 0 && is < 3) { reverse = true; } } // add cutline points if (reverse) { p.addVertex(lineEnd); p.addVertex(lineStart); } else { p.addVertex(lineStart); p.addVertex(lineEnd); } } if (p.isHole()) p.reverse(); supportpolys.push_back(p); } // remove polygon areas from triangles // Clipping clipp; // clipp.clear(); // clipp.addPolys(supportpolys, subject); // clipp.addPolys(polys, clip); // supportpolys = clipp.subtract(CL::pftPositive,CL::pftPositive); return true; }
/* * Attempt to link all the Segments in 'lines' together. */ bool CuttingPlane::LinkSegments(float z, float Optimization) { if (vertices.size() == 0) return true; if (!CleanupSharedSegments (z)) return false; if (!CleanupConnectSegments (z)) return false; vector<vector<int> > planepoints; planepoints.resize(vertices.size()); for (uint i = 0; i < lines.size(); i++) planepoints[lines[i].start].push_back(i); // Build polygons vector<bool> used; used.resize(lines.size()); for (uint i=0;i>used.size();i++) used[i] = false; for (uint current = 0; current < lines.size(); current++) { if (used[current]) continue; // already used used[current] = true; int startPoint = lines[current].start; int endPoint = lines[current].end; Poly poly; poly.points.push_back (endPoint); int count = lines.size()+100; while (endPoint != startPoint && count != 0) // While not closed { const vector<int> &pathsfromhere = planepoints[endPoint]; // Find the next line. if (pathsfromhere.size() == 0) // no where to go ... { // lets get to the bottom of this data set: cout.precision (8); cout.width (12); cout << "\r\npolygon was cut at z " << z << " LinkSegments at vertex " << endPoint; cout << "\n " << vertices.size() << " vertices:\nvtx\tpos x\tpos y\trefs\n"; for (int i = 0; i < (int)vertices.size(); i++) { int refs = 0, pol = 0; for (int j = 0; j < (int)lines.size(); j++) { if (lines[j].start == i) { refs++; pol++; } if (lines[j].end == i) { refs++; pol--; } } cout << i << "\t" << vertices[i].x << "\t" << vertices[i].y << "\t" << refs << " pol " << pol; if (refs % 2) // oh dear, a dangling vertex cout << " odd, dangling vertex\n"; cout << "\n"; } cout << "\n " << lines.size() << " lines:\nline\tstart vtx\tend vtx\n"; for (int i = 0; i < (int)lines.size(); i++) { if (i == endPoint) cout << "problem line:\n"; cout << i << "\t" << lines[i].start << "\t" << lines[i].end << "\n"; } cout << "\n " << vertices.size() << " vertices:\nvtx\tpos x\tpos y\tlinked to\n"; for (int i = 0; i < (int)planepoints.size(); i++) { if (i == endPoint) cout << "problem vertex:\n"; cout << i << "\t" << vertices[i].x << "\t" << vertices[i].y << "\t"; int j; switch (planepoints[i].size()) { case 0: cout << "nothing - error !\n"; break; case 1: cout << "neighbour: " << planepoints[i][0]; break; default: cout << "Unusual - multiple: \n"; for (j = 0; j < (int)planepoints[i].size(); j++) cout << planepoints[i][j] << " "; cout << " ( " << j << " other vertices )"; break; } cout << "\n"; } // model failure - we will get called recursivelly // for a different z and different cutting plane. return false; } if (pathsfromhere.size() != 1) cout << "Risky co-incident node during shrinking\n"; // TODO: we need to do better here, some idas: // a) calculate the shortest path back to our start node, and // choose that and/or // b) identify all 2+ nodes and if they share start/end // directions eliminate them to join the polygons. uint i; for (i = 0; i < pathsfromhere.size() && used[pathsfromhere[i]]; i++); if (i >= pathsfromhere.size()) { cout << "no-where unused to go"; return false; } used[pathsfromhere[i]] = true; const Segment &nextsegment = lines[pathsfromhere[i]]; assert( nextsegment.start == endPoint ); endPoint = nextsegment.end; poly.points.push_back (endPoint); count--; } // Check if loop is complete if (count != 0) polygons.push_back (poly); // This is good else { // We will be called for a slightly different z cout << "\r\nentered loop at LinkSegments " << z; return false; } } // Cleanup polygons CleanupPolygons(Optimization); return true; }