Пример #1
0
// Extract component border
void MoleculeLayoutGraph::_getBorder (Cycle &border) const
{
   QS_DEF(Array<int>, vertices);
   QS_DEF(Array<int>, edges);
   int i, n = 0;

   for (i = edgeBegin(); i < edgeEnd(); i = edgeNext(i))
      if  (_layout_edges[i].type == ELEMENT_BOUNDARY)
         n++;

   if (n == 0)
      return;

   vertices.clear();
   edges.clear();

   for (i = edgeBegin(); i < edgeEnd(); i = edgeNext(i))
      if  (_layout_edges[i].type == ELEMENT_BOUNDARY)
         break;

   Edge edge = getEdge(i);

   vertices.push(edge.beg);
   edges.push(i);

   while (edge.end != vertices[0])
   {
      const Vertex &vert = getVertex(edge.end);
      bool found = false;

      for (int i = vert.neiBegin(); !found && i < vert.neiEnd(); i = vert.neiNext(i))
      {
         int nei_v = vert.neiVertex(i);
         int nei_e = vert.neiEdge(i);

         if (getEdgeType(nei_e) == ELEMENT_BOUNDARY && nei_v != edge.beg)
         {
            edge.beg = edge.end;
            edge.end = nei_v;

            vertices.push(edge.beg);
            edges.push(nei_e);

            found = true;
         }
      }

      if (!found || vertices.size() > n)
         throw Error("corrupted border");
   }

   border.copy(vertices, edges);
   border.canonize();
}
void MoleculeLayoutGraphSmart::_getSurroundCycle(Cycle &cycle, Vec2f p) const
{
    QS_DEF(Array<int>, vertices);
    QS_DEF(Array<int>, edges);
    QS_DEF(Array<Vec2f>, pos);
    int i, n = 0;
    float eps = 1e-5;

    /*   for (i = edgeBegin(); i < edgeEnd(); i = edgeNext(i))
    if  (_layout_edges[i].type == ELEMENT_BOUNDARY)
    n++;

    if (n == 0)
    return;*/

    vertices.clear();
    edges.clear();

    srand(19857615);
    float sn = 0;
    float cs = 0;
    while (sn == 0 && cs == 0) {
        sn = 2.0*rand() / RAND_MAX - 1;
        cs = 2.0*rand() / RAND_MAX - 1;
    }
    float len = sqrt(sn*sn + cs*cs);
    sn /= len;
    cs /= len;

    pos.resize(vertexEnd());
    for (int i = vertexBegin(); i != vertexEnd(); i = vertexNext(i)) if (getVertexType(i) != ELEMENT_NOT_DRAWN) {
        pos[i].copy(getPos(i) - p);
    }

    for (int i = vertexBegin(); i != vertexEnd(); i = vertexNext(i))
        if (getVertexType(i) != ELEMENT_NOT_DRAWN) {
            pos[i].rotate(sn, cs);
        }

    int first_edge = -1;
    float first_edge_x = 1e20;
    for (int i = edgeBegin(); i != edgeEnd(); i = edgeNext(i))
        if (_layout_edges[i].type != ELEMENT_NOT_DRAWN) {
            Edge e = getEdge(i);
            if (pos[e.beg].y * pos[e.end].y <= 0) {
                float mid_x = (pos[e.beg].x * pos[e.end].y - pos[e.end].x * pos[e.beg].y) / (pos[e.end].y - pos[e.beg].y);
                if (abs(mid_x) < eps) return;
                if (mid_x > 0 && (first_edge == -1 || mid_x < first_edge_x)) {
                    first_edge = i;
                    first_edge_x = mid_x;
                }
            }
        }

    int firts_vertex = -1;
    if (first_edge != -1)
        if (pos[getEdge(first_edge).beg].y < pos[getEdge(first_edge).end].y) firts_vertex = getEdge(first_edge).beg;
        else firts_vertex = getEdge(first_edge).end;
    else {
        // in this case no edges are intersecs (OX) ray 
        // and so p is outside point
        // Then we are looking for border
        // and we can take the lowest vertex as the start vertex for searching of surround cycle
        float first_vertex_y;
        for (int i = vertexBegin(); i != vertexEnd(); i = vertexNext(i))
            if (_layout_vertices[i].type != ELEMENT_NOT_DRAWN)
                if (firts_vertex == -1 || pos[i].y < first_vertex_y) {
                    first_vertex_y = pos[i].y;
                    firts_vertex = i;
                }

        // and now lets find first edge...

        int second_vertex = -1;
        for (int i = getVertex(firts_vertex).neiBegin(); i != getVertex(firts_vertex).neiEnd(); i = getVertex(firts_vertex).neiNext(i)) {
            int new_vertex = getVertex(firts_vertex).neiVertex(i);
            if (isVertexDrawn(new_vertex) && (second_vertex == -1 || Vec2f::cross(pos[second_vertex] - pos[firts_vertex], pos[new_vertex] - pos[firts_vertex]) > 0)) {
                second_vertex = new_vertex;
                first_edge = getVertex(firts_vertex).neiEdge(i);
            }
        }
    }

    vertices.push(firts_vertex);
    edges.push(first_edge);

    while (true) {
        int current_vertex = vertices.top();
        int current_edge = edges.top();

        int next_vertex = getEdge(current_edge).findOtherEnd(current_vertex);
        int next_edge = -1;
        int next_vertex2 = current_vertex;

        for (int i = getVertex(next_vertex).neiBegin(); i != getVertex(next_vertex).neiEnd(); i = getVertex(next_vertex).neiNext(i)) {
            int try_vertex = getVertex(next_vertex).neiVertex(i);
            if (isVertexDrawn(try_vertex) && try_vertex != current_vertex) {
                bool need_to_update = false;
                if (next_vertex2 == current_vertex) {
                    need_to_update = true;
                }
                else {
                    if (Vec2f::cross(pos[next_vertex2] - pos[next_vertex], pos[current_vertex] - pos[next_vertex]) >= 0) {
                        need_to_update = Vec2f::cross(pos[next_vertex2] - pos[next_vertex], pos[try_vertex] - pos[next_vertex]) >= 0 &&
                            Vec2f::cross(pos[try_vertex] - pos[next_vertex], pos[current_vertex] - pos[next_vertex]) >= 0;
                    }
                    else {
                        need_to_update = Vec2f::cross(pos[next_vertex2] - pos[next_vertex], pos[try_vertex] - pos[next_vertex]) >= 0 ||
                            Vec2f::cross(pos[try_vertex] - pos[next_vertex], pos[current_vertex] - pos[next_vertex]) >= 0;
                    }
                }
                if (need_to_update) {
                    next_vertex2 = try_vertex;
                    next_edge = getVertex(next_vertex).neiEdge(i);
                }
            }
        }


        if (next_vertex == vertices[0] && next_edge == edges[0]) break;
        else {
            vertices.push(next_vertex);
            edges.push(next_edge);
            if (vertices.size() > vertexCount()) {
                vertices.clear_resize(0);
                edges.clear_resize(0);
                break;
            }
        }
    }

    cycle.copy(vertices, edges);
    //cycle.canonize();
}