// Check if point is outside cycle
// By calculating number of intersections of ray
bool MoleculeLayoutGraphSimple::_isPointOutsideCycle(const Cycle &cycle, const Vec2f &p) const
{
    Random rand(SOME_MAGIC_INT_FOR_RANDOM_3);
    int i, count = 0;
    float a, b;
    Vec2f v1, v2;
    const float eps = 0.01f;

    bool success = false;

    while (!success)
    {
        success = true;

        a = (float)rand.nextDouble();
        b = (float)rand.nextDouble();
        a = 2.f * (a - 0.5f);
        b = 2.f * (b - 0.5f);

        if (fabs(a) < eps || fabs(b) < eps)
        {
            success = false;
            continue;
        }

        for (i = 0; i < cycle.vertexCount(); i++)
        {
            const Vec2f &pos = getPos(cycle.getVertex(i));

            if (fabs((pos.x - p.x) / a - (pos.y - p.y) / b) < EPSILON)
            {
                count++;

                if (count > 50)
                    return false;

                success = false;
                break;
            }
        }
    }

    // Calculate
    count = 0;

    for (i = 0; i < cycle.vertexCount(); i++)
        if (_isRayIntersect(a, b, p, getPos(cycle.getVertex(i)),
            getPos(cycle.getVertex((i + 1) % cycle.vertexCount()))))
            count++;

    if (count & 1)
        return false;
    return true;
}
double MoleculeLayoutGraphSmart::_get_square() {

    Cycle cycle;
    _getBorder(cycle);

    int len = cycle.vertexCount();

    double sq = 0;

    for (int i = 1; i < len - 1; i++)
        sq += Vec2f::cross(getPos(cycle.getVertex(i)) - getPos(cycle.getVertex(0)), getPos(cycle.getVertex(i + 1)) - getPos(cycle.getVertex(0)));

    return abs(sq / 2);
}
float MoleculeLayoutGraphSmart::_get_square() {

    Cycle cycle;
    _getBorder(cycle);

    int len = cycle.vertexCount();

    float sq = 0;

    for (int i = 1; i < len - 1; i++)
        sq += Vec2f::cross(getPos(cycle.getVertex(i)) - getPos(cycle.getVertex(0)), getPos(cycle.getVertex(i + 1)) - getPos(cycle.getVertex(0)));

    //printf("sq = %.20f\n", sq);

    return fabs(sq / 2);
}
// The same but with mapping
bool MoleculeLayoutGraph::_isPointOutsideCycleEx(const Cycle &cycle, const Vec2f &p, const Array<int> &mapping) const
{
    Random rand(SOME_MAGIC_INT_FOR_RANDOM_3);
    // TODO: check that point 'p' is equal to the one of cycle points (sometimes it happens)
    float a, b;

    int tries = 0;
    while (tries < 50)
    {
        tries++;

        // Choose random direction
        a = (float)rand.nextDouble();
        b = (float)rand.nextDouble();
        a = 2.f * (a - 0.5f);
        b = 2.f * (b - 0.5f);

        // Calculate number of intersection with boundary
        int count = 0;

        for (int i = 0; i < cycle.vertexCount(); i++)
        {
            int ret = _isRayIntersectWithCheck(a, b, p, getPos(mapping[cycle.getVertex(i)]),
                getPos(mapping[cycle.getVertex((i + 1) % cycle.vertexCount())]), true);
            if (ret == -1)
            {
                // Ray is too near to the point. Choose another one point
                count = -1;
                break;
            }
            if (ret == 1)
                count++;
        }

        if (count == -1)
            // Try again
            continue;

        // If number of intersections is even then point is outside
        if (count & 1)
            return false;
        return true;
    }

    // Return any value hoping it will never happen
    return false;
}
// Split border in two parts by two vertices
void MoleculeLayoutGraph::_splitBorder (int v1, int v2, Array<int> &part1v, Array<int> &part1e, Array<int> &part2v, Array<int> &part2e) const
{
   Cycle border;

   _getBorder(border);

   int idx1 = border.findVertex(v1);
   int idx2 = border.findVertex(v2);
   int i;

   if (idx1 == -1 || idx2 == -1)
      throw Error("border division by non-boundary vertex");

   if (idx1 > idx2)
      __swap(idx1, idx2, i);

   part1v.clear();
   part1e.clear();
   part2v.clear();
   part2e.clear();

   for (i = idx1; i < idx2 + 1; i++)
   {
      part1v.push(border.getVertex(i));
      part1e.push(border.getEdge(i));
   }
   
   part1e.pop(); // edge count is less

   for (i = idx2; i < border.vertexCount(); i++)
   {
      part2v.push(border.getVertex(i));
      part2e.push(border.getEdge(i));
   }

   for (i = 0; i < idx1 + 1; i++)
   {
      part2v.push(border.getVertex(i));
      part2e.push(border.getEdge(i));
   }

   part2e.pop(); // edge count is less
}
void MoleculeLayoutGraph::_assignFirstCycle (const Cycle &cycle)
{
   // TODO: Start drawing from vertex with maximum code and continue to the right with one of two which has maximum code
   int i, n;
   float phi;

   n = cycle.vertexCount();

   for (i = 0; i < n; i++)
   {
      _layout_vertices[cycle.getVertex(i)].type = ELEMENT_BOUNDARY;
      _layout_edges[cycle.getEdge(i)].type = ELEMENT_BOUNDARY;
   }

   _first_vertex_idx = cycle.getVertex(0);

   _layout_vertices[cycle.getVertex(0)].pos.set(0.f, 0.f);
   _layout_vertices[cycle.getVertex(1)].pos.set(1.f, 0.f);

   phi = (float)M_PI * (n - 2) / n;

   for (i = 1; i < n - 1; i++)
   {
      const Vec2f &v1 = _layout_vertices[cycle.getVertex(i - 1)].pos;
      const Vec2f &v2 = _layout_vertices[cycle.getVertex(i)].pos;

      _layout_vertices[cycle.getVertex(i + 1)].pos.rotateAroundSegmentEnd(v1, v2, phi);
   }
}