老师好:
我根据您的例子,做了一个放样测试,希望实现 三个矩形 根据 空间坐标的不同, 做一个类似于T型梁的效果,如果按照两个截面做,没有问题,但是 如果是三个截面,每一个截面左下角顶点相连,作为向导线,从而构成一个实体。
下面代码,报Error in BodyFromLoft的错误,或者 放置不成功。向导线 我也做了一个 ,也不成功。恳请老师 过目,帮忙分析一下具体原因。 代码可以测试执行。
void createLoftSolid(DPoint3dR basePt) { //数据准备阶段 int x1=150,x2=3650,x3=100,x4=2200,x5=100,x6=3650,x7=150; int y1=300,y2=2400,y3=300; int x1Len=x1+x2+x3+x4+x5+x6+x7; int y1Len=y1+y2+y3; //int nKouCaoy=100; //int nKouCaox=400; //int nKouCaoDx=350; int nHigthZ1=800; int nHigthZ2=900; //int nradius=50; //构建放样的导向线 DPoint3d Pts[3]; Pts[0].x = basePt.x-x4/2; Pts[0].y = basePt.y-y2/2; Pts[0].z = basePt.z; Pts[1].x = basePt.x-x4/2-x3-x2-x1; Pts[1].y = basePt.y-y1Len/2; Pts[1].z = basePt.z+nHigthZ1; Pts[2].x = basePt.x-x1Len/2+x1; Pts[2].y = basePt.y-y2/2; Pts[2].z = basePt.z+nHigthZ1+nHigthZ2; /***********************************************************************************************************/ // 2 ---- 创建 CurveVectorPtr 数组 存储 CurveVector,并将两个圆 CurveVectorPtr profileVec[3]; //BOUNDARY_TYPE_Outer is important, it can create a closed profile that further makes a solid instead of a sheet profileVec[0] = CurveVector::Create(CurveVector::BOUNDARY_TYPE_Outer); profileVec[0]->Add(ICurvePrimitive::CreateRectangle (basePt.x-x4/2,basePt.y-y2/2,basePt.x+x4/2,basePt.y+y2/2,basePt.z) );//最下面的矩形 也是最小的 profileVec[1] = CurveVector::Create( CurveVector::BOUNDARY_TYPE_Outer); profileVec[1]->Add(ICurvePrimitive::CreateRectangle (basePt.x-x1Len/2,basePt.y-y1Len/2,basePt.x+x1Len/2,basePt.y+y1Len/2,basePt.z+nHigthZ1));//中间的矩形,也是最大的矩形 profileVec[2] = CurveVector::Create( CurveVector::BOUNDARY_TYPE_Outer); profileVec[2]->Add(ICurvePrimitive::CreateRectangle (basePt.x-x1Len/2+x1,basePt.y-y2/2,basePt.x+x1Len/2-x1,basePt.y+y2/2,basePt.z+nHigthZ1+nHigthZ2));//最上面的矩形, DSegment3d seg; seg.Init(Pts[0],Pts[1] ); CurveVectorPtr guideVec[2]; guideVec[0] = CurveVector::Create(CurveVector::BOUNDARY_TYPE_Open); guideVec[1] = CurveVector::Create(CurveVector::BOUNDARY_TYPE_Open); guideVec[0]->Add(ICurvePrimitive::CreateLine(seg));//最下面和中间 两个矩形的连接线 也就是向导线 seg.Init(Pts[1],Pts[2] ); guideVec[1]->Add(ICurvePrimitive::CreateLine(seg));//中间和最上面 两个矩形的连接线 也就是向导线 /*//改成一个向导线 也不行。如下 CurveVectorPtr guideVec; guideVec= CurveVector::Create(CurveVector::BOUNDARY_TYPE_Open); guideVec->Add(ICurvePrimitive::CreateLineString(Pts , 3)); */ // 3 ---- Create Solid by Loft ISolidKernelEntityPtr solid; DgnModelP pActiveModel = ISessionMgr::GetActiveDgnModelP(); //if (SUCCESS != SolidUtil::Create::BodyFromLoft(solid, profileVec, 3, &guideVec, 1, *pActiveModel, false, true)) if (SUCCESS != SolidUtil::Create::BodyFromLoft(solid, profileVec, 3, guideVec, 2, *pActiveModel, false, true)) { mdlDialog_dmsgsPrint(L"Error in BodyFromLoft"); return; } // 4 ---- Convert Solid to EditElementHandle and add it to model if (solid.IsValid()) { EditElementHandle eeh; SolidUtil::Convert::BodyToElement(eeh, *solid, nullptr, *pActiveModel); //DraftingElementSchema::ToElement(eeh, *solid, nullptr, *pActiveModel); eeh.AddToModel(); } }
我怀疑您的截面(左下角)连接导线后,每个截面并没有跟该点的切线垂直,这样是不能成功loft的。我以前做过一个需求,就是若干个相同的截面,一条导线,因为需要知道导线上面每个点的切线信息,所以我当时用了ORD的一些接口,您可以参考下:
//Many profiles and curve StatusInt PSSubgradePlaceLoftSolidTool::SolidCreateBySections(CurveVectorPtr& profile, CurveVectorPtr& path) { IBcLinearElPtr element; StatusInt status = IBcLinearEl::CreateFromCurveVector(*path, true, element); DPoint3d start, end; DVec3d stVec, endVec; element->GetEnds(&start, &end, &stVec, &endVec); IBcLinearElPointArrayPtr linearPointsP; int method = BCLINEAREL_STROKINGMETHOD_EQUALDISTANCE; int nLen = element->GetLength2d(); linearPointsP = IBcLinearElPointArray::make(element.get(), 0.001); status = element->Stroke(linearPointsP.get(), method, nLen / 10, 0, true, 0.001); int numPoints = linearPointsP->GetSize(); if (status != SUCCESS) { return ERROR; } DPoint3d pt; Transform trans; bvector<CurveVectorPtr> profiles; for (size_t i = 0; i < linearPointsP->GetSize(); i++) { DVec3d xVec, yVec, zVec; RotMatrix rMatrix; BcLinearElPoint point = linearPointsP->GetPointByIndex(i); DPoint3d ptTest = point.GetPoint(); DPoint3d ptTagTest = point.GetTangent(); xVec = DVec3d::From(ptTagTest); pt = linearPointsP->GetPointRAt(i).GetPoint(); CurveVectorPtr curVec2 = profile->Clone(); zVec = DVec3d::From(linearPointsP->GetPointRAt(i).GetTangent()); zVec.Normalize(); ///////////////////////////////////////////////////////////////////////////////////////////////// DVec3d wVec; wVec = zVec; wVec.Scale(50); DSegment3d segment; DPoint3d vpt; vpt.Init(wVec); segment.InitFromOriginAndDirection(pt, vpt); ICurvePrimitivePtr lineString = ICurvePrimitive::CreateLine(segment); EditElementHandle eehSub3; DraftingElementSchema::ToElement(eehSub3, *lineString, nullptr, ACTIVEMODEL->Is3d(), *ACTIVEMODEL); eehSub3.AddToModel(); ///////////////////////////////////////////////////////////////////////////////////////////////// yVec.Init(0.0, 0.0, 1.0); xVec = DVec3d::FromCrossProduct(yVec, zVec); xVec.Normalize(); yVec = DVec3d::FromCrossProduct(zVec, xVec); xVec.Normalize(); yVec.Normalize(); zVec.Normalize(); rMatrix = RotMatrix::FromColumnVectors(xVec, yVec, zVec); Transform vecTransform = Transform::From(rMatrix, pt); curVec2->TransformInPlace(vecTransform); profiles.push_back(curVec2); EditElementHandle eehSub1; DraftingElementSchema::ToElement(eehSub1, *curVec2, nullptr, ACTIVEMODEL->Is3d(), *ACTIVEMODEL); eehSub1.AddToModel(); } ISolidKernelEntityPtr body; if (SUCCESS != SolidUtil::Create::BodyFromLoft(body, &profiles.front(), profiles.size(), &path, 1, *ACTIVEMODEL)) { return ERROR; } if (body == nullptr) return ERROR; EditElementHandle sweepEh; BentleyStatus nStatus = SolidUtil::Convert::BodyToElement(sweepEh, *body.get(), nullptr, *ACTIVEMODEL); if (BentleyStatus::SUCCESS == nStatus) { sweepEh.AddToModel(); } }
谢谢老师,但是 我并没有 使用ord,第二 根据 我的理解 是可以相切的, 因为这三个截面 中心点 在一条Z轴线上,另外 三个截面 互信平行!导向线 是 每一个 截面的 左下角顶点 相连 ,形成的两条导向线。
辛苦老师 帮忙在分析一下!!!!
Bentley 二次开发小白一枚
不传递guides可以生成:
void createLoftSolid(DPoint3dR basePt) { //数据准备阶段 int x1 = 150, x2 = 3650, x3 = 100, x4 = 2200, x5 = 100, x6 = 3650, x7 = 150; int y1 = 300, y2 = 2400, y3 = 300; int x1Len = x1 + x2 + x3 + x4 + x5 + x6 + x7; int y1Len = y1 + y2 + y3; //int nKouCaoy=100; //int nKouCaox=400; //int nKouCaoDx=350; int nHigthZ1 = 800; int nHigthZ2 = 900; //int nradius=50; //构建放样的导向线 DPoint3d Pts[3]; Pts[0].x = basePt.x - x4 / 2; Pts[0].y = basePt.y - y2 / 2; Pts[0].z = basePt.z; Pts[1].x = basePt.x - x4 / 2 - x3 - x2 - x1; Pts[1].y = basePt.y - y1Len / 2; Pts[1].z = basePt.z + nHigthZ1; Pts[2].x = basePt.x - x1Len / 2 + x1; Pts[2].y = basePt.y - y2 / 2; Pts[2].z = basePt.z + nHigthZ1 + nHigthZ2; /***********************************************************************************************************/ // 2 ---- 创建 CurveVectorPtr 数组 存储 CurveVector,并将两个圆 CurveVectorPtr profileVec[3]; //BOUNDARY_TYPE_Outer is important, it can create a closed profile that further makes a solid instead of a sheet profileVec[0] = CurveVector::Create(CurveVector::BOUNDARY_TYPE_Outer); profileVec[0]->Add(ICurvePrimitive::CreateRectangle(basePt.x - x4 / 2, basePt.y - y2 / 2, basePt.x + x4 / 2, basePt.y + y2 / 2, basePt.z));//最下面的矩形 也是最小的 profileVec[1] = CurveVector::Create(CurveVector::BOUNDARY_TYPE_Outer); profileVec[1]->Add(ICurvePrimitive::CreateRectangle(basePt.x - x1Len / 2, basePt.y - y1Len / 2, basePt.x + x1Len / 2, basePt.y + y1Len / 2, basePt.z + nHigthZ1));//中间的矩形,也是最大的矩形 profileVec[2] = CurveVector::Create(CurveVector::BOUNDARY_TYPE_Outer); profileVec[2]->Add(ICurvePrimitive::CreateRectangle(basePt.x - x1Len / 2 + x1, basePt.y - y2 / 2, basePt.x + x1Len / 2 - x1, basePt.y + y2 / 2, basePt.z + nHigthZ1 + nHigthZ2));//最上面的矩形, DSegment3d seg; seg.Init(Pts[0], Pts[1]); //CurveVectorPtr guideVec[2]; //guideVec[0] = CurveVector::Create(CurveVector::BOUNDARY_TYPE_Open); //guideVec[1] = CurveVector::Create(CurveVector::BOUNDARY_TYPE_Open); //guideVec[0]->Add(ICurvePrimitive::CreateLine(seg));//最下面和中间 两个矩形的连接线 也就是向导线 //seg.Init(Pts[1], Pts[2]); //guideVec[1]->Add(ICurvePrimitive::CreateLine(seg));//中间和最上面 两个矩形的连接线 也就是向导线 //改成一个向导线 也不行。如下 CurveVectorPtr guideVec; guideVec= CurveVector::Create(CurveVector::BOUNDARY_TYPE_Open); guideVec->Add(ICurvePrimitive::CreateLineString(Pts , 3)); // 3 ---- Create Solid by Loft ISolidKernelEntityPtr solid; DgnModelP pActiveModel = ISessionMgr::GetActiveDgnModelP(); //if (SUCCESS != SolidUtil::Create::BodyFromLoft(solid, profileVec, 3, &guideVec, 1, *pActiveModel, false, true)) if (SUCCESS != SolidUtil::Create::BodyFromLoft(solid, profileVec, 3, NULL, 0, *pActiveModel, false, true)) { mdlDialog_dmsgsPrint(L"Error in BodyFromLoft"); return; } // 4 ---- Convert Solid to EditElementHandle and add it to model if (solid.IsValid()) { EditElementHandle eeh; SolidUtil::Convert::BodyToElement(eeh, *solid, nullptr, *pActiveModel); //DraftingElementSchema::ToElement(eeh, *solid, nullptr, *pActiveModel); eeh.AddToModel(); } }
Answer Verified By: 平凡人生
郭老师:
您好,按照您说的 确实 ,已经可以了,但是针对 BodyFromLoft 还是有一些不明所以,肯请解释 说明。
1、导向线不也是和 截面 一样,是一个数组吗?什么情况下可以使用该数组?
2、我的情况是否满足使用导向线数组的情况,如果满足,应该怎么使用(比如我题中 三个截面,两个导向线)?
3、使用一根导向线的话,就向您帮我解决的这个问题(三个截面,使用一个导向线)是否有需要注意的地方或限制条件?
4、我的这个情况,不向BodyFromLoft 传入导向线 ,就可以成功 ,是什么原因?
辛苦老师,给予解答!!!!多谢!!!!
这种通过面、轮廓、路径构造体的方法是不能保证一定能生成的,因为通过输入这些参数去构造体的时候有可能会出现非法体(例如自交)的情况,具体是什么原因造成的,这得非常熟悉loft(还有一种跟loft比较类似的sweep)的底层算法才能分析出来。其实有些情况下我们是不用调用这些函数去构造我们的体的,例如如果想生成个正四面体的话,您可能会为了省事,构造四个正三角形,然后调用缝合的函数去构造这个四面体。这种情况,其实完全可以通过先生成一个立方体,然后去构造负实体,从这个立方体上切割出一个正四面体出来。所以我的建议是,编程的时候如果能不使用就不要使用这些sweep、loft、缝合等这些函数,通过构造负实体从大的体上切割出来自己想要的实体。