Files
gjm 164968b62e chore
把非utf8-bom编码的cpp/h文件改为 utf8 bom 编码, msvc识别utf8编码时,如果不是bom格式的,会使用当前cp_oem来解码.
2026-10-04 00:04:20 +08:00

966 lines
24 KiB
C++

#include "StdAfx.h"
#include "GiDrawutility.h"
#include "EarThwormDef.h"
namespace
{
Acad::ErrorStatus AddToModelSpace(AcDbEntity *pEnt, AcDbDatabase *pDb, bool bClose, AcDbObjectId *pId)
{
if (!pEnt) return Acad::eInvalidInput;
if (pDb == NULL)
pDb = acdbHostApplicationServices()->workingDatabase();
Acad::ErrorStatus es;
AcDbBlockTable *pTbl = NULL;
if (Acad::eOk == (es = pDb->getBlockTable(pTbl, AcDb::kForRead)))
{
AcDbBlockTableRecord *pBTR = NULL;
if (Acad::eOk == (es = pTbl->getAt(ACDB_MODEL_SPACE, pBTR, AcDb::kForWrite)))
{
es = pBTR->appendAcDbEntity(pEnt);
if (es == Acad::eOk && pId) *pId = pEnt->objectId();
if (bClose)
pEnt->close();
pBTR->close();
}
pTbl->close();
}
return es;
}
AcDbObjectId AddToModelSpace(AcDbEntity *pEnt, bool bClose)
{
if (!pEnt) return AcDbObjectId::kNull;
AcDbDatabase *pDb = acdbHostApplicationServices()->workingDatabase();
Acad::ErrorStatus es;
AcDbObjectId id(AcDbObjectId::kNull);
AcDbBlockTable *pTbl = NULL;
if (Acad::eOk == (es = pDb->getBlockTable(pTbl, AcDb::kForRead)))
{
AcDbBlockTableRecord *pBTR = NULL;
if (Acad::eOk == (es = pTbl->getAt(ACDB_MODEL_SPACE, pBTR, AcDb::kForWrite)))
{
es = pBTR->appendAcDbEntity(id, pEnt);
if (bClose)
pEnt->close();
pBTR->close();
}
pTbl->close();
}
return id;
}
Acad::ErrorStatus CloneAndAddToModelSpace(const AcDbEntity *pEnt, int clr)
{
if (!pEnt) return Acad::eInvalidInput;
AcDbEntity *p((AcDbEntity *)pEnt->clone());
p->setColorIndex(clr);
return AddToModelSpace(p, NULL, true, NULL);
}
AcGePoint3d MidPt(AcGePoint3d ptGe1, AcGePoint3d ptGe2)
{
return AcGePoint3d((ptGe1.x + ptGe2.x) * 0.5
, (ptGe1.y + ptGe2.y) * .5
, (ptGe1.z + ptGe2.z) * .5);
}
Acad::ErrorStatus AddToModelSpace(AcDbEntity* pEnt, AcDbDatabase* pDb = NULL, bool bClose = true)
{
if (pDb == NULL)
pDb = acdbHostApplicationServices()->workingDatabase();
Acad::ErrorStatus es;
AcDbBlockTable* pTbl = NULL;
if (Acad::eOk == (es = pDb->getBlockTable(pTbl, AcDb::kForRead)))
{
AcDbBlockTableRecord* pBTR = NULL;
if (Acad::eOk == (es = pTbl->getAt(ACDB_MODEL_SPACE, pBTR, AcDb::kForWrite)))
{
es = pBTR->appendAcDbEntity(pEnt);
if (bClose) pEnt->close();
pBTR->close();
}
pTbl->close();
}
return es;
}
bool createRegion(const AcDbVoidPtrArray& curveSegments, AcDbVoidPtrArray& regions)
{
Acad::ErrorStatus es;
if ( (es = AcDbRegion::createFromCurves(curveSegments, regions) ) != Acad::eOk)
{
acutPrintf(_T("\ncreateFromCurves failed:%d."),es);
return false;
}
if (regions.isEmpty())
{
acutPrintf(_T("\n result is empty."));
return false;
}
return true;
}
AcDbRegion* createRegion(AcDbEntity *pEnt)
{
AcDbVoidPtrArray arr, segs;
arr.append(pEnt);
if (!createRegion(arr, segs))
{
return NULL;
}
return (AcDbRegion*)segs[0];
}
AcDb3dPolyline* create3DPolyline(const AcGePoint3d *pBuffer, int len)
{
AcDb3dPolyline *p = new AcDb3dPolyline;
if (!p) return NULL;
for (int i = 0; i < len; ++i)
{
AcDb3dPolylineVertex *pV = new AcDb3dPolylineVertex(pBuffer[i]);
p->appendVertex(pV);
}
p->makeClosed();
return p;
}
}
// 把region变换到以 vtNormal为法向,以ptOnPlan为中心的面上,并且, 将region上的点ptOnRegion与平面中心点ptOnPlan对齐
AECDLLIMPEXP void GiDrawUtility::transfromRegion(AcDbRegion *pRegion
, const AcGePoint3d &ptOnRegion
, const AcGeVector3d &vtNormal
, const AcGePoint3d &ptOnPlan)
{
AcGePlane plan;
plan.set(ptOnPlan, vtNormal);
AcGePoint3d pt0, pt1, pt2;
plan.get(pt0, pt1, pt2);
AcGeMatrix3d xform;
xform.setToPlaneToWorld(plan);
// 把region转到此面上
pRegion->transformBy(xform);
// 把 region 上的点也转到面上
AcGePoint3d pt(ptOnRegion);
pt.transformBy(xform);
// 再把region在面上平移
AcGeVector3d vtm = ptOnPlan - pt;
if (!vtm.isZeroLength())
{
xform.setToIdentity();
xform.setToTranslation(ptOnPlan - pt);
pRegion->transformBy(xform);
}
}
AECDLLIMPEXP AcGeMatrix3d GiDrawUtility::RotateAndMove(const AcGeVector3d &vtOrig
, const AcGePoint3d &ptOrig
, const AcGeVector3d &vtDist
, const AcGePoint3d &ptDist)
{
AcGeVector3d _vtOrig(vtOrig);
AcGeVector3d _vtDist(vtDist);
_vtOrig *= 1;// 保证长度不为0
_vtDist *= 1;// 保证长度不为0
AcGeMatrix3d mat(AcGeMatrix3d::kIdentity);
//mat = _vtDist.rotateTo(_vtOrig);
mat = _vtOrig.rotateTo(_vtDist);
mat.setTranslation(ptDist - ptOrig);
return mat;
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawLoft(const AcDbRegion *pTop
, const AcDbRegion *pBottom
, const AcDbCurve *pLine)
{
AcDbRegion *_pTop = (AcDbRegion*)pTop->clone();
AcDbRegion *_pBottom = (AcDbRegion*)pBottom->clone();
AcDbCurve *_pLine(NULL);
if (pLine)
_pLine = (AcDbCurve *)pLine->clone();
AcArray<AcDbEntity*> arGuides;
AcArray<AcDbEntity*> arSections;
arSections.append(_pTop);
arSections.append(_pBottom);
AcDbLoftOptions op;
AcDb3dSolid *pEnt = new AcDb3dSolid;
if (pEnt->createLoftedSolid(arSections, arGuides, _pLine, op) != Acad::eOk)
{
DELETE_PTR(pEnt);
DELETE_PTR(_pTop);
DELETE_PTR(_pBottom);
DELETE_PTR(_pLine);
return NULL;
}
DELETE_PTR(_pTop);
DELETE_PTR(_pBottom);
DELETE_PTR(_pLine);
return pEnt;
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawLoft(const AcDbCurve *pTop
, const AcDbCurve *pBottom
, const AcDbCurve *pLine)
{
if (!pTop || !pBottom || !pLine) return NULL;
AcDbCurve *_pTop = (AcDbCurve*)pTop->clone();
AcDbCurve *_pBottom = (AcDbCurve*)pBottom->clone();
AcDbCurve *_pLine = (AcDbCurve*)pLine->clone();
AcDbRegion *pRegT = createRegion(_pTop);
AcDbRegion *pRegB = createRegion(_pBottom);
if (!pRegT || !pRegB) return NULL;
AcDbEntity *p = DrawLoft(pRegT, pRegB, pLine);
DELETE_PTR(pRegT);
DELETE_PTR(pRegB);
DELETE_PTR(_pTop);
DELETE_PTR(_pBottom);
DELETE_PTR(_pLine);
return p;
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawRevolve(const AcDbLine& lnAxis
, const AcDbRegion *pReg)
{
AcDbRegion *_pReg = (AcDbRegion*)pReg->clone();
AcDbRevolveOptions op;
AcDb3dSolid *p = new AcDb3dSolid;
if (p->createRevolvedSolid(_pReg
, lnAxis.startPoint()
, lnAxis.endPoint() - lnAxis.startPoint()
, 2 * PI
, .0
, op) != Acad::eOk)
{
DELETE_PTR(p);
DELETE_PTR(_pReg);
return NULL;
}
DELETE_PTR(_pReg);
return p;
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawRevolve(const AcDbLine& lnAxis
, const AcDbCurve *pCurve)
{
if (!pCurve) return NULL;
AcDbCurve *_pC = (AcDbCurve*)pCurve->clone();
AcDbRegion *pReg = createRegion(_pC);
if (!pReg)
{
//DELETE_PTR(_pC);
_pC->setColorIndex(1);
AddToModelSpace(_pC);
return NULL;
}
AcDbEntity *p = DrawRevolve(lnAxis, pReg);
DELETE_PTR(pReg);
DELETE_PTR(_pC);
return p;
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawRevolve(const AcDbLine& lnAxis
, const AcGePoint3dArray& arSectionPtrs)
{
AcDb3dPolyline *pPL = create3DPolyline(arSectionPtrs.asArrayPtr()
, arSectionPtrs.length());
if (!pPL) return NULL;
return DrawRevolve(lnAxis, pPL);
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawCone(const AcGePoint3d &ptPos
, const AcGeVector3d &vtMove
, const double &Tr
, const double &Br
, const double &H
, const double &xOffset)
{
AcGePoint3d ptBottom(AcGePoint3d::kOrigin);
AcGePoint3d ptTop(ptBottom + xOffset * AcGeVector3d::kXAxis);
ptTop.z = H;
AcDbCircle cirB(ptBottom, AcGeVector3d::kZAxis, Br);
AcDbCircle cirT(ptTop, AcGeVector3d::kZAxis, Tr);
AcDbLine line(ptBottom, ptTop);
AcDbEntity *p = DrawLoft(&cirT, &cirB, &line);
if (!p) return NULL;
p->transformBy(RotateAndMove(AcGeVector3d::kZAxis
, ptBottom
, vtMove, ptPos ));
return p;
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawExclude(const AcGePoint3dArray& arSectionPtrs, const AcGeVector3d &vtPath)
{
AcDb3dPolyline *pPL = create3DPolyline(arSectionPtrs.asArrayPtr(), arSectionPtrs.length());
if (!pPL) return NULL;
return DrawExclude(pPL, vtPath);
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawMesh( const Adesk::UInt32 &rows
, const Adesk::UInt32 &columns
, const AcGePoint3d *pVertexList
, bool bHasSeal /* = true*/)
{
// 去掉头尾两个无效面
int first = 1, last = rows - 1;
if (!bHasSeal)
{
first = 0;
last = rows;
}
// 取第一个点和最后一个点连成一条线
AcDbLine line(pVertexList[0], pVertexList[rows * columns - 1]);
AcGePoint3d *pSection = new AcGePoint3d[columns];
AcArray<AcDbEntity*> vecPLs, vecGuides;
for (int i = first; i < last; ++i)
{
::memset(pSection, 0, sizeof(AcGePoint3d)*columns);
::memcpy(pSection, pVertexList + i * columns, sizeof(AcGePoint3d)*columns);
AcDb3dPolyline *p3dPL = create3DPolyline(pSection, columns);
vecPLs.append(p3dPL);
}
AcDbLoftOptions op;
op.setRuled(true);
op.setNormal(AcDbLoftOptions::kUseDraftAngles);
AcDb3dSolid *pEnt = new AcDb3dSolid;
if (pEnt->createLoftedSolid(vecPLs, vecGuides, &line, op) != Acad::eOk)
{
DELETE_PTR(pEnt);
return NULL;
}
delete [] pSection;
for (size_t i = 0; i < vecPLs.length(); ++i)
{
if (vecPLs[i]) DELETE_PTR(vecPLs[i]);
}
return pEnt;
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawExclude(const AcDbRegion *pReg
, const AcGePoint3d &ptInReg
, const AcGeVector3d &vtPath)
{
AcDbRegion *_pReg = (AcDbRegion*)pReg->clone();
AcDbLine line;
line.setStartPoint(ptInReg);
line.setEndPoint(ptInReg + vtPath);
AcDb3dSolid *p = new AcDb3dSolid;
if (p->extrudeAlongPath(_pReg, &line) != Acad::eOk)
{
DELETE_PTR(p);
DELETE_PTR(_pReg);
return NULL;
}
DELETE_PTR(_pReg);
return p;
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawExclude(const AcDbCurve *pCurve, const AcGeVector3d &vtPath)
{
AcDbCurve *_pCurve = (AcDbCurve*)pCurve->clone();
AcDbRegion *pReg = createRegion(_pCurve);
if (!pReg)
{
DELETE_PTR(_pCurve);
return NULL;
}
AcDbExtents ext;
pReg->getGeomExtents(ext);
AcGePoint3d pt1(ext.maxPoint()), pt2(ext.minPoint());
AcGePoint3d ptS((pt1.x + pt2.x) * .5, (pt1.y + pt2.y) * .5, (pt1.z + pt2.z) * .5);
AcDbEntity *p = DrawExclude(pReg, ptS, vtPath);
DELETE_PTR(pReg);
DELETE_PTR(_pCurve);
return p;
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawBox(const AcGePoint3d &ptPos
, const AcGeVector3d &vtMove
, const double &X
, const double &Y
, const double &Z)
{
AcDb3dSolid *pSolid = new AcDb3dSolid();
if (!pSolid) return NULL;
if (Acad::eOk != pSolid->createBox(X, Y, Z))
return NULL;
pSolid->transformBy(
RotateAndMove(AcGeVector3d::kZAxis
, AcGePoint3d::kOrigin
, vtMove, ptPos)
);
return pSolid;
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawSphere(const AcGePoint3d &ptCenter
, const double &dRadius)
{
AcDb3dSolid *pSolid = new AcDb3dSolid();
if (!pSolid) return NULL;
if (Acad::eOk != pSolid->createSphere(dRadius))
return NULL;
pSolid->transformBy(
RotateAndMove(AcGeVector3d::kZAxis
, AcGePoint3d::kOrigin
, AcGeVector3d::kZAxis, ptCenter)
);
return pSolid;
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawPyramid(const AcGePoint3d &ptPos
, const AcGeVector3d &vtMove
, const double &Tx
, const double &Ty
, const double &Bx
, const double &By
, const double &H
, const double &xOffset)
{
// 构建两个四边形region
AcGePoint3d ptBottom(AcGePoint3d::kOrigin);
AcGePoint3d ptTop(ptBottom + xOffset * AcGeVector3d::kXAxis);
ptTop.z = H;
double xt(Tx * .5), yt(Ty * .5), xb(Bx * .5), yb(By * .5);
AcGePoint2d ptGeTop[4] = {
AcGePoint2d(-xt, -yt)
,AcGePoint2d(-xt, yt)
,AcGePoint2d(xt, yt)
,AcGePoint2d(xt, -yt) };
AcGePoint2d ptGeBottom[4] = {
AcGePoint2d(-xb, -yb)
,AcGePoint2d(-xb, yb)
,AcGePoint2d(xb, yb)
,AcGePoint2d(xb, -yb) };
AcGeMatrix3d mat;
AcDbPolyline plTop;
plTop.addVertexAt(0, ptGeTop[0]);
plTop.addVertexAt(1, ptGeTop[1]);
plTop.addVertexAt(2, ptGeTop[2]);
plTop.addVertexAt(3, ptGeTop[3]);
plTop.setClosed(Adesk::kTrue);
mat.setToTranslation(ptTop - AcGePoint3d::kOrigin);
plTop.transformBy(mat);
AcDbPolyline plBottom;
plBottom.addVertexAt(0, ptGeBottom[0]);
plBottom.addVertexAt(1, ptGeBottom[1]);
plBottom.addVertexAt(2, ptGeBottom[2]);
plBottom.addVertexAt(3, ptGeBottom[3]);
plBottom.setClosed(Adesk::kTrue);
mat.setToTranslation(ptBottom - AcGePoint3d::kOrigin);
plBottom.transformBy(mat);
AcDbLine line(ptBottom, ptTop);
AcDbEntity *p = DrawLoft(&plTop, &plBottom, &line);
if (!p) return NULL;
p->transformBy(RotateAndMove(AcGeVector3d::kZAxis
, ptBottom
, vtMove, ptPos));
return p;
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawTydf(const AcGePoint3d &ptPos
, const AcGeVector3d &vtMove
, const double &Tr
, const double &Bx
, const double &By
, const double &H
, const double &xOffset
, BOOL bIsTfdy)
{
AcGePoint3d ptBottom(AcGePoint3d::kOrigin);
AcGePoint3d ptTop(ptBottom + xOffset * AcGeVector3d::kXAxis);
ptTop.z = H;
double xb(Bx * .5), yb(By * .5);
AcGePoint2d ptGeBottom[4] = {
AcGePoint2d(-xb, -yb)
,AcGePoint2d(-xb, yb)
,AcGePoint2d(xb, yb)
,AcGePoint2d(xb, -yb) };
AcGeMatrix3d mat;
AcDbCircle cir(ptTop, AcGeVector3d::kZAxis, Tr);
AcDbPolyline plBottom;
plBottom.addVertexAt(0, ptGeBottom[0]);
plBottom.addVertexAt(1, ptGeBottom[1]);
plBottom.addVertexAt(2, ptGeBottom[2]);
plBottom.addVertexAt(3, ptGeBottom[3]);
plBottom.setClosed(Adesk::kTrue);
mat.setToTranslation(ptBottom - AcGePoint3d::kOrigin);
plBottom.transformBy(mat);
AcDbLine line(ptBottom, ptTop);
AcDbEntity *p = NULL;
if (bIsTfdy)
{
AcGeVector3d vt(0,0,H);
AcGeMatrix3d xForm1;
xForm1.setToTranslation(vt);
plBottom.transformBy(xForm1);
ptBottom.transformBy(xForm1);
xForm1.invert();
cir.transformBy(xForm1);
ptTop.transformBy(xForm1);
p = DrawLoft(&plBottom, &cir, &line);
}
else
{
p = DrawLoft(&cir, &plBottom, &line);
}
if (!p) return NULL;
p->transformBy(RotateAndMove(AcGeVector3d::kZAxis
, ptBottom
, vtMove, ptPos));
return p;
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawCylinder(const AcGePoint3d &ptFr
, const AcGePoint3d &ptTo
, const double &dRadius)
{
return DrawPipe(ptFr, ptTo, dRadius, 0.);
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawCirTorus(const AcGePoint3d &ptCenter
, const AcGeVector3d &vtNormal
, const double &majorRadius /* 大半径 */
, const double &minorRadius /* 小半径,大半径减小半径是管子直径 */
, const double &startAngle
, const double &endAngle)
{
AcDbArc arc(ptCenter, vtNormal, (majorRadius + minorRadius) * .5, startAngle, endAngle);
AcDbCircle cir(AcGePoint3d::kOrigin, AcGeVector3d::kZAxis, (majorRadius - minorRadius) * .5);
return DrawPipe(&arc, &cir, AcGePoint3d::kOrigin);
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawRectTorus(const AcGePoint3d &ptCenter
, const AcGeVector3d &vtNormal
, const double &majorRadius /* 大半径 */
, const double &minorRadius /* 小半径 */
, const double &height /* 大半径减小半径是正方形的宽,这个参数是高 */
, const double &startAngle
, const double &endAngle)
{
AcDbArc arc(ptCenter, vtNormal, (majorRadius + minorRadius) * .5, startAngle, endAngle);
double dW = (majorRadius - minorRadius) * .5;
double xt(dW * .5), yt(height * .5);
AcGePoint2d ptGeTop[4] = {
AcGePoint2d(-xt, -yt)
,AcGePoint2d(-xt, yt)
,AcGePoint2d(xt, yt)
,AcGePoint2d(xt, -yt) };
AcDbPolyline plTop;
plTop.addVertexAt(0, ptGeTop[0]);
plTop.addVertexAt(1, ptGeTop[1]);
plTop.addVertexAt(2, ptGeTop[2]);
plTop.addVertexAt(3, ptGeTop[3]);
plTop.setClosed(Adesk::kTrue);
return DrawPipe(&arc, &plTop, AcGePoint3d::kOrigin);
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawDish(const double &dH /*小半径*/
, const double &dD /* 大直径 */
, const AcGePoint3d &axisPnt
, const AcGeVector3d &axisDir)
{
// 先构造一个(zox)面, 圆心为原点的1/4椭圆, 然后绕Z轴旋转
// 再转换到 axisPnt点,其中心轴(原Z轴)指向axisDir
AcDbEllipse elArc(AcGePoint3d::kOrigin
, -1 * AcGeVector3d::kYAxis
, AcGeVector3d::kXAxis * dD * .5
, 2 * dH / dD
, 0
, .5 * PI);
AcDbLine line1(AcGePoint3d::kOrigin, AcGePoint3d(dD * .5, 0, 0));
AcDbLine line2(AcGePoint3d::kOrigin, AcGePoint3d(0, 0, dH));
AcDbVoidPtrArray arCurves, arRegs;
arCurves.append(&line1);
arCurves.append(&line2);
arCurves.append(&elArc);
if (AcDbRegion::createFromCurves(arCurves, arRegs) != Acad::eOk)
return NULL;
if (arRegs.isEmpty()) return NULL;
AcDbEntity *p = DrawRevolve(
AcDbLine(AcGePoint3d::kOrigin , AcGePoint3d::kOrigin + AcGeVector3d::kZAxis * 1)
, (AcDbRegion*)arRegs[0]);
if (!p) return NULL;
AcGeMatrix3d mat = RotateAndMove(AcGeVector3d::kZAxis, AcGePoint3d::kOrigin, axisDir, axisPnt);
p->transformBy(mat);
AcDbEntity *pDel((AcDbEntity*)arRegs[0]);
DELETE_PTR(pDel);
return p;
}
AcDbEntity* GiDrawUtility::DrawPipe(const AcGePoint3d& ptFrom
, const AcGePoint3d& ptTo
, const double &dRadius
, const double &dThick
, const int &nSegs /*= 20*/)
{
AcDbCircle Cir1(AcGePoint3d::kOrigin, AcGeVector3d::kZAxis, dRadius);
if (!createRegion(&Cir1)) return NULL;
AcDbRegion *pBig = createRegion(&Cir1);
if (!pBig) return NULL;
AcDbRegion *pSml(NULL);
if (!EQUAL_ZERO(dThick))
{
AcDbCircle Cir2(AcGePoint3d::kOrigin, AcGeVector3d::kZAxis, dRadius - dThick);
pSml = createRegion(&Cir2);
if (!pSml) return NULL;
}
// 这里做一个布尔减
if (pBig && pSml)
{
if (pBig->booleanOper(AcDb::kBoolSubtract, pSml) != Acad::eOk)
{
acutPrintf(_T("\n DrawPipe booleanOper failed."));
DELETE_PTR(pBig);
DELETE_PTR(pSml);
return NULL;
}
}
AcDbRegion *pRegion(pBig);
AcDbLine path(ptTo, ptFrom);
AcDbEntity *pSolid = DrawPipe(&path, pRegion, AcGePoint3d::kOrigin);
DELETE_PTR(pRegion);
return pSolid;
}
AECDLLIMPEXP AcDbEntity* GiDrawUtility::DrawPipe(const AcDbCurve* pCurve
, const AcDbCurve* pPoly
, const AcGePoint3d& ptCenInRgn)
{
if (!pPoly || !pCurve) return NULL;
AcDbCurve *pClonePoly = (AcDbCurve*)pPoly->clone();
AcDbRegion *pRegion = createRegion(pClonePoly);
AcDbEntity *pSolid = DrawPipe(pCurve, pRegion, ptCenInRgn);
DELETE_PTR(pRegion);
DELETE_PTR(pClonePoly);
return pSolid;
}
// 分段长度大于max取max,小于max,取min
static int spliteCurve(const AcDbCurve *pCurve, const double &max, const double &min, AcDbVoidPtrArray &ar)
{
Acad::ErrorStatus es;
double dEnd = 0.0, dLen = 0.0, dSplitLen = 100000.0;
es = pCurve->getEndParam(dEnd);
if (es != Acad::eOk) return 0;
es = pCurve->getDistAtParam(dEnd, dLen);
if (es != Acad::eOk) return 0;
if (dLen > max)
dSplitLen = max;
else
dSplitLen = min;
double dMax(dSplitLen), dPrec(10e-4);
AcGePoint3d ptStart(AcGePoint3d::kOrigin), ptEnd(AcGePoint3d::kOrigin), pt(AcGePoint3d::kOrigin);
es = pCurve->getPointAtDist(.0, ptStart);
if (es != Acad::eOk) return 0;
es = pCurve->getEndPoint(ptEnd);
if (es != Acad::eOk) return 0;
int quotient((int)(dLen / dMax));
double remainder(fmod(dLen, dMax));
if (remainder < dPrec) quotient -= 1;
AcGePoint3dArray arPts;
if (dLen - dMax > dPrec)
{
for (int i = 0; i < quotient; ++i)
{
if (pCurve->getPointAtDist((i + 1) * dMax, pt) != Acad::eOk) continue;
arPts.append(pt);
}
}
if (arPts.isEmpty()) return 0;
es = pCurve->getSplitCurves(arPts, ar);
return ar.length();
}
static void deleteContainerOfArx(AcDbVoidPtrArray &ss)
{
while(!ss.isEmpty())
{
AcDbEntity *p = (AcDbEntity *)ss.last();
ss.removeLast();
delete p;
}
}
AcDbEntity* GiDrawUtility::DrawPipe(const AcDbCurve* pCurve
, const AcDbPolyline* pPoly
, const AcGePoint3d& ptCenInRgn)
{
return DrawPipe(pCurve, (AcDbCurve*)pPoly, ptCenInRgn);
}
AcDbEntity* GiDrawUtility::DrawPipe(const AcDbCurve *pCurve, double dR)
{
if (!pCurve) return NULL;
//开始切向量,向内
AcGePoint3d ptS;
AcGeVector3d vtS;
pCurve->getStartPoint(ptS);
if (Acad::eOk != pCurve->getFirstDeriv(ptS, vtS)) return NULL;
AcDbCircle cir;
cir.setNormal(vtS);
cir.setCenter(ptS);
cir.setRadius(dR);
AcDbVoidPtrArray arCurPts, arRegs;
arCurPts.append(&cir);
AcDbRegion::createFromCurves(arCurPts, arRegs);
if (arRegs.isEmpty()) return NULL;
AcDbRegion *pReg = (AcDbRegion *)arRegs.first();
if (!pReg) return NULL;
Acad::ErrorStatus es;
AcDb3dSolid *pSolid = new AcDb3dSolid();
//当时闭合Polyline线时,extrudeAlongPath结果三维和CAD命令Extrude比较变小;
//调整为createSweptSolid 和 CAD Extrude 命令结果一致
AcDbPolyline *pPl = AcDbPolyline::cast(pCurve);
if (pPl != NULL && pPl->isClosed())
{
AcDbSweepOptions sweepOp;
es = pSolid->createSweptSolid((AcDbEntity *)pReg, (AcDbEntity *)pCurve, sweepOp);
if (es != Acad::eOk)
{
acutPrintf(_T("\n拉伸错误:%d."), es);
DELETE_PTR(pSolid);
}
}
else
{
#ifndef ZWCAD
es = pSolid->extrudeAlongPath(pReg, pCurve);
DELETE_PTR(pReg);
if (es != Acad::eOk)
{
DELETE_PTR(pSolid);
// 处理 CAD 3D 实体体量不能大于 12000问题
// 拉伸 扫掠 实体,路径长不能大于 120000 ,圆,弧 除外
AcDbVoidPtrArray arCuvs;
spliteCurve(pCurve, 100000., 10000., arCuvs);
AcGePoint3d ptStart(AcGePoint3d::kOrigin);
AcDbVoidPtrArray arSolids;
for (int i = 0; i < arCuvs.length(); ++i)
{
AcDbCurve *p((AcDbCurve *)arCuvs[i]);
if (!p) continue;
AcDbEntity *pSo(DrawPipe(p, dR));
if (pSo)
arSolids.append(pSo);
}
deleteContainerOfArx(arCuvs);
if (!arSolids.isEmpty())
{
pSolid = (AcDb3dSolid *)((AcDbEntity *)arSolids.first())->clone();
for (int i(1); i < arSolids.length(); ++i)
es = pSolid->booleanOper(AcDb::kBoolUnite, (AcDb3dSolid *)arSolids[i]);
deleteContainerOfArx(arSolids);
}
else
acutPrintf(_T("\n拉伸错误."));
}
#else
AcDbSweepOptions sweepOp;
es = pSolid->createSweptSolid((AcDbEntity *)pReg, (AcDbEntity *)pCurve, sweepOp);
DELETE_PTR(pReg);
if (es != Acad::eOk)
{
DELETE_PTR(pSolid);
acutPrintf(_T("\n扫掠错误:%d."), es);
}
#endif
}
return pSolid;
}
AcDbEntity *GiDrawUtility::DrawPipe(
const AcDbCurve *pCurve
, const AcDbRegion *pRegion
, const AcGePoint3d &ptCenInRgn)
{
if (!pRegion || !pCurve) return NULL;
AcGePoint3d ptStart(AcGePoint3d::kOrigin);
if (pCurve->getStartPoint(ptStart) != Acad::eOk) return NULL;
AcGePoint3d ptEnd;
if (pCurve->getEndPoint(ptEnd) != Acad::eOk) return NULL;
AcGeVector3d vtNormal(AcGeVector3d::kIdentity);
if (pCurve->getFirstDeriv(ptStart, vtNormal) != Acad::eOk) return NULL;
AcDbRegion *pCloneRegion = (AcDbRegion*)pRegion->clone();
transfromRegion(pCloneRegion, ptCenInRgn, vtNormal, ptStart);
Acad::ErrorStatus es;
AcDb3dSolid *pSolid = new AcDb3dSolid();
//当时闭合Polyline线时,extrudeAlongPath结果三维和CAD命令Extrude比较变小;
//调整为createSweptSolid 和 CAD Extrude 命令结果一致
AcDbPolyline* pPl = AcDbPolyline::cast(pCurve);
if (pPl != NULL && pPl->isClosed() )
{
AcDbSweepOptions sweepOp;
es = pSolid->createSweptSolid((AcDbEntity*)pCloneRegion,(AcDbEntity*)pCurve,sweepOp);
DELETE_PTR(pCloneRegion);
if (es != Acad::eOk)
{
DELETE_PTR(pSolid);
acutPrintf(_T("\n拉伸错误:%d."), es);
}
}
else
{
#ifndef ZWCAD
es = pSolid->extrudeAlongPath(pCloneRegion, pCurve);
DELETE_PTR(pCloneRegion);
if (es != Acad::eOk)
{
DELETE_PTR(pSolid);
// 处理 CAD 3D 实体体量不能大于 12000问题
// 拉伸 扫掠 实体,路径长不能大于 120000 ,圆,弧 除外
AcDbVoidPtrArray arCuvs;
spliteCurve(pCurve, 100000., 10000., arCuvs);
AcGePoint3d ptStart(AcGePoint3d::kOrigin);
AcDbVoidPtrArray arSolids;
for (int i = 0; i < arCuvs.length(); ++i)
{
AcDbCurve *p((AcDbCurve *)arCuvs[i]);
if (!p) continue;
AcDbEntity *pSo(DrawPipe(p, pRegion, ptCenInRgn));
if (pSo)
arSolids.append(pSo);
}
deleteContainerOfArx(arCuvs);
if (!arSolids.isEmpty())
{
pSolid = (AcDb3dSolid *)((AcDbEntity *)arSolids.first())->clone();
for (int i(1); i < arSolids.length(); ++i)
es = pSolid->booleanOper(AcDb::kBoolUnite, (AcDb3dSolid *)arSolids[i]);
deleteContainerOfArx(arSolids);
}
else
acutPrintf(_T("\n拉伸错误."));
}
#else
AcDbSweepOptions sweepOp;
es = pSolid->createSweptSolid((AcDbEntity *)pCloneRegion, (AcDbEntity *)pCurve, sweepOp);
DELETE_PTR(pCloneRegion);
if (es != Acad::eOk)
{
DELETE_PTR(pSolid);
acutPrintf(_T("\n扫掠错误:%d."), es);
}
#endif
}
return pSolid;
}