int DPolygon::getCrossPoints(const DPolygon &p, List<DPoint> &crossPoints) const { crossPoints.clear(); ListConstIterator<DPoint> i, j; for (i = begin(); i.valid(); ++i) { DSegment s1 = segment(i); for (j = p.begin(); j.valid(); ++j) { DSegment s2 = p.segment(j); DPoint intersec; if (s1.intersection(s2, intersec)) crossPoints.pushBack(intersec); } } // unify the list ListIterator<DPoint> k, l; for (k = crossPoints.begin(); k.valid(); ++k) for (l = k, ++l; l.valid(); ++l) if (*k == *l) { --l; crossPoints.del(crossPoints.cyclicSucc(l)); } return crossPoints.size(); }
void GenPolygonTest::testDefaultConstructor() { // ------ // Set Up // ------ IPolygon iPoly; FPolygon fPoly; DPolygon dPoly; // ----- // Check // ----- CPPUNIT_ASSERT( iPoly.accessVertices().empty() ); CPPUNIT_ASSERT( fPoly.accessVertices().empty() ); CPPUNIT_ASSERT( dPoly.accessVertices().empty() ); }
void GenPolygonTest::testSerializeDeserialize() { // Triangle: (1.1, 2.2) (3.3, 4.4) (5.5, 6.6) // ^^^^^^^^^^ ^^^^^^^^^^ // source target list<DPoint> lp; lp.push_back(DPoint(1.1 , 2.2)); lp.push_back(DPoint(3.3 , 4.4)); lp.push_back(DPoint(5.5 , 6.6)); DPolygon oplg(lp); DPolygon iplg; stringstream ss; ss << oplg; ss >> iplg; ss.flush(); // Check source and target CPPUNIT_ASSERT_DOUBLES_EQUAL( oplg.xSource(), 1.1, 0. ); CPPUNIT_ASSERT_DOUBLES_EQUAL( oplg.ySource(), 2.2, 0. ); CPPUNIT_ASSERT_DOUBLES_EQUAL( oplg.xTarget(), 5.5, 0. ); CPPUNIT_ASSERT_DOUBLES_EQUAL( oplg.yTarget(), 6.6, 0. ); CPPUNIT_ASSERT_DOUBLES_EQUAL( iplg.xSource(), 1.1, 0. ); CPPUNIT_ASSERT_DOUBLES_EQUAL( iplg.ySource(), 2.2, 0. ); CPPUNIT_ASSERT_DOUBLES_EQUAL( iplg.xTarget(), 5.5, 0. ); CPPUNIT_ASSERT_DOUBLES_EQUAL( iplg.yTarget(), 6.6, 0. ); // Check vertices const deque<DPoint>& vo = oplg.accessVertices(); const deque<DPoint>& vi = iplg.accessVertices(); deque<DPoint>::const_iterator itVO = vo.begin(); deque<DPoint>::const_iterator itVI = vi.begin(); CPPUNIT_ASSERT_DOUBLES_EQUAL( itVO->x(), 1.1, 0. ); CPPUNIT_ASSERT_DOUBLES_EQUAL( itVO->y(), 2.2, 0. ); CPPUNIT_ASSERT_DOUBLES_EQUAL( itVI->x(), 1.1, 0. ); CPPUNIT_ASSERT_DOUBLES_EQUAL( itVI->y(), 2.2, 0. ); ++itVO; ++itVI; CPPUNIT_ASSERT_DOUBLES_EQUAL( itVO->x(), 3.3, 0. ); CPPUNIT_ASSERT_DOUBLES_EQUAL( itVO->y(), 4.4, 0. ); CPPUNIT_ASSERT_DOUBLES_EQUAL( itVI->x(), 3.3, 0. ); CPPUNIT_ASSERT_DOUBLES_EQUAL( itVI->y(), 4.4, 0. ); ++itVO; ++itVI; CPPUNIT_ASSERT_DOUBLES_EQUAL( itVO->x(), 5.5, 0. ); CPPUNIT_ASSERT_DOUBLES_EQUAL( itVO->y(), 6.6, 0. ); CPPUNIT_ASSERT_DOUBLES_EQUAL( itVI->x(), 5.5, 0. ); CPPUNIT_ASSERT_DOUBLES_EQUAL( itVI->y(), 6.6, 0. ); }
//TODO: Regard some kind of aspect ration (input) //(then also the rotation of a single component makes sense) void ComponentSplitterLayout::reassembleDrawings(GraphAttributes& GA, const Array<List<node> > &nodesInCC) { int numberOfComponents = nodesInCC.size(); Array<IPoint> box; Array<IPoint> offset; Array<DPoint> oldOffset; Array<double> rotation; ConvexHull CH; // rotate components and create bounding rectangles //iterate through all components and compute convex hull for (int j = 0; j < numberOfComponents; j++) { //todo: should not use std::vector, but in order not //to have to change all interfaces, we do it anyway std::vector<DPoint> points; //collect node positions and at the same time center average // at origin double avg_x = 0.0; double avg_y = 0.0; for (node v : nodesInCC[j]) { DPoint dp(GA.x(v), GA.y(v)); avg_x += dp.m_x; avg_y += dp.m_y; points.push_back(dp); } avg_x /= nodesInCC[j].size(); avg_y /= nodesInCC[j].size(); //adapt positions to origin int count = 0; //assume same order of vertices and positions for (node v : nodesInCC[j]) { //TODO: I am not sure if we need to update both GA.x(v) = GA.x(v) - avg_x; GA.y(v) = GA.y(v) - avg_y; points.at(count).m_x -= avg_x; points.at(count).m_y -= avg_y; count++; } // calculate convex hull DPolygon hull = CH.call(points); double best_area = numeric_limits<double>::max(); DPoint best_normal; double best_width = 0.0; double best_height = 0.0; // find best rotation by using every face as rectangle border once. for (DPolygon::iterator j = hull.begin(); j != hull.end(); ++j) { DPolygon::iterator k = hull.cyclicSucc(j); double dist = 0.0; DPoint norm = CH.calcNormal(*k, *j); for (const DPoint &z : hull) { double d = CH.leftOfLine(norm, z, *k); if (d > dist) { dist = d; } } double left = 0.0; double right = 0.0; norm = CH.calcNormal(DPoint(0, 0), norm); for (const DPoint &z : hull) { double d = CH.leftOfLine(norm, z, *k); if (d > left) { left = d; } else if (d < right) { right = d; } } double width = left - right; dist = max(dist, 1.0); width = max(width, 1.0); double area = dist * width; if (area <= best_area) { best_height = dist; best_width = width; best_area = area; best_normal = CH.calcNormal(*k, *j); } } if (hull.size() <= 1) { best_height = 1.0; best_width = 1.0; best_area = 1.0; best_normal = DPoint(1.0, 1.0); } double angle = -atan2(best_normal.m_y, best_normal.m_x) + 1.5 * Math::pi; if (best_width < best_height) { angle += 0.5f * Math::pi; double temp = best_height; best_height = best_width; best_width = temp; } rotation.grow(1, angle); double left = hull.front().m_x; double top = hull.front().m_y; double bottom = hull.front().m_y; // apply rotation to hull and calc offset for (DPoint tempP : hull) { double ang = atan2(tempP.m_y, tempP.m_x); double len = sqrt(tempP.m_x*tempP.m_x + tempP.m_y*tempP.m_y); ang += angle; tempP.m_x = cos(ang) * len; tempP.m_y = sin(ang) * len; if (tempP.m_x < left) { left = tempP.m_x; } if (tempP.m_y < top) { top = tempP.m_y; } if (tempP.m_y > bottom) { bottom = tempP.m_y; } } oldOffset.grow(1, DPoint(left + 0.5 * static_cast<double>(m_border), -1.0 * best_height + 1.0 * bottom + 0.0 * top + 0.5 * (double)m_border)); // save rect int w = static_cast<int>(best_width); int h = static_cast<int>(best_height); box.grow(1, IPoint(w + m_border, h + m_border)); }// components offset.init(box.size()); // call packer m_packer.get().call(box, offset, m_targetRatio); int index = 0; // Apply offset and rebuild Graph for (int j = 0; j < numberOfComponents; j++) { double angle = rotation[index]; // apply rotation and offset to all nodes for (node v : nodesInCC[j]) { double x = GA.x(v); double y = GA.y(v); double ang = atan2(y, x); double len = sqrt(x*x + y*y); ang += angle; x = cos(ang) * len; y = sin(ang) * len; x += static_cast<double>(offset[index].m_x); y += static_cast<double>(offset[index].m_y); x -= oldOffset[index].m_x; y -= oldOffset[index].m_y; GA.x(v) = x; GA.y(v) = y; }// while nodes in component index++; } // for components //now we center the whole graph again //TODO: why? //const Graph& G = GA.constGraph(); //for(node v : G.nodes) //MLG.moveToZero(); }