Vec2d Algebra::linesIntersection(const Settings& vars, const Vec2d &p11, const Vec2d &p12, const Vec2d &p21, const Vec2d &p22 ) { Line l1 = points2line(p11, p12); Line l2 = points2line(p21, p22); double den = l1.A * l2.B - l2.A * l1.B; if (absolute(den) < vars.routines.Algebra_IntersectionEps) { Vec2d res; res.add(p11); res.add(p21); res.scale(0.5); // average return res; } else { return linesIntersection(vars, l1, l2); } }
Vec2d Algebra::linesIntersection( const Vec2d &p11, const Vec2d &p12, const Vec2d &p21, const Vec2d &p22 ) { Line l1 = points2line(p11, p12); Line l2 = points2line(p21, p22); double den = l1.A * l2.B - l2.A * l1.B; //Nonstandart behaviour if (absolute(den) < 0.01) //"Constants" ? { Vec2d res; res.add(p11); res.add(p21); res.scale(0.5); return res; } else { return linesIntersection(l1, l2); } }
void Molecule::mapLabels(const Settings& vars, std::deque<Label> &unmapped_labels ) { double space, space2; double bl = bondLength(); if (bl > vars.molecule.LengthValue_long) space = vars.molecule.LengthFactor_long; else if (bl > vars.molecule.LengthValue_medium) space = vars.molecule.LengthFactor_medium; else space = vars.molecule.LengthFactor_default; // printf("****: %lf %lf\n", bl, space); std::vector<Skeleton::Vertex> nearest; labels.assign(_labels.begin(), _labels.end()); for (size_t i = 0; i < labels.size(); ++i) { Label &l = labels[i]; #ifdef DEBUG printf("LABELS: %d %d\n", l.rect.x, l.rect.y); #endif nearest.clear(); space = l.MaxSymbolWidth() * vars.molecule.SpaceMultiply; space2 = l.rect.width < l.rect.height ? l.rect.width : l.rect.height; for (SkeletonGraph::edge_iterator begin = _g.edgeBegin(), end = _g.edgeEnd(); begin != end; ++begin) { SkeletonGraph::edge_descriptor e = *begin; if (vars.checkTimeLimit()) throw ImagoException("Timelimit exceeded"); double d1, d2; d1 = d2 = DIST_INF; if(_g.getDegree(e.m_source) > 1 && _g.getDegree(e.m_target) > 1) continue; if (_g.getDegree(e.m_source) == 1) d1 = Algebra::distance2rect(_g.getVertexPosition(e.m_source), l.rect); if (_g.getDegree(e.m_target) == 1) d2 = Algebra::distance2rect(_g.getVertexPosition(e.m_target), l.rect); auto v_m_target = _g.getVertexPosition(e.m_target); auto v_m_source = _g.getVertexPosition(e.m_source); if (d1 <= d2 && ((testCollision(v_m_target, v_m_source, l.rect) && testNear(v_m_source, l.rect, space)) || testNear(v_m_source, l.rect, space2/2))) nearest.push_back(e.m_source); else if (d2 < d1 && ((testCollision(v_m_source, v_m_target, l.rect) && testNear(v_m_target, l.rect, space)) || testNear(v_m_target, l.rect, space2/2))) nearest.push_back(e.m_target); } for (SkeletonGraph::vertex_iterator begin = _g.vertexBegin(), end = _g.vertexEnd(); begin != end; ++begin) { SkeletonGraph::vertex_descriptor v = *begin; auto v_position = _g.getVertexPosition( v); if(_g.getDegree(v) != 2) continue; if(!testNear(v_position, l.rect, space2/2)) continue; std::deque<Skeleton::Vertex> neighbors; Skeleton::SkeletonGraph::adjacency_iterator b_e, e_e; b_e = _g.adjacencyBegin(v); e_e = _g.adjacencyEnd(v); neighbors.assign(b_e, e_e); Skeleton::Edge edge1 = _g.getEdge(neighbors[0], v).first; Skeleton::Edge edge2 = _g.getEdge(neighbors[1], v).first; BondType t1 = getBondType(edge1); BondType t2 = getBondType(edge2); if( t1 != BT_SINGLE || t2 != BT_SINGLE) continue; Vec2d p_v = _g.getVertexPosition(v); Vec2d p1 = _g.getVertexPosition(neighbors[0]); Vec2d p2 = _g.getVertexPosition(neighbors[1]); Vec2d ap1, ap2; ap1.diff(p1, p_v); ap2.diff(p2, p_v); if( testCollision(p1, p_v, l.rect) && testCollision(p2, p_v, l.rect) && testNear(p_v, l.rect, space) && !testNear( p1, l.rect, space) && !testNear( p2, l.rect, space) ) { removeBond(edge1); Vertex v_d = addVertex(p_v); addBond(neighbors[0], v_d, BT_SINGLE, true); nearest.push_back(v_d); nearest.push_back(v); } } size_t s = nearest.size(); if (s == 0) { unmapped_labels.push_back(l); continue; } if (s == 1) { _mapping[nearest[0]] = &l; continue; } Vec2d middle; for (int j = 0; j < s; j++) { for (int k = j + 1; k < s; k++) { if (vars.checkTimeLimit()) throw ImagoException("Timelimit exceeded"); Skeleton::Vertex a, b; Skeleton::Vertex c, d; a = nearest[j]; b = nearest[k]; c = *_g.adjacencyBegin(a); d = *_g.adjacencyBegin(b); Vec2d n1, n2; Vec2d v_a, v_b, v_c, v_d; v_a = _g.getVertexPosition(a); v_b = _g.getVertexPosition(b); v_c = _g.getVertexPosition(c); v_d = _g.getVertexPosition(d); n1.diff(v_a, v_c); n2.diff(v_b, v_d); Vec2d m; double ang = Vec2d::angle(n1, n2); if (fabs(ang) < vars.molecule.AngleTreshold || fabs(ang - PI) < vars.molecule.AngleTreshold ) { m.middle(v_a, v_b); } else { m.copy(Algebra::linesIntersection(vars, v_a, v_c, v_b, v_d)); } middle.add(m); } } middle.scale(2.0 / (s * (s - 1))); Vertex newVertex = addVertex(middle); for (int j = 0; j < s; j++) { Vertex e = nearest[j]; Vertex b = *_g.adjacencyBegin(e); Edge bond = _g.getEdge(e, b).first; BondType t = _g.getEdgeBond(bond).type; _g.removeEdge(bond); _g.removeVertex(e); addBond(b, newVertex, t); } _mapping[newVertex] = &l; } std::deque<Skeleton::Vertex> deck; //Removing dots without labels for (SkeletonGraph::vertex_iterator begin = _g.vertexBegin(), end = _g.vertexEnd(); begin != end; ++begin) { SkeletonGraph::vertex_descriptor v = *begin; if (_g.getDegree(v) == 0 && _mapping.find(v) == _mapping.end()) deck.push_back(v); } for (Skeleton::Vertex v : deck) _g.removeVertex(v); }