// 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); } }