Пример #1
0
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();
}
Пример #2
0
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() );
}
Пример #3
0
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. );
}
Пример #4
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();
}