示例#1
0
toxi::geom::Vec2D toxi::geom::Polygon2D::getCentroid()
{
	Vec2D res = Vec2D();
	for (int i = 0, num = vertices.size(); i < num; i++) 
	{
		Vec2D a = vertices.at(i);
		Vec2D b = vertices.at( ( i + 1 ) % num );
		double crossP = a.getX() * b.getY() - b.getX() * a.getY();
		res.set( res.getX() +  (a.getX() + b.getX()) * crossP, res.getY() + (a.getY() + b.getY()) * crossP );
	}
	return res.scale(1 / (6 * getArea()));
}
示例#2
0
bool toxi::geom::Polygon2D::toOutLine()
{
	int corners = vertices.size();
	int maxSegs = corners * 3;
	std::vector<Vec2D> newVerts;

	std::vector< Vec2D > segments( maxSegs );
	std::vector< Vec2D > segEnds( maxSegs );
	std::vector< double > segAngles( maxSegs );

	//Vec2D * segments;
	//segments = ( Vec2D* ) malloc( sizeof( Vec2D ) * maxSegs);
	//Vec2D * segEnds;
	//segEnds = (Vec2D * ) malloc(sizeof( Vec2D ) * maxSegs );
	//float * segAngles;
	//segAngles = (float * ) malloc( sizeof( float ) * maxSegs );
	//Vec2D[] segments = new Vec2D[maxSegs];
	//Vec2D[] segEnds = new Vec2D[maxSegs];
	//float[] segAngles = new float[maxSegs];
	Vec2D start = vertices.at(0);
	double lastAngle = toxi::math::MathUtils::PI;
	float a, b, c, d, e, f;
	double angleDif, bestAngleDif;
	int i, j = corners - 1, segs = 0;

	if (corners > maxSegs) {
		return false;
	}

	// 1,3. Reformulate the polygon as a set of line segments, and choose a
	// starting point that must be on the perimeter.
	for (i = 0; i < corners; i++) {
		Vec2D pi = vertices.at(i);
		Vec2D pj = vertices.at(j);
		if (!( pi == pj )) {
			segments[segs] = pi;
			segEnds[segs++] = pj;
		}
		j = i;
		if (pi.getY() > start.getY() || (pi.getY() == start.getY() && pi.getX() < start.getX())) {
			start.set( pi);
		}
	}
	if (segs == 0) {
		return false;
	}

	// 2. Break the segments up at their intersection points.
	for (i = 0; i < segs - 1; i++) {
		for (j = i + 1; j < segs; j++) {
			Line2D li = toxi::geom::Line2D( segments[i], segEnds[i]);
			Line2D lj = toxi::geom::Line2D( segments[j], segEnds[j]);
			LineIntersection isec = li.intersectLine( lj );
			if (isec.getType() == toxi::geom::LineIntersection::Type::INTERSECTING) {
				Vec2D ipos = isec.getPos();
				if (!( ipos == segments[i] ) && !( ipos == segEnds[i])) {
					if (segs == maxSegs) {
						return false;
					}
					segments[segs] = segments[i];
					segEnds[segs++] = ipos;
					segments[i] = ipos;
				}
				if (!( ipos == segments[j] ) && !( ipos ==  segEnds[ j ] ) ) {
					if (segs == maxSegs) {
						return false;
					}
					segments[segs] = segments[j];
					segEnds[segs++] = ipos;
					segments[j] = ipos;
				}
			}
		}
	}

	// Calculate the angle of each segment.
	for (i = 0; i < segs; i++) {
		segAngles[i] = segEnds[i].sub( segments[i] ).positiveHeading();
	}

	// 4. Build the perimeter polygon.
	c = static_cast< float > ( start.getX() );
	d = static_cast< float > ( start.getY() );
	a = c - 1;
	b = d;
	e = 0;
	f = 0;
	newVerts.push_back(Vec2D(c, d));
	corners = 1;
	while (true) {
		bestAngleDif = toxi::math::MathUtils::TWO_PI;
		for (i = 0; i < segs; i++) {
			if (segments[i].getX() == c && segments[i].getY() == d
				&& (segEnds[i].getX() != a || segEnds[i].getY() != b)) {
					angleDif = lastAngle - segAngles[i];
					while (angleDif >= toxi::math::MathUtils::TWO_PI) {
						angleDif -= toxi::math::MathUtils::TWO_PI;
					}
					while (angleDif < 0) {
						angleDif += toxi::math::MathUtils::TWO_PI;
					}
					if (angleDif < bestAngleDif) {
						bestAngleDif = angleDif;
						e =  static_cast< float > ( segEnds[i].getX() );
						f = static_cast< float > ( segEnds[i].getY() );
					}
			}
			if (segEnds[i].getX() == c && segEnds[i].getY() == d
				&& (segments[i].getX() != a || segments[i].getY() != b)) {
					angleDif = lastAngle - segAngles[i] + toxi::math::MathUtils::PI;
					while (angleDif >= toxi::math::MathUtils::TWO_PI) {
						angleDif -= toxi::math::MathUtils::TWO_PI;
					}
					while (angleDif < 0) {
						angleDif += toxi::math::MathUtils::TWO_PI;
					}
					if (angleDif < bestAngleDif) {
						bestAngleDif = angleDif;
						e = static_cast< float > ( segments[i].getX() );
						f = static_cast< float > ( segments[i].getY() );
					}
			}
		}
		if (corners > 1 && c == newVerts.at(0).getX() && d == newVerts.at(0).getY()
			&& e == newVerts.at(1).getX() && f == newVerts.at(1).getY()) {
				corners--;
				vertices = newVerts;
				return true;
		}
		if (bestAngleDif == toxi::math::MathUtils::TWO_PI || corners == maxSegs) {
			return false;
		}
		lastAngle -= bestAngleDif + toxi::math::MathUtils::PI;
		newVerts.push_back(Vec2D(e, f));
		corners++;
		a = c;
		b = d;
		c = e;
		d = f;
	}
}