CurveCurve下有一个IntersectionsXY函数,可以计算出两条曲线的交点。此函数虽然有三个重载形式,但传入的参数实际上都是两条曲线,函数将这两条曲线之间相交的部分分别投影到这两条曲线上并返回给我们。从这个函数的名字我们可以看出来其在计算相交部分时,是忽略了投影方向的Z坐标的,所以在这篇wiki“计算三维空间线真实交点”中介绍了如何得到两条曲线的真实交点。假如我们不是要计算真实交点,而仅仅是想得到从某个方向(例如其中一条曲线所在的平面的法向量)看过去两条线的交点的话,应该怎么做呢。IntersectionsXY函数还有一个“DMatrix4dCP pWorldToLocal”参数,通过这个参数我们可以指定计算相交部分时从哪个方向去投影计算。如下代码演示了如何求得从第一个曲线所在平面的法向量投影后两条曲线的交点。
void TestIntersectionsXY()
{
ElementAgenda selectset;
SelectionSetManager::GetManager().BuildAgenda(selectset);
if (selectset.GetCount() < 2)
{
return;
}
EditElementHandleR eeh1 = selectset[0];
EditElementHandleR eeh2 = selectset[1];
CurveVectorPtr cveVec1 = ICurvePathQuery::ElementToCurveVector(eeh1);
CurveVectorPtr cveVec2 = ICurvePathQuery::ElementToCurveVector(eeh2);
DPoint3d pt1, pt2,pt3;
cveVec1->GetStartPoint(pt1);
CurveLocationDetail detail;
cveVec1->at(0)->FractionToPoint(0.5, detail);
pt2 = detail.point;
cveVec1->at(0)->FractionToPoint(0.7, detail);
pt3 = detail.point;
DVec3d vecXLoc = DVec3d::FromStartEnd(pt1, pt2);
DVec3d vecYLoc = DVec3d::FromStartEnd(pt1, pt3);
DVec3d vecZLoc = DVec3d::FromCrossProduct(vecXLoc, vecYLoc);
vecZLoc.Normalize();
DMatrix4d dMatr4d;
if (1 != vecZLoc.z)
{
vecYLoc = DVec3d::FromCrossProduct(vecZLoc, vecXLoc);
vecXLoc.Normalize();
vecYLoc.Normalize();
RotMatrix rMatrix = RotMatrix::FromRowVectors(vecXLoc, vecYLoc, vecZLoc);
dMatr4d = DMatrix4d::From(rMatrix);
}
else
{
dMatr4d.InitIdentity();
}
CurveVectorPtr cveVecA = CurveVector::Create(CurveVector::BoundaryType::BOUNDARY_TYPE_Open), cveVecB = CurveVector::Create(CurveVector::BoundaryType::BOUNDARY_TYPE_Open);
CurveCurve::IntersectionsXY(*cveVecA, *cveVecB, *cveVec1, *cveVec2, &dMatr4d);
if (!cveVecB.IsNull()&& cveVecB.IsValid())
{
bvector<DPoint3d> vecPt;
for (int i = 0; i < cveVecB->size(); i++)
{
cveVecB->at(i)->GetStartPoint(pt1);
vecPt.push_back(pt1);
}
ICurvePrimitivePtr cvePri = ICurvePrimitive::CreateLineString(vecPt);
EditElementHandle eehInter;
DraftingElementSchema::ToElement(eehInter, *cvePri, NULL, ACTIVEMODEL->Is3d(), *ACTIVEMODEL);
eehInter.AddToModel();
}
}