Beispiel #1
0
int Line::intersect(std::list<Kernel::V3D> &PntOut, const Cylinder &Cyl) const
/**
For the line that intersects the cylinder generate
add the point to the VecOut, return number of points
added. It does not check the points for validity.

@param PntOut :: Vector of points found by the line/cylinder intersection
@param Cyl :: Cylinder to intersect line with
@return Number of points found by intersection
*/
{
    const Kernel::V3D Cent = Cyl.getCentre();
    const Kernel::V3D Ax = Origin - Cent;
    const Kernel::V3D N = Cyl.getNormal();
    const double R = Cyl.getRadius();
    const double vDn = N.scalar_prod(Direct);
    const double vDA = N.scalar_prod(Ax);
    // First solve the equation of intersection
    double C[3];
    C[0] = 1.0 - (vDn * vDn);
    C[1] = 2.0 * (Ax.scalar_prod(Direct) - vDA * vDn);
    C[2] = Ax.scalar_prod(Ax) - (R * R + vDA * vDA);
    std::pair<std::complex<double>, std::complex<double>> SQ;
    const int ix = solveQuadratic(C, SQ);
    // This takes the centre displacement into account:
    return lambdaPair(ix, SQ, PntOut);
}
Vector ClosestPointCylinder ( Vector const & V, Cylinder const & C )
{
	Vector delta = V - C.getBase();

	delta.y = 0.0f;

	real dist = delta.magnitude();

	Vector point = V;

	// clamp the x-z coords of the point so they're inside the tube

	IGNORE_RETURN( delta.normalize() );
	delta *= std::min( C.getRadius(), dist );
	
	point = C.getBase() + delta;

	// and clamp the y coord so it's inside also

	real min = C.getBase().y;
	real max = min + C.getHeight();

	point.y = clamp( min, V.y, max );

	return point;
}
ContainmentResult  TestCylinderCylinder ( Cylinder const & A,
                                          Cylinder const & B )
{
	Vector delta = B.getBase() - A.getBase();
	delta.y = 0;

	real dist = delta.magnitude();

	Range AD( dist - A.getRadius(), dist + A.getRadius() );
	Range BD( -B.getRadius(), B.getRadius() );

	ContainmentResult hTest = Containment1d::TestRangeRange( AD, BD );
	ContainmentResult vTest = Containment1d::TestRangeRange( A.getRangeY(), B.getRangeY() );

	// ----------

	return Containment::ComposeAxisTests(hTest,vTest);
}
ContainmentResult  TestPointCylinder    ( Vector const & V,
                                          Cylinder const & C )
{
	Vector delta = V - C.getBase();
	delta.y = 0;

	real dist = delta.magnitude();
	real radius = C.getRadius();

	ContainmentResult rTest = Containment1d::TestFloatLess(dist,radius);
	ContainmentResult vTest = Containment1d::TestFloatRange(V.y, C.getRangeY());

	// ----------

	return Containment::ComposeAxisTests(rTest,vTest);
}
/*!
 * \brief RectifyToVector::setUpResult
 * \param cylinder
 * \return
 */
