void LayerTriangulation::triangulate1(int layer0, int layer1, const std::vector<Point2D> &points)
{

    std::vector<int> &idx0 = layers[layer0];
    std::vector<int> &idx1 = layers[layer1];

    int point0 = lowest[layer0], point1 = 0;

    real min_dist = distance(points[idx0[point0]], points[idx1[point1]]);
    for (int index = 1; index < idx1.size(); ++index) {
        real dist = distance(points[idx0[point0]], points[idx1[index]]);
        if (dist < min_dist) {
            point1 = index;
            min_dist = dist;
        }
    }

    int end0 = point0, end1 = point1;
    do {

        edges.push_back(std::make_pair(idx0[point0], idx1[point1]));

        int next0 = (point0 + 1) % idx0.size(), next1 = (point1 + 1) % idx1.size();
        if ((point0 == end0 && next1 == end1 && idx1.size() > 1) || (point1 == end1 && next0 == end0))
            break;
        
        if (!is_ccw(points[idx0[point0]], points[idx1[point1]], points[idx1[next1]])) {
            // Check if we can build next triangle
            if (!is_ccw(points[idx0[next0]], points[idx1[point1]], points[idx1[next1]])) {
                // Check triangle with minimum angle
                real angle0 = std::min(min_angle(points[idx0[point0]], points[idx1[point1]], points[idx1[next1]]),
                              min_angle(points[idx0[point0]], points[idx1[next1]], points[idx0[next0]]));
                real angle1 = std::min(min_angle(points[idx0[point0]], points[idx0[next0]], points[idx1[point1]]),
                              min_angle(points[idx0[next0]], points[idx1[next1]], points[idx1[point1]]));
                if (angle0 > angle1) {
                    point1 = next1;
                } else {
                    point0 = next0;
                }
            } else {
                point1 = next1;
            }
        } else {
            point0 = next0;
        }
    } while (point0 != end0 || point1 != end1);

}
void LayerTriangulation::grahamScan0(const std::vector<int> &indices, const std::vector<Point2D> &points, std::vector<int> &inner)
{
    if (indices.size() == 0)
        return;

    layers.push_back(std::vector<int>());
    std::vector<int> &layer = layers.back();

    if (indices.size() < 3) {
        for (int index : indices)
            layer.push_back(index);
    } else if (indices.size() == 3) {
        layer.push_back(indices[0]);
        layer.push_back(indices[1]);
        layer.push_back(indices[2]);
    } else {

        std::vector<bool> mask(indices.size(), false);
        layer.reserve(indices.size());

        layer.push_back(0);
        layer.push_back(1);
        layer.push_back(2);

        for (size_t index = 3; index < indices.size(); ++index) {
            int prev_index = layer.back(); layer.pop_back();
            while (!is_ccw(points[indices[layer.back()]], points[indices[prev_index]], points[indices[index]])) {
                mask[prev_index] = true;
                prev_index = layer.back();
                layer.pop_back();
            }
            layer.push_back(prev_index);
            layer.push_back(index);
        }

        for (size_t index = 0; index < layer.size(); ++index) {
            layer[index] = indices[layer[index]];
        }

        inner.push_back(indices[0]);
        for (size_t index = 0; index < mask.size();  ++index) {
            if (mask[index])
                inner.push_back(indices[index]);
        }
    }
}
void LayerTriangulation::triangulate0(int layer0, int layer1, const std::vector<Point2D> &points)
{
    int point0 = lowest[layer0];
    int point1 = lowest[layer1];

    std::vector<int> &idx0 = layers[layer0];
    std::vector<int> &idx1 = layers[layer1];

    do {
        edges.push_back(std::make_pair(idx0[point0], idx1[point1]));

        if (!is_ccw(points[idx0[point0]], points[idx1[point1]], points[idx1[(point1 + 1) % idx1.size()]])) {
            point1 = (point1 + 1) % idx1.size();
        } else {
            point0 = (point0 + 1) % idx0.size();
        }
    } while (point0 != lowest[layer0] || point1 != lowest[layer1]);

}
 //------------------------------------------------------------------------
 void vcgen_contour::rewind(unsigned)
 {
     if(m_status == initial)
     {
         m_src_vertices.close(true);
         if(m_auto_detect)
         {
             if(!is_oriented(m_orientation))
             {
                 m_orientation = (calc_polygon_area(m_src_vertices) > 0.0) ? 
                                 path_flags_ccw : 
                                 path_flags_cw;
             }
         }
         if(is_oriented(m_orientation))
         {
             m_stroker.width(is_ccw(m_orientation) ? m_width : -m_width);
         }
     }
     m_status = ready;
     m_src_vertex = 0;
 }
void LayerTriangulation::grahamScan1(const std::vector<int> &indices, const std::vector<Point2D> &points, std::vector<int> &inner)
{
    if (indices.size() <= 1)
        return;

    layers.push_back(std::vector<int>());
    std::vector<int> &layer = layers.back();

    if (indices.size() < 4) {
        for (size_t index = 1; index < indices.size(); ++index) {
            layer.push_back(indices[index]);
        }
    } else if (indices.size() == 4) {
        if (is_ccw(points[indices[1]], points[indices[2]], points[indices[3]])) {
            layer.push_back(indices[1]);
            layer.push_back(indices[2]);
            layer.push_back(indices[3]);
        } else {
            layer.push_back(indices[1]);
            layer.push_back(indices[3]);
            layer.push_back(indices[2]);
        }
    } else {

        std::deque<int> hull;
        std::vector<bool> mask(indices.size(), false);

        hull.push_back(0);
        hull.push_back(1);
        hull.push_back(2);

        for (size_t index = 3; index < indices.size(); ++index) {
            int prev_index = hull.back(); hull.pop_back();
            while (!is_ccw(points[indices[hull.back()]], points[indices[prev_index]], points[indices[index]])) {
                mask[prev_index] = true;
                prev_index = hull.back();
                hull.pop_back();
            }
            hull.push_back(prev_index);
            hull.push_back(index);
        }

        mask[1] = true;
        hull.pop_front();

        for (int index = (int)indices.size() - 1; index > 0; --index) {
            if (mask[index]) {
                int prev_index = hull.back(); hull.pop_back();
                while (!is_ccw(points[indices[hull.back()]], points[indices[prev_index]], points[indices[index]])) {
                    mask[prev_index] = true;
                    prev_index = hull.back();
                    hull.pop_back();
                }

                mask[prev_index] = false;
                mask[index] = false;

                hull.push_back(prev_index);
                hull.push_back(index);
            }
        }

        mask[1] = false;
        hull.pop_back();

        for (auto it = hull.begin(); it != hull.end(); ++it) {
            layer.push_back(indices[*it]);
        }

        inner.push_back(indices[0]);
        for (size_t index = 0; index < mask.size(); ++index) {
            if (mask[index])
                inner.push_back(indices[index]);
        }
    }
}