<commit_before>/** Copyright (C) 2013 <NAME> - Released under terms of the AGPLv3 License */
#include "comb.h"

#include <algorithm>

#include "utils/polygonUtils.h"
#include "sliceDataStorage.h"

namespace cura {



Polygons Comb::getLayerOutlines(SliceDataStorage& storage, unsigned int layer_nr)
{
    Polygons layer_outlines;
    for (SliceMeshStorage& mesh : storage.meshes)
    {
        for (SliceLayerPart& part : mesh.layers[layer_nr].parts)
        {
            layer_outlines.add(part.outline);
        }
    }
    return layer_outlines;
}

Polygons Comb::getLayerOuterWalls()
{
    Polygons layer_walls;
    for (SliceMeshStorage& mesh : storage.meshes)
    {
        for (SliceLayerPart& part : mesh.layers[layer_nr].parts)
        {
            if (part.insets.size() > 0)
            {
                layer_walls.add(part.insets[0]);
            }
            else 
            {
                layer_walls.add(part.outline.offset(-offset_from_outlines));
            }
        }
    }
    return layer_walls;
}
  
Polygons* Comb::getBoundaryOutside()
{
    if (!boundary_outside)
    {
        boundary_outside = new Polygons();
        *boundary_outside = getLayerOutlines(storage, layer_nr).offset(offset_from_outlines_outside);
    }
    return boundary_outside;
}
  
Comb::Comb(SliceDataStorage& storage, unsigned int layer_nr, int64_t wall_line_width_0, bool travel_avoid_other_parts, int64_t travel_avoid_distance)
: storage(storage)
, layer_nr(layer_nr)
, boundary_inside( getLayerOuterWalls() )
// , boundary_inside( boundary.offset(-offset_from_outlines) ) // TODO: make inside boundary configurable?
, boundary_outside(nullptr)
, partsView_inside( boundary_inside.splitIntoPartsView() ) // !! changes the order of boundary_inside 
, offset_from_outlines(wall_line_width_0) // between outer two walls
, max_moveInside_distance2(wall_line_width_0 * wall_line_width_0 * 4)
, offset_from_outlines_outside(travel_avoid_distance)
, avoid_other_parts(travel_avoid_other_parts)
{
}

Comb::~Comb()
{
    if (boundary_outside)
        delete boundary_outside;
}

unsigned int Comb::moveInside_(Point& from, int distance)
{
    return moveInside(boundary_inside, from, distance, max_moveInside_distance2);
}


bool Comb::calc(Point startPoint, Point endPoint, CombPaths& combPaths)
{
    if (shorterThen(endPoint - startPoint, max_comb_distance_ignored))
    {
        return true;
    }
    
    
    bool startInside = true;
    bool endInside = true;
    
    //Move start and end point inside the comb boundary
    unsigned int start_inside_poly = boundary_inside.findInside(startPoint, true);
    if (start_inside_poly == NO_INDEX)
    {
        start_inside_poly = moveInside(boundary_inside, startPoint, offset_extra_start_end, max_moveInside_distance2);
        if (start_inside_poly == NO_INDEX)    //If we fail to move the point inside the comb boundary we need to retract.
        {   
            startInside = false;
        }
    }
    unsigned int end_inside_poly = boundary_inside.findInside(endPoint, true);
    if (end_inside_poly == NO_INDEX)
    {
        end_inside_poly = moveInside(boundary_inside, endPoint, offset_extra_start_end, max_moveInside_distance2);
        if (end_inside_poly == NO_INDEX)    //If we fail to move the point inside the comb boundary we need to retract.
        {
            endInside = false;
        }
    }
    

    
    unsigned int start_part_boundary_poly_idx;
    unsigned int end_part_boundary_poly_idx;
    unsigned int start_part_idx = partsView_inside.getPartContaining(start_inside_poly, &start_part_boundary_poly_idx);
    unsigned int end_part_idx = partsView_inside.getPartContaining(end_inside_poly, &end_part_boundary_poly_idx);
    
    if (startInside && endInside && start_part_idx == end_part_idx)
    { // normal combing within part
        PolygonsPart part = partsView_inside.assemblePart(start_part_idx);
        combPaths.emplace_back();
        LinePolygonsCrossings::comb(part, startPoint, endPoint, combPaths.back(), -offset_dist_to_get_from_on_the_polygon_to_outside);
        return true;
    }
    else 
    { // comb inside part to edge (if needed) >> move through air avoiding other parts >> comb inside end part upto the endpoint (if needed) 
        Point middle_from;
        Point middle_to;
        
        if (startInside && endInside)
        {
            ClosestPolygonPoint middle_from_cp = findClosest(endPoint, boundary_inside[start_part_boundary_poly_idx]);
            ClosestPolygonPoint middle_to_cp = findClosest(middle_from_cp.location, boundary_inside[end_part_boundary_poly_idx]);
//             walkToNearestSmallestConnection(middle_from_cp, middle_to_cp); // TODO: perform this optimization?
            middle_from = middle_from_cp.location;
            middle_to = middle_to_cp.location;
        }
        else 
        {
            if (!startInside && !endInside) 
            { 
                middle_from = startPoint; 
                middle_to = endPoint; 
            }
            else if (!startInside && endInside)
            {
                middle_from = startPoint;
                ClosestPolygonPoint middle_to_cp = findClosest(middle_from, boundary_inside[end_part_boundary_poly_idx]);
                middle_to = middle_to_cp.location;
            }
            else if (startInside && !endInside)
            {
                middle_to = endPoint;
                ClosestPolygonPoint middle_from_cp = findClosest(middle_to, boundary_inside[start_part_boundary_poly_idx]);
                middle_from = middle_from_cp.location;
            }
        }
        
        if (startInside)
        {
            // start to boundary
            PolygonsPart part_begin = partsView_inside.assemblePart(start_part_idx); // comb through the starting part only
            combPaths.emplace_back();
            LinePolygonsCrossings::comb(part_begin, startPoint, middle_from, combPaths.back(), -offset_dist_to_get_from_on_the_polygon_to_outside);
        }
        
        // throught air from boundary to boundary
        if (avoid_other_parts)
        {
            Polygons& middle = *getBoundaryOutside(); // comb through all air, since generally the outside consists of a single part
            Point from_outside = middle_from;
            if (startInside || middle.inside(from_outside, true))
            { // move outside
                moveInside(middle, from_outside, -offset_extra_start_end, max_moveOutside_distance2);
            }
            Point to_outside = middle_to;
            if (endInside || middle.inside(to_outside, true))
            { // move outside
                moveInside(middle, to_outside, -offset_extra_start_end, max_moveOutside_distance2);
            }
            combPaths.emplace_back();
            combPaths.back().throughAir = true;
            if ( vSize(middle_from - middle_to) < vSize(middle_from - from_outside) + vSize(middle_to - to_outside) )
            { // via outside is a detour
                combPaths.back().push_back(middle_from);
                combPaths.back().push_back(middle_to);
            }
            else
            {
                LinePolygonsCrossings::comb(middle, from_outside, to_outside, combPaths.back(), offset_dist_to_get_from_on_the_polygon_to_outside);
            }
        }
        else 
        { // directly through air (not avoiding other parts)
            combPaths.emplace_back();
            combPaths.back().throughAir = true;
            combPaths.back().cross_boundary = true; // TODO: calculate whether we cross a boundary!
            combPaths.back().push_back(middle_from);
            combPaths.back().push_back(middle_to);<commit_msg>lil refactor<commit_after>/** Copyright (C) 2013 <NAME> - Released under terms of the AGPLv3 License */
#include "comb.h"

#include <algorithm>

#include "utils/polygonUtils.h"
#include "sliceDataStorage.h"

namespace cura {



Polygons Comb::getLayerOutlines(SliceDataStorage& storage, unsigned int layer_nr)
{
    Polygons layer_outlines;
    for (SliceMeshStorage& mesh : storage.meshes)
    {
        for (SliceLayerPart& part : mesh.layers[layer_nr].parts)
        {
            layer_outlines.add(part.outline);
        }
    }
    return layer_outlines;
}

Polygons Comb::getLayerOuterWalls()
{
    Polygons layer_walls;
    for (SliceMeshStorage& mesh : storage.meshes)
    {
        for (SliceLayerPart& part : mesh.layers[layer_nr].parts)
        {
            if (part.insets.size() > 0)
            {
                layer_walls.add(part.insets[0]);
            }
            else 
            {
                layer_walls.add(part.outline.offset(-offset_from_outlines));
            }
        }
    }
    return layer_walls;
}
  
Polygons* Comb::getBoundaryOutside()
{
    if (!boundary_outside)
    {
        boundary_outside = new Polygons();
        *boundary_outside = getLayerOutlines(storage, layer_nr).offset(offset_from_outlines_outside);
    }
    return boundary_outside;
}
  
Comb::Comb(SliceDataStorage& storage, unsigned int layer_nr, int64_t wall_line_width_0, bool travel_avoid_other_parts, int64_t travel_avoid_distance)
: storage(storage)
, layer_nr(layer_nr)
, boundary_inside( getLayerOuterWalls() )
// , boundary_inside( boundary.offset(-offset_from_outlines) ) // TODO: make inside boundary configurable?
, boundary_outside(nullptr)
, partsView_inside( boundary_inside.splitIntoPartsView() ) // !! changes the order of boundary_inside 
, offset_from_outlines(wall_line_width_0) // between outer two walls
, max_moveInside_distance2(wall_line_width_0 * wall_line_width_0 * 4)
, offset_from_outlines_outside(travel_avoid_distance)
, avoid_other_parts(travel_avoid_other_parts)
{
}

Comb::~Comb()
{
    if (boundary_outside)
        delete boundary_outside;
}

unsigned int Comb::moveInside_(Point& from, int distance)
{
    return moveInside(boundary_inside, from, distance, max_moveInside_distance2);
}


bool Comb::calc(Point startPoint, Point endPoint, CombPaths& combPaths)
{
    if (shorterThen(endPoint - startPoint, max_comb_distance_ignored))
    {
        return true;
    }
    
    
    bool startInside = true;
    bool endInside = true;
    
    //Move start and end point inside the comb boundary
    unsigned int start_inside_poly = boundary_inside.findInside(startPoint, true);
    if (start_inside_poly == NO_INDEX)
    {
        start_inside_poly = moveInside_(boundary_inside, startPoint, offset_extra_start_end);
        if (start_inside_poly == NO_INDEX)    //If we fail to move the point inside the comb boundary we need to retract.
        {   
            startInside = false;
        }
    }
    unsigned int end_inside_poly = boundary_inside.findInside(endPoint, true);
    if (end_inside_poly == NO_INDEX)
    {
        end_inside_poly = moveInside_(boundary_inside, endPoint, offset_extra_start_end);
        if (end_inside_poly == NO_INDEX)    //If we fail to move the point inside the comb boundary we need to retract.
        {
            endInside = false;
        }
    }
    

    
    unsigned int start_part_boundary_poly_idx;
    unsigned int end_part_boundary_poly_idx;
    unsigned int start_part_idx = partsView_inside.getPartContaining(start_inside_poly, &start_part_boundary_poly_idx);
    unsigned int end_part_idx = partsView_inside.getPartContaining(end_inside_poly, &end_part_boundary_poly_idx);
    
    if (startInside && endInside && start_part_idx == end_part_idx)
    { // normal combing within part
        PolygonsPart part = partsView_inside.assemblePart(start_part_idx);
        combPaths.emplace_back();
        LinePolygonsCrossings::comb(part, startPoint, endPoint, combPaths.back(), -offset_dist_to_get_from_on_the_polygon_to_outside);
        return true;
    }
    else 
    { // comb inside part to edge (if needed) >> move through air avoiding other parts >> comb inside end part upto the endpoint (if needed) 
        Point middle_from;
        Point middle_to;
        
        if (startInside && endInside)
        {
            ClosestPolygonPoint middle_from_cp = findClosest(endPoint, boundary_inside[start_part_boundary_poly_idx]);
            ClosestPolygonPoint middle_to_cp = findClosest(middle_from_cp.location, boundary_inside[end_part_boundary_poly_idx]);
//             walkToNearestSmallestConnection(middle_from_cp, middle_to_cp); // TODO: perform this optimization?
            middle_from = middle_from_cp.location;
            middle_to = middle_to_cp.location;
        }
        else 
        {
            if (!startInside && !endInside) 
            { 
                middle_from = startPoint; 
                middle_to = endPoint; 
            }
            else if (!startInside && endInside)
            {
                middle_from = startPoint;
                ClosestPolygonPoint middle_to_cp = findClosest(middle_from, boundary_inside[end_part_boundary_poly_idx]);
                middle_to = middle_to_cp.location;
            }
            else if (startInside && !endInside)
            {
                middle_to = endPoint;
                ClosestPolygonPoint middle_from_cp = findClosest(middle_to, boundary_inside[start_part_boundary_poly_idx]);
                middle_from = middle_from_cp.location;
            }
        }
        
        if (startInside)
        {
            // start to boundary
            PolygonsPart part_begin = partsView_inside.assemblePart(start_part_idx); // comb through the starting part only
            combPaths.emplace_back();
            LinePolygonsCrossings::comb(part_begin, startPoint, middle_from, combPaths.back(), -offset_dist_to_get_from_on_the_polygon_to_outside);
        }
        
        // throught air from boundary to boundary
        if (avoid_other_parts)
        {
            Polygons& middle = *getBoundaryOutside(); // comb through all air, since generally the outside consists of a single part
            Point from_outside = middle_from;
            if (startInside || middle.inside(from_outside, true))
            { // move outside
                moveInside_(middle, from_outside, -offset_extra_start_end);
            }
            Point to_outside = middle_to;
            if (endInside || middle.inside(to_outside, true))
            { // move outside
                moveInside_(middle, to_outside, -offset_extra_start_end);
            }
            combPaths.emplace_back();
            combPaths.back().throughAir = true;
            if ( vSize(middle_from - middle_to) < vSize(middle_from - from_outside) + vSize(middle_to - to_outside) )
            { // via outside is a detour
                combPaths.back().push_back(middle_from);
                combPaths.back().push_back(middle_to);
            }
            else
            {
                LinePolygonsCrossings::comb(middle, from_outside, to_outside, combPaths.back(), offset_dist_to_get_from_on_the_polygon_to_outside);
            }
        }
        else 
        { // directly through air (not avoiding other parts)
            combPaths.emplace_back();
            combPaths.back().throughAir = true;
            combPaths.back().cross_boundary = true; // TODO: calculate whether we cross a boundary!
            combPaths.back().push_back(middle_from);
            combPaths.back().push_back(middle_to);
{'fraction_non_alphanumeric': 0.08421190491781809, 'fraction_numerical': 0.0026193438543644816, 'mean_word_length': 2.615530303030303, 'pattern_counts': {'":': 0, '<': 9, '<?xml version=': 0, '>': 17, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '6457856', 'n_tokens_mistral': 4700, 'n_tokens_neox': 4413, 'n_words': 904}