bool RectifyToVector::setUpResult(Cylinder &cylinder)
{
    //get and check cylinder
    if(!this->inputElements.contains(0) || this->inputElements[0].size() != 1){
        return false;
    }
    QPointer<Geometry> geometry = this->inputElements[0].at(0).geometry;
    if(geometry.isNull() || !geometry->getIsSolved() || !geometry->hasDirection()){
        return false;
    }

    //get the sense (positive or negative)
    double sense = 1.0;
    if(this->scalarInputParams.stringParameter.contains("sense")){
        if(this->scalarInputParams.stringParameter.value("sense").compare("negative") == 0){
            sense = -1.0;
        }
    }

    //get the direction to compare
    OiVec r_reference = geometry->getDirection().getVector();
    r_reference.normalize();
    OiVec r_cylinder = cylinder.getDirection().getVector();
    r_cylinder.normalize();

    //calculate the angle between both directions
    double angle = 0.0;
    OiVec::dot(angle, r_reference, r_cylinder);
    angle = qAbs(qAcos(angle));

    //invert the normal vector if the angle is greater than 90°
    if(angle > PI/2.0){
        r_cylinder = -1.0 * r_cylinder;
    }

    //invert the normal vector if sense is negative
    r_cylinder = sense * r_cylinder;

    //set result
    Direction direction = cylinder.getDirection();
    direction.setVector(r_cylinder);
    cylinder.setCylinder(cylinder.getPosition(), direction, cylinder.getRadius());

    return true;
}
bool TestYLineCylinder ( Vector const & V, Cylinder const & C )
{
	return Distance2d::Distance2PointPoint(V,C.getBase()) < sqr(C.getRadius());
}
ContainmentResult  TestSphereCylinder ( Sphere const & S,
									    Cylinder const & C )
{
	Vector delta = C.getBase() - S.getCenter();
	delta.y = 0;

	real dist = delta.magnitude();

	Range SD( dist - S.getRadius(), dist + S.getRadius() );

	Range CD( -C.getRadius(), C.getRadius() );

	ContainmentResult hTest = Containment1d::TestRangeRange( SD, CD );
	ContainmentResult hTest2 = Containment1d::TestFloatRange( dist, CD );

	ContainmentResult vTest = Containment1d::TestRangeRange( S.getRangeY(), C.getRangeY() );
	ContainmentResult cTest = Containment1d::TestFloatRange( S.getCenter().y, C.getRangeY() );

	// ----------

	if(hTest == CR_Outside)
	{
		// Sphere can't possibly touch the cylinder

		return CR_Outside;
	}
	else if((hTest == CR_TouchingOutside) || (hTest == CR_Boundary))
	{
		// Sphere is touching the outside of the cylinder's tube if its
		// center is inside the vertical range of the cylinder

		if((cTest == CR_Inside) || (cTest == CR_Boundary))
		{
			return CR_TouchingOutside;
		}
		else
		{
			return CR_Outside;
		}
	}
	else if((hTest == CR_Inside) || (hTest == CR_TouchingInside))
	{
		// Sphere is in the tube of the cylinder. It touches the cylinder
		// if its vertical range touches the vertical range of the cylinder

		return Containment::ComposeAxisTests(hTest,vTest);
	}
	else
	{
		// hTest == CR_Overlap

		if(vTest == CR_Outside)
		{
			return CR_Outside;
		}
		else if((vTest == CR_Inside) || (vTest == CR_TouchingInside))
		{
			return CR_Overlap;
		}
		else if (vTest == CR_Boundary)
		{
			// This really shouldn't be happening
			return CR_Boundary;
		}
		else if (vTest == CR_TouchingOutside)
		{
			if(hTest2 == CR_Inside)
			{
				// Sphere is touching a cap of the cylinder
				return CR_TouchingOutside;
			}
			else if(hTest2 == CR_Boundary)
			{
				// Sphere is touching the edge of the cap of the cylinder
				return CR_TouchingOutside;
			}
			else
			{
				// Sphere isn't touching the cap
				return CR_Outside;
			}
		}
		else
		{
			// vTest == CR_Overlap

			if((cTest == CR_Inside) || (cTest == CR_Boundary))
			{
				// The ranges overlap vertically and horizontally, and the center of
				// the sphere is inside the vertical range - the sphere overlaps the
				// cylinder

				return CR_Overlap;
			}
			else
			{
				// The sphere is inside both ranges, but its center is outside both
				// ranges. The sphere overlaps the cylinder if the closest point
				// on the cylinder is inside the sphere.

				Vector closestPoint = Distance3d::ClosestPointCylinder(S.getCenter(),C);

				ContainmentResult result = TestPointSphere(closestPoint,S);

				if(result == CR_Outside)
				{
					return CR_Outside;
				}
				else if(result == CR_Boundary)
				{
					return CR_TouchingOutside;
				}
				else
				{
					return CR_Overlap;
				}
			}
		}
	}
}
Beispiel #8
0
C3DModel CTriangulator<Real, Cylinder<Real> >::Triangulate(const Cylinder<Real> &pShape)
{

  Vector3<Real> center  = pShape.getCenter();
  Vector3<Real> u       = pShape.getU();
  Real height2           = pShape.getHalfLength();
  Real rad               = pShape.getRadius();

  C3DModel model;

  std::vector<Vector3<Real> > vVertices;
  std::vector<TriFace>         vFaces;

  int verticalsegments = 2;
  int pointsoncircle   = 24;

  Real dalpha = 2.0 * CMath<Real>::SYS_PI/(Real)pointsoncircle;

  Vector3<Real> vTop    = center + (height2 * u);
  Vector3<Real> vBottom = center - (height2 * u);
  vVertices.push_back(vTop);

  Real dheight = (2.0 * height2)/Real(verticalsegments+1);
  Real currentheight = center.z + height2;
  Real alpha = 0.0;

  //create the vertices
  for(int j=0;j<(verticalsegments+2);j++)
  {
    for(int i=0;i<pointsoncircle;i++)
    {
      Vector3<Real> vNext=pShape.eval(alpha);
      vNext.z = currentheight;
      vVertices.push_back(vNext);
      alpha+=dalpha;
    }
    alpha=0.0;
    currentheight-=dheight;
  }

  vVertices.push_back(vBottom);

  //add the top triangle fan
  for(int i=0;i<pointsoncircle;i++)
  {
    int verts[3];
    verts[0]=0;
    verts[1]=1+i;
    verts[2]=1+(i+1)%pointsoncircle;
    TriFace face(verts);
    vFaces.push_back(face);
  }

  //add the body of the cylinder
  int index = 1;
  for(int i=0;i<verticalsegments+1;i++)
  {
	  int index=1+i*pointsoncircle;
	  for(int j=0;j<pointsoncircle;j++)
	  {
	    int verts[3];
	    verts[0]=index+j;
	    verts[1]=index+pointsoncircle+j;
	    verts[2]=index+(j+1)%pointsoncircle;

	    TriFace face1(verts);
	    vFaces.push_back(face1);
	    verts[0]=index+(j+1)%pointsoncircle;
	    verts[1]=index+pointsoncircle+j;
	    verts[2]=index+pointsoncircle+(j+1)%pointsoncircle;
	    TriFace face2(verts);
	    vFaces.push_back(face2);
	  }
  }//end for i

  int ilast=vVertices.size()-1;
  int ilastrow=ilast-pointsoncircle;
  //add lower triangle fan
  for(int i=0;i<pointsoncircle;i++)
  {
	int verts[3];
	verts[0]=ilast;
	verts[1]=ilastrow+(i+1)%pointsoncircle;
	verts[2]=ilastrow+i;
	TriFace face(verts);
	vFaces.push_back(face);
  }

  model.CreateFrom(vVertices,vFaces);

  return model;

}