Example #1
0
// Splitting an extrusion loop, possibly made of multiple segments, some of the segments may be bridging.
void ExtrusionLoop::split_at(const Point &point, bool prefer_non_overhang)
{
    if (this->paths.empty())
        return;
    
    // Find the closest path and closest point belonging to that path. Avoid overhangs, if asked for.
    size_t path_idx = 0;
    Point  p;
    {
        double min = std::numeric_limits<double>::max();
        Point  p_non_overhang;
        size_t path_idx_non_overhang = 0;
        double min_non_overhang = std::numeric_limits<double>::max();
        for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
            Point p_tmp = point.projection_onto(path->polyline);
            double dist = point.distance_to(p_tmp);
            if (dist < min) {
                p = p_tmp;
                min = dist;
                path_idx = path - this->paths.begin();
            } 
            if (prefer_non_overhang && ! path->is_bridge() && dist < min_non_overhang) {
                p_non_overhang = p_tmp;
                min_non_overhang = dist;
                path_idx_non_overhang = path - this->paths.begin();
            }
        }
        if (prefer_non_overhang && min_non_overhang != std::numeric_limits<double>::max()) {
            // Only apply the non-overhang point if there is one.
            path_idx = path_idx_non_overhang;
            p        = p_non_overhang;
        }
    }
    
    // now split path_idx in two parts
    const ExtrusionPath &path = this->paths[path_idx];
    ExtrusionPath p1(path.role, path.mm3_per_mm, path.width, path.height);
    ExtrusionPath p2(path.role, path.mm3_per_mm, path.width, path.height);
    path.polyline.split_at(p, &p1.polyline, &p2.polyline);
    
    if (this->paths.size() == 1) {
        if (! p1.polyline.is_valid())
            std::swap(this->paths.front().polyline.points, p2.polyline.points);
        else if (! p2.polyline.is_valid())
            std::swap(this->paths.front().polyline.points, p1.polyline.points);
        else {
            p2.polyline.points.insert(p2.polyline.points.end(), p1.polyline.points.begin() + 1, p1.polyline.points.end());
            std::swap(this->paths.front().polyline.points, p2.polyline.points);
        }
    } else {
        // install the two paths
        this->paths.erase(this->paths.begin() + path_idx);
        if (p2.polyline.is_valid()) this->paths.insert(this->paths.begin() + path_idx, p2);
        if (p1.polyline.is_valid()) this->paths.insert(this->paths.begin() + path_idx, p1);
    }
    
    // split at the new vertex
    this->split_at_vertex(p);
}
Example #2
0
bool
ExtrusionLoop::has_overhang_point(const Point &point) const
{
    for (ExtrusionPaths::const_iterator path = this->paths.begin(); path != this->paths.end(); ++path) {
        int pos = path->polyline.find_point(point);
        if (pos != -1) {
            // point belongs to this path
            // we consider it overhang only if it's not an endpoint
            return (path->is_bridge() && pos > 0 && pos != (int)(path->polyline.points.size())-1);
        }
    }
    return false;
}