示例#1
0
bool Triangle::IntersectCylinder(const Point& c0, const Point& c1, const double radius) const
{
	// check intersection with the edges
	if(SegmentSegmentDistance(p0, p1, c0, c1) < radius)
		return true;
	if(SegmentSegmentDistance(p1, p2, c0, c1) < radius)
		return true;
	if(SegmentSegmentDistance(p2, p1, c0, c1) < radius)
		return true;

	// check intersection with the inner 
	Point n = ((p0-p1)^(p0-p2)).Normalize();
	Point intersect;

	double origin = n|p0;
	double nC0 = (n|c0) - origin;
	double nC1 = (n|c1) - origin;

	if(nC0*nC1 > 0)
	{

		if(abs(nC0) < abs(nC1))
		{
			if(abs(nC0) > radius)
				return false;

			intersect = c0 - n*nC0;
		}
		else
		{
			if(abs(nC1) > radius)
				return false;

			intersect = c1 - n*nC1;
		}
	}
	else
	{
		Point dir = c1 - c0;
		intersect = c0 + (nC0/(dir|n))*dir.Normalize();
	}

	return IntersectPoint(intersect);
}
示例#2
0
bool
CPolygonBinaryOp(const CPolygon2D &poly1, const CPolygon2D &poly2, CBinaryOp op,
                 std::vector<CPolygon2D> &rpolys)
{
  int n1 = poly1.getNumPoints();
  int n2 = poly2.getNumPoints();

  if (n1 < 3 || n2 < 3) return false;

  //------

  // build list of node points for first polygon
  NodePointArray points1;

  NodePointMap pointMap1;

  {
  // find first point of poly1 not inside poly2
  int ii = 0;

  for ( ; ii < n1; ++ii) {
    const CPoint2D &p = poly1.getPoint(ii);

    if (! poly2.insideEvenOdd(p))
      break;
  }

  // if all inside then we are done
  if (ii >= n1) {
    if      (op == CBINARY_OP_OR)
      rpolys.push_back(poly1);
    else if (op == CBINARY_OP_AND)
      rpolys.push_back(poly1);

    return true;
  }

  //----

  bool inside1 = false;
  bool inside2 = inside1;

  int np = 0;

  for (int i = 0, i1 = ii, i2 = i1 + 1; i < n1; ++i, i1 = i2++, inside1 = inside2) {
    FIX_IND(i2, n1);

    const CPoint2D &p1 = poly1.getPoint(i1);
    const CPoint2D &p2 = poly1.getPoint(i2);

    inside2 = poly2.insideEvenOdd(p2);

    // find intersection points of this edge with other polygon's edges
    std::vector<IntersectPoint> idata;

    for (int j1 = n2 - 1, j2 = 0; j2 < n2; j1 = j2++) {
      // calc intersection (if any)
      const CPoint2D &p21 = poly2.getPoint(j1);
      const CPoint2D &p22 = poly2.getPoint(j2);

      CPoint2D pi;
      double   mu1, mu2;

      if (! CMathGeom2D::IntersectLine(p1, p2, p21, p22, &pi, &mu1, &mu2))
        continue;

      if (mu1 <= 0.0 || mu1 >= 1.0 || mu2 <= 0.0 || mu2 >= 1.0)
        continue;

      // save intersection data
      int id = CALC_ID(i1, j1, n1);

      idata.push_back(IntersectPoint(mu1, pi, id));
    }

    // sort multiple intersects by mu1
    std::sort(idata.begin(), idata.end());

    // add intersect points
    uint n = idata.size();

    for (uint k = 0; k < n; ++k) {
      NodePoint *np1 = new NodePoint(NodePoint::INTERSECT, np++, idata[k].id, idata[k].p);

      points1.push_back(np1);

      pointMap1[idata[k].id] = np1;
    }

    // add end of line
    NodePoint *np1 = new NodePoint((inside2 ? NodePoint::INSIDE : NodePoint::OUTSIDE), np++, 0, p2);

    points1.push_back(np1);
  }
  }

  //-----

  // build list of node points for second polygon
  NodePointArray points2;

  NodePointMap pointMap2;

  {
  // find first point of poly2 not inside poly1
  int ii = 0;

  for ( ; ii < n1; ++ii) {
    const CPoint2D &p = poly2.getPoint(ii);

    if (! poly1.insideEvenOdd(p))
      break;
  }

  // if all inside then we are done
  if (ii >= n1) {
    if      (op == CBINARY_OP_OR)
      rpolys.push_back(poly2);
    else if (op == CBINARY_OP_AND)
      rpolys.push_back(poly2);

    return true;
  }

  //----

  bool inside1 = false;
  bool inside2 = inside1;

  int np = 0;

  for (int i = 0, i1 = ii, i2 = i1 + 1; i < n2; ++i, i1 = i2++, inside1 = inside2) {
    FIX_IND(i2, n2);

    const CPoint2D &p1 = poly2.getPoint(i1);
    const CPoint2D &p2 = poly2.getPoint(i2);

    inside2 = poly1.insideEvenOdd(p2);

    // find intersection points of this edge with other polygon's edges
    std::vector<IntersectPoint> idata;

    for (int j1 = n1 - 1, j2 = 0; j2 < n1; j1 = j2++) {
      int id = CALC_ID(j1, i1, n1);

      // skip if no intersection (faster ?)
      NodePointMap::const_iterator p = pointMap1.find(id);

      if (p == pointMap1.end()) continue;

      // calc intersection
      const CPoint2D &p21 = poly1.getPoint(j1);
      const CPoint2D &p22 = poly1.getPoint(j2);

      CPoint2D pi;
      double   mu1, mu2;

      bool rc = CMathGeom2D::IntersectLine(p1, p2, p21, p22, &pi, &mu1, &mu2);

      assert(rc && mu1 > 0.0 && mu1 < 1.0 && mu2 > 0.0 && mu2 < 1.0);

      idata.push_back(IntersectPoint(mu1, pi, id));
    }

    // sort multiple intersects by mu1
    std::sort(idata.begin(), idata.end());

    // add intersect points
    uint n = idata.size();

    for (uint k = 0; k < n; ++k) {
      NodePoint *np1 = new NodePoint(NodePoint::INTERSECT, np++, idata[k].id, idata[k].p);

      points2.push_back(np1);

      pointMap2[idata[k].id] = np1;
    }

    // add end of line
    NodePoint *np1 = new NodePoint((inside2 ? NodePoint::INSIDE : NodePoint::OUTSIDE), np++, 0, p2);

    points2.push_back(np1);
  }
  }

  //-----

  // Connect Intersections between shapes
  assert(pointMap1.size() == pointMap2.size());

  NodePointMap::iterator pm1, pm2;

  for (pm1 = pointMap1.begin(), pm2 = pointMap1.end(); pm1 != pm2; ++pm1) {
    NodePoint *np1 = (*pm1).second;

    NodePointMap::iterator pm = pointMap2.find(np1->id);

    assert(pm != pointMap2.end());

    NodePoint *np2 = (*pm).second;

    np1->ip = np2;
    np2->ip = np1;
  }

  //-----

  // build list of points for boolean op
  if      (op == CBINARY_OP_OR) {
    CPolygon2D rpoly;

    while (CPolygonOrOp(points1, points2, rpoly))
      rpolys.push_back(rpoly);
  }
  else if (op == CBINARY_OP_AND) {
    CPolygon2D rpoly;

    while (CPolygonAndOp(points1, points2, rpoly))
      rpolys.push_back(rpoly);
  }
  else if (op == CBINARY_OP_XOR) {
    CPolygon2D rpoly;

    while (CPolygonXorOp(points1, points2, rpoly))
      rpolys.push_back(rpoly);
  }
  else if (op == CBINARY_OP_NOT) {
    CPolygon2D rpoly;

    while (CPolygonXorOp(points2, points1, rpoly))
      rpolys.push_back(rpoly);
  }

  return true;
}