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;
}
Beispiel #2
0
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());

}
Beispiel #3
0
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;
}
Beispiel #4
0
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;
}
Beispiel #5
0
// 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 &copy,
        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;
    }
}
Beispiel #6
0
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,
        );
    }
    */
}