马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。
您需要 登录 才可以下载或查看,没有账号?立即注册
×
判断点是否在曲线内,可以用REGION的方法,但是更快的是用射线法,下面是实现代码
[C++] 纯文本查看 复制代码 enum IncidenceType
{
kIncidenceToLeft = 0,
kIncidenceToRight,
kIncidenceToFront,
kIncidenceUnknown
};
IncidenceType CurveIncidence(const AcDbCurve* pCurve,
const double& param,
const AcGeVector3d& dir,
const AcGeVector3d& normal)
{
AcGeVector3d deriv1;
pCurve->getFirstDeriv(param, deriv1);
if(deriv1.isParallelTo(dir))
{
// need second degree analysis
AcGeVector3d deriv2;
pCurve->getSecondDeriv(param, deriv2);
if(deriv2.isZeroLength() || deriv2.isParallelTo(dir))
return kIncidenceToFront;
else
{
if(deriv2.crossProduct(dir).dotProduct(normal) < 0)
return kIncidenceToRight;
else
return kIncidenceToLeft;
}
}
if(deriv1.crossProduct(dir).dotProduct(normal) < 0)
return kIncidenceToLeft;
else
return kIncidenceToRight;
}
Acad::ErrorStatus IsInsideCurve(const AcDbCurve* pCurve,
const AcGePoint3d& testPt,
bool& result)
{
result = false;
if(!pCurve->isClosed() || !pCurve)
{
//Curve needs to be closed
return Acad::eInvalidInput;
}
Acad::ErrorStatus es;
AcDb2dPolyline*p2dPoly = AcDb2dPolyline::cast(pCurve);
if(p2dPoly != NULL && p2dPoly->polyType() != AcDb::k2dSimplePoly)
{
// Not supported
return Acad::eInvalidInput;
}
AcGePoint3d ptOnCurve;
es = pCurve->getClosestPointTo(testPt, ptOnCurve);
if(testPt.isEqualTo(ptOnCurve))
{
result = true;
return es;
}
// check its planar
AcGePlane plane;
AcDb::Planarity planarity;
if((es = pCurve->getPlane(plane, planarity)) != Acad::eOk)
{
return es;
}
if(planarity != AcDb::kPlanar)
{
return Acad::eInvalidInput;
}
// make the test ray from the plane
double epsilon = 2e-6; // ( trust me on this )
AcGePoint3dArray IntersectionPoints;
AcGeVector3d normal = plane.normal();
AcGeVector3d testVector = normal.perpVector();
AcDbRay ray;
ray.setBasePoint(testPt);
int nGlancingHits=0, numberOfInters=0;
bool bRetryWithOtherRayDirection;
do
{
IntersectionPoints.removeAll();
bRetryWithOtherRayDirection = false;
ray.setUnitDir(testVector);
// fire the ray at the curve
if((es = pCurve->intersectWith(&ray, AcDb::kOnBothOperands, IntersectionPoints)) != Acad::eOk)
return es;
numberOfInters = IntersectionPoints.length();
nGlancingHits = 0;
for(int i=0; i < numberOfInters; ++i)
{
// get the first point, and get its parameter
AcGePoint3d hitPt = IntersectionPoints[i];
double hitParam;
//Circumvents an issue with AcDbCurve::getParamAtPoint API
if((es = pCurve->getParamAtPoint(hitPt, hitParam )) != Acad::eOk)
{
bRetryWithOtherRayDirection = true;
testVector.rotateBy(5.0 * 3.141592653/180.0, normal);
break;
}
double inParam = hitParam - epsilon;
double outParam = hitParam + epsilon;
double startParam, endParam;
pCurve->getStartParam(startParam);
pCurve->getEndParam(endParam);
//Loop back inside the curve if param is falling outside of range
if (inParam < startParam)
inParam = endParam - epsilon + (startParam - inParam);
if (outParam > endParam)
outParam = startParam + epsilon + (endParam - outParam);
IncidenceType inIncidence = CurveIncidence(pCurve, inParam, testVector, normal);
IncidenceType outIncidence = CurveIncidence(pCurve, outParam, testVector, normal);
if (inIncidence == kIncidenceToFront || outIncidence == kIncidenceToFront)
{
bRetryWithOtherRayDirection = true;
testVector.rotateBy(5.0 * 3.141592653/180.0, normal);
break;
}
if( (inIncidence == kIncidenceToRight && outIncidence == kIncidenceToLeft) ||
(inIncidence == kIncidenceToLeft && outIncidence == kIncidenceToRight))
{
++nGlancingHits;
}
}
}
while (bRetryWithOtherRayDirection);
result = (( numberOfInters + nGlancingHits) % 2 == 1);
return es;
}
|