<commit_before>#include <list>
#include <vector>

#include "pather_optimizer_fastgraph.h"

namespace mgl {

#define BUCKET pather_optimizer_fastgraph::bucket
#define HIERARCHY BUCKET::LoopHierarchy

BUCKET::bucket(Point2Type testPoint) 
        : m_testPoint(testPoint), m_empty(true) {}
BUCKET::bucket(const Loop& loop)
        : m_testPoint(*loop.clockwise()), m_empty(false), m_loop(loop) {
    insertNoCross(m_loop);
}
bool BUCKET::contains(Point2Type point) const {
    if(!m_loop.empty())
        return m_loop.windingContains(point);
    //things with no boundaries contain everything
    return true;
}
bool BUCKET::contains(const bucket& other) const {
    if(!other.m_loop.empty())
        return contains(other.m_testPoint);
    //things with no boundaries cannot be contained
    return false;
}
void BUCKET::insertBoundary(const Loop& loop) {
    bucket constructed(loop);
    insertBucket(constructed);
}
void BUCKET::insertPath(const LabeledOpenPath& path) {
    insertPath(path.myPath, path.myLabel);
}
void BUCKET::insertPath(const OpenPath& path, const PathLabel& label) {
    if(!path.empty()) {
        Point2Type testPoint = *path.fromStart();
        LoopHierarchy& target = m_hierarchy.select(testPoint);
        graph_type& currentGraph = target.m_graph;
        node_index last = -1;
        for(OpenPath::const_iterator iter = path.fromStart(); 
                iter != path.end(); 
                ++iter) {
            OpenPath::const_iterator next = iter;
            ++next;
            if(iter == path.fromStart()) {
                last = currentGraph.createNode(NodeData(*iter, 
                        label, true)).getIndex();
            }
            if(next != path.end()) {
                OpenPath::const_iterator future = next;
                ++future;
                node& curNode = currentGraph.createNode(NodeData(*next, 
                        label, future==path.end()));
                node& lastNode = currentGraph[last];
                Segment2Type connection( 
                        curNode.data().getPosition(), 
                        lastNode.data().getPosition());
                Point2Type normal;
                try {
                    normal = (connection.b - connection.a).unit();
                } catch (const GeometryException& le) {}
                Scalar distance = connection.length();
                Cost frontCost(label, distance, normal);
                Cost backCost(label, distance, normal * -1.0);
                curNode.connect(lastNode, backCost);
                lastNode.connect(curNode, frontCost);
                last = curNode.getIndex();
            }
        }
    }
}
void BUCKET::insertBucket(bucket& constructed) {
    if(constructed.contains(*this)) {
        swap(constructed);
    }
    for(bucket_list::iterator childIter = m_children.begin();
            childIter != m_children.end(); 
            ++childIter) {
        if(childIter->contains(constructed)) {
            childIter->insertBucket(constructed);
            return;
        }
    }
    std::list<bucket_list::iterator> thingsToMove;
    for(bucket_list::iterator bucketIter = m_children.begin(); 
            bucketIter != m_children.end(); 
            ++bucketIter) {
        if(constructed.contains(*bucketIter))
            thingsToMove.push_back(bucketIter);
    }
    while(!thingsToMove.empty()) {
        constructed.insertBucket(*thingsToMove.front());
        thingsToMove.pop_front();
    }
    m_children.push_back(bucket());
    m_children.back().swap(constructed);
}
BUCKET& BUCKET::select(Point2Type point) {
    for(bucket_list::iterator childIter = m_children.begin();
            childIter != m_children.end(); 
            ++childIter) {
        if(childIter->contains(point))
            return childIter->select(point);
    }
    return *this;
}
void BUCKET::optimize(LabeledOpenPaths& output, Point2Type& entryPoint, 
        const GrueConfig& grueConf) {
    buildNoCross();
    Scalar myDistance = std::numeric_limits<Scalar>::max();
    for(edge_iterator edge = edgeBegin(); 
            edge != edgeEnd(); 
            ++edge) {
        Scalar distance = (entryPoint - *edge).squaredMagnitude();
        if(distance < myDistance)
            myDistance = distance;
    }
    bucket_list::iterator bestRecursiveChoice;
    Scalar bestDistance;
    while((bestRecursiveChoice = pickBestChild(m_children.begin(), 
            m_children.end(), entryPoint, bestDistance)) != m_children.end()) {
        if(bestDistance > myDistance)
            break;
        bestRecursiveChoice->optimize(output, entryPoint, grueConf);
        m_children.erase(bestRecursiveChoice);
    }
//    m_hierarchy.repr(std::cerr);
//    std::cout << "That was it for this bucket!" << std::endl;
    m_hierarchy.optimize(output, entryPoint, 
            m_noCrossing, grueConf);
    optimizeGraph(output, m_graph, m_noCrossing, entryPoint, grueConf);
    while((bestRecursiveChoice = pickBestChild(m_children.begin(), 
            m_children.end(), entryPoint)) != m_children.end()) {
        bestRecursiveChoice->optimize(output, entryPoint, grueConf);
        m_children.erase(bestRecursiveChoice);<commit_msg>Avoid drawing connections accross layers<commit_after>#include <list>
#include <vector>
#include <limits>

#include "pather_optimizer_fastgraph.h"

namespace mgl {

#define BUCKET pather_optimizer_fastgraph::bucket
#define HIERARCHY BUCKET::LoopHierarchy

BUCKET::bucket(Point2Type testPoint) 
        : m_testPoint(testPoint), m_empty(true) {}
BUCKET::bucket(const Loop& loop)
        : m_testPoint(*loop.clockwise()), m_empty(false), m_loop(loop) {
    insertNoCross(m_loop);
}
bool BUCKET::contains(Point2Type point) const {
    if(!m_loop.empty())
        return m_loop.windingContains(point);
    //things with no boundaries contain everything
    return true;
}
bool BUCKET::contains(const bucket& other) const {
    if(!other.m_loop.empty())
        return contains(other.m_testPoint);
    //things with no boundaries cannot be contained
    return false;
}
void BUCKET::insertBoundary(const Loop& loop) {
    bucket constructed(loop);
    insertBucket(constructed);
}
void BUCKET::insertPath(const LabeledOpenPath& path) {
    insertPath(path.myPath, path.myLabel);
}
void BUCKET::insertPath(const OpenPath& path, const PathLabel& label) {
    if(!path.empty()) {
        Point2Type testPoint = *path.fromStart();
        LoopHierarchy& target = m_hierarchy.select(testPoint);
        graph_type& currentGraph = target.m_graph;
        node_index last = -1;
        for(OpenPath::const_iterator iter = path.fromStart(); 
                iter != path.end(); 
                ++iter) {
            OpenPath::const_iterator next = iter;
            ++next;
            if(iter == path.fromStart()) {
                last = currentGraph.createNode(NodeData(*iter, 
                        label, true)).getIndex();
            }
            if(next != path.end()) {
                OpenPath::const_iterator future = next;
                ++future;
                node& curNode = currentGraph.createNode(NodeData(*next, 
                        label, future==path.end()));
                node& lastNode = currentGraph[last];
                Segment2Type connection( 
                        curNode.data().getPosition(), 
                        lastNode.data().getPosition());
                Point2Type normal;
                try {
                    normal = (connection.b - connection.a).unit();
                } catch (const GeometryException& le) {}
                Scalar distance = connection.length();
                Cost frontCost(label, distance, normal);
                Cost backCost(label, distance, normal * -1.0);
                curNode.connect(lastNode, backCost);
                lastNode.connect(curNode, frontCost);
                last = curNode.getIndex();
            }
        }
    }
}
void BUCKET::insertBucket(bucket& constructed) {
    if(constructed.contains(*this)) {
        swap(constructed);
    }
    for(bucket_list::iterator childIter = m_children.begin();
            childIter != m_children.end(); 
            ++childIter) {
        if(childIter->contains(constructed)) {
            childIter->insertBucket(constructed);
            return;
        }
    }
    std::list<bucket_list::iterator> thingsToMove;
    for(bucket_list::iterator bucketIter = m_children.begin(); 
            bucketIter != m_children.end(); 
            ++bucketIter) {
        if(constructed.contains(*bucketIter))
            thingsToMove.push_back(bucketIter);
    }
    while(!thingsToMove.empty()) {
        constructed.insertBucket(*thingsToMove.front());
        thingsToMove.pop_front();
    }
    m_children.push_back(bucket());
    m_children.back().swap(constructed);
}
BUCKET& BUCKET::select(Point2Type point) {
    for(bucket_list::iterator childIter = m_children.begin();
            childIter != m_children.end(); 
            ++childIter) {
        if(childIter->contains(point))
            return childIter->select(point);
    }
    return *this;
}
void BUCKET::optimize(LabeledOpenPaths& output, Point2Type& entryPoint, 
        const GrueConfig& grueConf) {
    buildNoCross();
    Scalar myDistance = std::numeric_limits<Scalar>::max();
    for(edge_iterator edge = edgeBegin(); 
            edge != edgeEnd(); 
            ++edge) {
        Scalar distance = (entryPoint - *edge).squaredMagnitude();
        if(distance < myDistance)
            myDistance = distance;
    }
    bucket_list::iterator bestRecursiveChoice;
    Scalar bestDistance;
    while((bestRecursiveChoice = pickBestChild(m_children.begin(), 
            m_children.end(), entryPoint, bestDistance)) != m_children.end()) {
        if(bestDistance > myDistance)
            break;
        bestRecursiveChoice->optimize(output, entryPoint, grueConf);
        m_children.erase(bestRecursiveChoice);
    }
//    m_hierarchy.repr(std::cerr);
//    std::cout << "That was it for this bucket!" << std::endl;
    if(grueConf.get_doFixedLayerStart()) {
        /*
         to avoid extra connections between layers (or between buckets) 
         when we fix our starting point to the bottom left, 
         I set the entry point to that location.
         
         This is not necessary otherwise because the algorithm will 
         naturally select the nearest point
        */
        Scalar minDist = std::numeric_limits<Scalar>::max();
        for(Loop::finite_cw_iterator iter = m_loop.clockwiseFinite(); 
                iter != m_loop.clockwiseEnd(); 
                ++iter) {
            Scalar dist = Point2Type(*iter).dotProduct(Point2Type(1.0,1.0));
            if(dist < minDist) {
                entryPoint = *iter;
            }
        }
    }
    m_hierarchy.optimize(output, entryPoint, 
            m_noCrossing, grueConf);
    optimizeGraph(output, m_graph, m_noCrossing, entryPoint, grueConf);
    while((bestRecursiveChoice = pickBestChild(m_children.begin(), 
            m_children.end(), entryPoint)) != m_children.end()) {
        bestRecursiveChoice->optimize(output, entryPoint, grueConf);
        m_children.erase(bestRecursiveChoice);
{'fraction_non_alphanumeric': 0.11901774511561211, 'fraction_numerical': 0.0023301666965405985, 'mean_word_length': 2.465527950310559, 'pattern_counts': {'":': 0, '<': 24, '<?xml version=': 0, '>': 27, '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': '2392271', 'n_tokens_mistral': 3209, 'n_tokens_neox': 3118, 'n_words': 595}