void Discrete_upper_envelope::init_build_and_verify_input( const Lines& input, int LB, int UB) { assert(input.size() > 0 && LB < UB); // set the size one_ = LB; U_ = UB; }
void GetSection(Geometry*target,Geometry*section,Geometry*res,bool inside_section,bool back_faces,float*perimeter) { Triangle cur_tr; Lines lines; std::vector<LineConf> lines_conf; for(int i=0;i<target->tr.size();i++){ /* for(int b=0;b<target->boxes.size();b++) if(CrossBoxes(target->boxes[b].v[0],target->boxes[b].v[1],section->box1,section->box2)) for(int bi=0;bi<target->boxes[b].boxes.size();bi++) {int i=target->boxes[b].boxes[bi];*/ if(CrossBoxes(target->tr_bb[i].v[0],target->tr_bb[i].v[1],section->box1,section->box2)) { cur_tr = target->tr[i]; lines.clear(); lines_conf.clear(); GetCrTriangles(*section, cur_tr, lines,&lines_conf, target->tr_bb[i],perimeter); bool ins = section->Inside(cur_tr.v[0]); ins = xor(inside_section,ins); if(lines.size()) { //static int cc=0; //cc++; CutTriangle(cur_tr,lines,lines_conf,ins,res,!back_faces); //if(cc==2)return; }else { if(ins) { if(back_faces){swap(cur_tr.v[0],cur_tr.v[1]);cur_tr.norm.Inv();} res->AddTriangle(cur_tr); }//else } } } //printf("\n\nSection's triangles:%d\n",res->tr.size()); }
Lines _clipper_ln(ClipperLib::ClipType clipType, const Lines &subject, const Polygons &clip, bool safety_offset_) { // convert Lines to Polylines Polylines polylines; polylines.reserve(subject.size()); for (Lines::const_iterator line = subject.begin(); line != subject.end(); ++line) polylines.push_back(*line); // perform operation polylines = _clipper_pl(clipType, polylines, clip, safety_offset_); // convert Polylines to Lines Lines retval; for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) retval.push_back(*polyline); return retval; }
Lines _clipper_ln(ClipperLib::ClipType clipType, const Lines &subject, const Polygons &clip, bool safety_offset_) { // convert Lines to Polylines Polylines polylines; polylines.reserve(subject.size()); for (const Line &line : subject) polylines.emplace_back(Polyline(line.a, line.b)); // perform operation polylines = _clipper_pl(clipType, polylines, clip, safety_offset_); // convert Polylines to Lines Lines retval; for (Polylines::const_iterator polyline = polylines.begin(); polyline != polylines.end(); ++polyline) retval.emplace_back(polyline->operator Line()); return retval; }
// caller is responsible for supplying NO lines with zero length void _3DScene::_extrusionentity_to_verts_do(const Lines &lines, const std::vector<double> &widths, const std::vector<double> &heights, bool closed, double top_z, const Point ©, GLVertexArray* qverts, GLVertexArray* tverts) { /* It looks like it's faster without reserving capacity... // each segment has 4 quads, thus 16 vertices; + 2 caps qverts->reserve_more(3 * 4 * (4 * lines.size() + 2)); // two triangles for each corner tverts->reserve_more(3 * 3 * 2 * (lines.size() + 1)); */ Line prev_line; Pointf prev_b1, prev_b2; Vectorf3 prev_xy_left_normal, prev_xy_right_normal; // loop once more in case of closed loops bool first_done = false; for (size_t i = 0; i <= lines.size(); ++i) { if (i == lines.size()) i = 0; const Line &line = lines.at(i); if (i == 0 && first_done && !closed) break; double len = line.length(); double unscaled_len = unscale(len); double bottom_z = top_z - heights.at(i); double middle_z = (top_z + bottom_z) / 2; double dist = widths.at(i)/2; // scaled Vectorf v = Vectorf::new_unscale(line.vector()); v.scale(1/unscaled_len); Pointf a = Pointf::new_unscale(line.a); Pointf b = Pointf::new_unscale(line.b); Pointf a1 = a; Pointf a2 = a; a1.translate(+dist*v.y, -dist*v.x); a2.translate(-dist*v.y, +dist*v.x); Pointf b1 = b; Pointf b2 = b; b1.translate(+dist*v.y, -dist*v.x); b2.translate(-dist*v.y, +dist*v.x); // calculate new XY normals Vector n = line.normal(); Vectorf3 xy_right_normal = Vectorf3::new_unscale(n.x, n.y, 0); xy_right_normal.scale(1/unscaled_len); Vectorf3 xy_left_normal = xy_right_normal; xy_left_normal.scale(-1); if (first_done) { // if we're making a ccw turn, draw the triangles on the right side, otherwise draw them on the left side double ccw = line.b.ccw(prev_line); if (ccw > EPSILON) { // top-right vertex triangle between previous line and this one { // use the normal going to the right calculated for the previous line tverts->push_norm(prev_xy_right_normal); tverts->push_vert(prev_b1.x, prev_b1.y, middle_z); // use the normal going to the right calculated for this line tverts->push_norm(xy_right_normal); tverts->push_vert(a1.x, a1.y, middle_z); // normal going upwards tverts->push_norm(0,0,1); tverts->push_vert(a.x, a.y, top_z); } // bottom-right vertex triangle between previous line and this one { // use the normal going to the right calculated for the previous line tverts->push_norm(prev_xy_right_normal); tverts->push_vert(prev_b1.x, prev_b1.y, middle_z); // normal going downwards tverts->push_norm(0,0,-1); tverts->push_vert(a.x, a.y, bottom_z); // use the normal going to the right calculated for this line tverts->push_norm(xy_right_normal); tverts->push_vert(a1.x, a1.y, middle_z); } } else if (ccw < -EPSILON) { // top-left vertex triangle between previous line and this one { // use the normal going to the left calculated for the previous line tverts->push_norm(prev_xy_left_normal); tverts->push_vert(prev_b2.x, prev_b2.y, middle_z); // normal going upwards tverts->push_norm(0,0,1); tverts->push_vert(a.x, a.y, top_z); // use the normal going to the right calculated for this line tverts->push_norm(xy_left_normal); tverts->push_vert(a2.x, a2.y, middle_z); } // bottom-left vertex triangle between previous line and this one { // use the normal going to the left calculated for the previous line tverts->push_norm(prev_xy_left_normal); tverts->push_vert(prev_b2.x, prev_b2.y, middle_z); // use the normal going to the right calculated for this line tverts->push_norm(xy_left_normal); tverts->push_vert(a2.x, a2.y, middle_z); // normal going downwards tverts->push_norm(0,0,-1); tverts->push_vert(a.x, a.y, bottom_z); } } } // if this was the extra iteration we were only interested in the triangles if (first_done && i == 0) break; prev_line = line; prev_b1 = b1; prev_b2 = b2; prev_xy_right_normal = xy_right_normal; prev_xy_left_normal = xy_left_normal; if (!closed) { // terminate open paths with caps if (i == 0) { // normal pointing downwards qverts->push_norm(0,0,-1); qverts->push_vert(a.x, a.y, bottom_z); // normal pointing to the right qverts->push_norm(xy_right_normal); qverts->push_vert(a1.x, a1.y, middle_z); // normal pointing upwards qverts->push_norm(0,0,1); qverts->push_vert(a.x, a.y, top_z); // normal pointing to the left qverts->push_norm(xy_left_normal); qverts->push_vert(a2.x, a2.y, middle_z); } // we don't use 'else' because both cases are true if we have only one line if (i == lines.size()-1) { // normal pointing downwards qverts->push_norm(0,0,-1); qverts->push_vert(b.x, b.y, bottom_z); // normal pointing to the left qverts->push_norm(xy_left_normal); qverts->push_vert(b2.x, b2.y, middle_z); // normal pointing upwards qverts->push_norm(0,0,1); qverts->push_vert(b.x, b.y, top_z); // normal pointing to the right qverts->push_norm(xy_right_normal); qverts->push_vert(b1.x, b1.y, middle_z); } } // bottom-right face { // normal going downwards qverts->push_norm(0,0,-1); qverts->push_norm(0,0,-1); qverts->push_vert(a.x, a.y, bottom_z); qverts->push_vert(b.x, b.y, bottom_z); qverts->push_norm(xy_right_normal); qverts->push_norm(xy_right_normal); qverts->push_vert(b1.x, b1.y, middle_z); qverts->push_vert(a1.x, a1.y, middle_z); } // top-right face { qverts->push_norm(xy_right_normal); qverts->push_norm(xy_right_normal); qverts->push_vert(a1.x, a1.y, middle_z); qverts->push_vert(b1.x, b1.y, middle_z); // normal going upwards qverts->push_norm(0,0,1); qverts->push_norm(0,0,1); qverts->push_vert(b.x, b.y, top_z); qverts->push_vert(a.x, a.y, top_z); } // top-left face { qverts->push_norm(0,0,1); qverts->push_norm(0,0,1); qverts->push_vert(a.x, a.y, top_z); qverts->push_vert(b.x, b.y, top_z); qverts->push_norm(xy_left_normal); qverts->push_norm(xy_left_normal); qverts->push_vert(b2.x, b2.y, middle_z); qverts->push_vert(a2.x, a2.y, middle_z); } // bottom-left face { qverts->push_norm(xy_left_normal); qverts->push_norm(xy_left_normal); qverts->push_vert(a2.x, a2.y, middle_z); qverts->push_vert(b2.x, b2.y, middle_z); // normal going downwards qverts->push_norm(0,0,-1); qverts->push_norm(0,0,-1); qverts->push_vert(b.x, b.y, bottom_z); qverts->push_vert(a.x, a.y, bottom_z); } first_done = true; } }
void BridgeDetector::coverage(double angle, Polygons* coverage) const { // Clone our expolygon and rotate it so that we work with vertical lines. ExPolygon expolygon = this->expolygon; expolygon.rotate(PI/2.0 - angle, Point(0,0)); /* Outset the bridge expolygon by half the amount we used for detecting anchors; we'll use this one to generate our trapezoids and be sure that their vertices are inside the anchors and not on their contours leading to false negatives. */ ExPolygons grown; offset(expolygon, &grown, this->extrusion_width/2.0); // Compute trapezoids according to a vertical orientation Polygons trapezoids; for (ExPolygons::const_iterator it = grown.begin(); it != grown.end(); ++it) it->get_trapezoids2(&trapezoids, PI/2.0); // get anchors, convert them to Polygons and rotate them too Polygons anchors; for (ExPolygons::const_iterator anchor = this->_anchors.begin(); anchor != this->_anchors.end(); ++anchor) { Polygons pp = *anchor; for (Polygons::iterator p = pp.begin(); p != pp.end(); ++p) p->rotate(PI/2.0 - angle, Point(0,0)); anchors.insert(anchors.end(), pp.begin(), pp.end()); } Polygons covered; for (Polygons::const_iterator trapezoid = trapezoids.begin(); trapezoid != trapezoids.end(); ++trapezoid) { Lines lines = trapezoid->lines(); Lines supported; intersection(lines, anchors, &supported); // not nice, we need a more robust non-numeric check for (size_t i = 0; i < supported.size(); ++i) { if (supported[i].length() < this->extrusion_width) { supported.erase(supported.begin() + i); i--; } } if (supported.size() >= 2) covered.push_back(*trapezoid); } // merge trapezoids and rotate them back Polygons _coverage; union_(covered, &_coverage); for (Polygons::iterator p = _coverage.begin(); p != _coverage.end(); ++p) p->rotate(-(PI/2.0 - angle), Point(0,0)); // intersect trapezoids with actual bridge area to remove extra margins // and append it to result intersection(_coverage, this->expolygon, coverage); /* if (0) { my @lines = map @{$_->lines}, @$trapezoids; $_->rotate(-(PI/2 - $angle), [0,0]) for @lines; require "Slic3r/SVG.pm"; Slic3r::SVG::output( "coverage_" . rad2deg($angle) . ".svg", expolygons => [$self->expolygon], green_expolygons => $self->_anchors, red_expolygons => $coverage, lines => \@lines, ); } */ }