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; } } } } }
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; }