objectarx 按比例分割面积

测试结果:这个是按0.1,0.1,0.1,0.3,0.4的比例划分的。

插件描述:这个插件主要是选择一个多段线poly,设置poly的close属性为true,在poly任意一侧画一条长线line(line画的时候不能与poly相交),找到line的垂直向量p'yXl,这个pyXl是要往与poly能相交的方向。在找到这个line与poly相切的时候。然后取每次平移的步进值bujin,因为这个poly的总面积有大有小,所以我是取总面积totaArea/2000在开方,如果这个bujin<=1,则直接取1,这样对于面积很大的poly也不需要平移很多次。然后就是利用acedTraceBoundary函数来获取平移后的
切线与poly形成的封闭多段线pl,求这个pl的面积是否大与按比例分割后的面积。

需要注意的地方:在使用acedTraceBoundary的时候,必须确认poly和平移的切线都是close掉的,不然无法求出pl。如果没有acedTraceBoundary函数,可以这样:

//ads_point pt = { seedPoint.x,seedPoint.y,seedPoint.z };
    //acedCommandS(RTSTR, L"-boundary", RTPOINT, pt, RTSTR, L"", RTNONE);
    //acdbEntLast(pent);
    ////acedRedraw(pent, 3);
    //AcDbObjectId eId;

    //acdbGetObjectId(eId, pent);

    //AcDbPolyline * pEnt = NULL;

    //ErrorStatus es = acdbOpenObject(pEnt, eId, AcDb::OpenMode::kForWrite);

来获得封闭的多段线,然后在求面积。

下面给出详细代码:
求pyXl:

AcGeVector3d CAreaFenGe::GetDirection()
{
    //l2pt和l1pt是在poly侧边画的线的端点
    AcGeVector3d lineDirc = l2Pt - l1Pt;
    AcGeVector3d lineDirc2 = l2Pt - l1Pt;

    AcGePoint3d centerPt((l2Pt.x + l1Pt.x) / 2, (l2Pt.y + l1Pt.y) / 2, 0);
    AcGePoint3d ptCloset;

    poly->getClosestPointTo(centerPt, ptCloset, false);

    AcDbLine *line1 = AcDbLine::cast(line->clone());
    AcDbLine *line2 = AcDbLine::cast(line->clone());
    double len = ptCloset.distanceTo(centerPt);

    AcGeVector3d pyXl1 = lineDirc.rotateBy(-1 * CMathUtil::PI() / 2, AcGeVector3d::kZAxis);
    AcGeVector3d pyXl2 = lineDirc2.rotateBy(CMathUtil::PI() / 2, AcGeVector3d::kZAxis);

    line1->transformBy(AcGeMatrix3d::translation(pyXl1.normal()*len*1.5));
    line2->transformBy(AcGeMatrix3d::translation(pyXl2.normal()*len*1.5));
    AcGePoint3dArray p3dArr1, p3dArr2;

    poly->intersectWith(line1, AcDb::Intersect::kExtendArg, p3dArr1, 0, 0);
    poly->intersectWith(line2, AcDb::Intersect::kExtendArg, p3dArr2, 0, 0);

    if (p3dArr1.length() > 0) {        
        pyXl = pyXl1;    
    }
    else if(p3dArr2.length()>0){        
        pyXl = pyXl2;
    }
    else {
        pyXl = AcGeVector3d(3, -1, 0);//这个可以注释掉
    }
    delete line1;
    line1 = NULL;
    delete line2;
    line2 = NULL;

    return pyXl;
}
View Code

获得切线:

//得到切线
AcGePoint3d CAreaFenGe::GetQieDian(AcDbLine * &line1)
{

    line1 = new AcDbLine(l1Pt, l2Pt);

    AcGePoint3dArray ptArr;

    while (ptArr.length() < 1) {

        poly->intersectWith(line1, AcDb::Intersect::kOnBothOperands, ptArr, 0, 0);

        line1->transformBy(AcGeMatrix3d::translation(pyXl.normal() * 1));

    }
    poly->close();

    if (ptArr.length() > 0)
        return ptArr[0];
    else
        return AcGePoint3d::kOrigin;

}
View Code

得到面积:

bool  CAreaFenGe::GetPyPolyline(AcGePoint3d seedPoint, double & a)
{

    AcDbVoidPtrArray ptrArr;
    ErrorStatus es = acedTraceBoundary(seedPoint, false, ptrArr);

    if (es != Acad::eOk) {
        acutPrintf(L"\nboundary=%d", es);
        return false;
    }

    AcDbPolyline * pl = NULL;
    pl = (AcDbPolyline*)ptrArr[0];

    pl->setColorIndex(1);

    pl->getArea(a);

    pl->erase();
    pl->close();
    pl = NULL;
    return true;

}

主要步骤:

void CAreaFenGe::Command()
{

    ErrorStatus es;
    AcDbLine * lQieXian = NULL;
    AcGePoint3d ptQieDian = GetQieDian(lQieXian);

    acutPrintf(L"\nptQieDian=[%.2f,%.2f,%.2f]", ptQieDian.x, ptQieDian.y, ptQieDian.z);

    ptQieDian=ptQieDian.transformBy(AcGeMatrix3d::translation(pyXl.normal() * 5));
    acutPrintf(L"\nptQieDian2=[%.2f,%.2f,%.2f]", ptQieDian.x, ptQieDian.y, ptQieDian.z);

    if (ptQieDian.x == 0 && ptQieDian.y == 0) {
        return;
    }
    double bujin = sqrt(totalArea * 1 / 2000);

    if (bujin <= 1) {
        bujin = 1;
    }

    AcDbObjectId qxId;
    lQieXian->transformBy(AcGeMatrix3d::translation(pyXl.normal() * bujin*3));


    es = acdbOpenObject(poly, plId, AcDb::kForRead);

    AcGePoint3dArray ptJdArr;

    poly->intersectWith(lQieXian, AcDb::Intersect::kOnBothOperands, ptJdArr, 0, 0);


    if (ptJdArr.length() >= 2) {

        ptQieDian=AcGePoint3d((ptJdArr[0].x+ ptJdArr[1].x)/2, (ptJdArr[0].y + ptJdArr[1].y) / 2,0);

        ptQieDian= ptQieDian.transformBy(AcGeMatrix3d::translation(pyXl.normal() * -bujin*1.5));

    }
    poly->close();


    qxId = CDwgDataBaseUtil::PostToModelSpace(lQieXian);

    lQieXian->close();

    lQieXian = NULL;

    //AcDbPolyline * ptPy = new AcDbPolyline();

    //ptPy->setColorIndex(5);

    //AcDbObjectId ptId;

    AcGePoint3dArray ptJdArr2;


    for (int i = 0; i < (int)vecArea.size(); i++)
    {


        AcGePoint3d ptCopyQd = ptQieDian;

        double a = 0.0;
        
        while (a < vecArea[i]) {

            bool flag = GetPyPolyline(ptQieDian, a);

            if (!flag) {
                return;
            }
            es = acdbOpenObject(lQieXian, qxId, AcDb::kForWrite);
            lQieXian->transformBy(AcGeMatrix3d::translation(pyXl.normal() * bujin));

            ptJdArr2.removeAll();

            es = acdbOpenObject(poly, plId, AcDb::kForRead);
            poly->intersectWith(lQieXian, AcDb::Intersect::kExtendArg, ptJdArr2, 0, 0);

            poly->close();

            if (ptJdArr2.length() < 1) {

                lQieXian->close();
                break;
                
            }


            lQieXian->close();

        }

        acdbOpenObject(lQieXian, qxId, AcDb::kForWrite);

        es = acdbOpenObject(poly, plId, AcDb::kForRead);

         ptJdArr.removeAll();

        poly->intersectWith(lQieXian, AcDb::Intersect::kExtendArg, ptJdArr, 0, 0);

        AcGePoint3d preCenter;
        if (ptJdArr.length() >= 2) {

            AcDbLine* lFg = new AcDbLine(ptJdArr[0], ptJdArr[1]);

            preCenter = AcGePoint3d((ptJdArr[0].x + ptJdArr[1].x) / 2, (ptJdArr[0].y + ptJdArr[1].y) / 2, 0);
            lFg->setColorIndex(2);

            CDwgDataBaseUtil::PostToModelSpace(lFg);

            lFg->close();

        }
        else {

            poly->close();
            lQieXian->erase();
            lQieXian->close();
            lQieXian = NULL;
            //ptId = CDwgDataBaseUtil::PostToModelSpace(ptPy);
            return;

        }
    
        poly->close();

        AcDbPolyline *pCopyQx = (AcDbPolyline*)lQieXian->clone();

        pCopyQx->transformBy(AcGeMatrix3d::translation(pyXl.normal() *bujin));

        if (i != (int)vecArea.size() - 1) {


            es = acdbOpenObject(poly, plId, AcDb::kForRead);

            ptJdArr.removeAll();

            poly->intersectWith(pCopyQx, AcDb::Intersect::kExtendArg, ptJdArr, 0, 0);

            if (ptJdArr.length() >= 2) {
                ptQieDian = AcGePoint3d((ptJdArr[0].x + ptJdArr[1].x) / 2, (ptJdArr[0].y + ptJdArr[1].y) / 2, 0);

                ptQieDian = AcGePoint3d((preCenter.x + ptQieDian.x) / 2, (preCenter.y + ptQieDian.y) / 2, 0);

            }
            qxId = CDwgDataBaseUtil::PostToModelSpace(pCopyQx);

            pCopyQx->close();
            poly->close();
            pCopyQx = NULL;
        }
        lQieXian->erase();
        lQieXian->close();
        lQieXian = NULL;

        //当运行到最后一个面积时,就不复制了
        if (i == (int)vecArea.size() - 1) {

            delete pCopyQx;
            pCopyQx = NULL;

            break;
        }
    }

    /*if (ptId.isNull()) {
        ptId = CDwgDataBaseUtil::PostToModelSpace(ptPy);
        ptPy->close();
    }*/
}

构造函数:

CAreaFenGe::CAreaFenGe(ACHAR *fenGeStr, AcDbPolyline *&p, AcDbLine *&l)
{
    
    vector<CString> vec;

    CStringUtil::Split(W2T(fenGeStr), L",", vec, false);

    for (int i = 0; i < (int)vec.size(); i++)
    {
        vecFenGe.push_back(_wtof(vec.at(i)));
    }
    this->poly = p;
    this->line = l;

    l1Pt = l->startPoint();
    l2Pt = l->endPoint();

    if (poly->isClosed() == false) {
        poly->setClosed(true);
    }

    poly->getArea(totalArea);

    for (int i = 0; i < (int)vecFenGe.size(); i++)
    {
        vecArea.push_back(totalArea*vecFenGe.at(i));
        acutPrintf(L"%.2f", vecArea[i]);
    }
    GetDirection();
    plId = poly->objectId();
}
View Code
可以通过使用 AutoCAD 的 ObjectARX API 来按指定边界裁剪 Polyline。具体步骤如下: 1. 获取 Polyline 对象。 2. 构建一个多边形对象,表示裁剪边界。 3. 调用 Polyline 对象的 IntersectWith() 方法,传入多边形对象作为参数,获取裁剪后的新 Polyline 对象。 以下是一个示例代码,可以实现该功能: ``` using Autodesk.AutoCAD.ApplicationServices; using Autodesk.AutoCAD.DatabaseServices; using Autodesk.AutoCAD.EditorInput; using Autodesk.AutoCAD.Geometry; namespace MyCommands { public class MyCommands { [CommandMethod("ClipPolyline")] public void ClipPolyline() { // 获取当前文档和数据库 Document acDoc = Application.DocumentManager.MdiActiveDocument; Database acCurDb = acDoc.Database; // 提示用户选择要裁剪的 Polyline PromptEntityOptions peo = new PromptEntityOptions("\n选择要裁剪的 Polyline:"); peo.SetRejectMessage("\n请选择 Polyline 对象。"); peo.AddAllowedClass(typeof(Polyline), true); PromptEntityResult per = acDoc.Editor.GetEntity(peo); if (per.Status != PromptStatus.OK) return; Polyline pline = (Polyline)acCurDb.GetObject(per.ObjectId, OpenMode.ForRead); // 提示用户指定裁剪边界 PromptPointResult ppr = acDoc.Editor.GetPoint("\n指定裁剪边界的第一个点:"); if (ppr.Status != PromptStatus.OK) return; Point3d pt1 = ppr.Value; ppr = acDoc.Editor.GetPoint("\n指定裁剪边界的第二个点:"); if (ppr.Status != PromptStatus.OK) return; Point3d pt2 = ppr.Value; ppr = acDoc.Editor.GetPoint("\n指定裁剪边界的第三个点:"); if (ppr.Status != PromptStatus.OK) return; Point3d pt3 = ppr.Value; Polyline2d boundary = new Polyline2d(new Point2d[] { new Point2d(pt1.X, pt1.Y), new Point2d(pt2.X, pt2.Y), new Point2d(pt3.X, pt3.Y) }); // 裁剪 Polyline Polyline clippedPline = new Polyline(); clippedPline.AddVertices(pline.IntersectWith(boundary, Intersect.OnBothOperands, new Point3dCollection(), IntPtr.Zero, IntPtr.Zero)); clippedPline.Closed = pline.Closed; // 将裁剪后的 Polyline 替换原来的 Polyline using (Transaction acTrans = acCurDb.TransactionManager.StartTransaction()) { BlockTable acBlkTbl = acTrans.GetObject(acCurDb.BlockTableId, OpenMode.ForRead) as BlockTable; BlockTableRecord acBlkTblRec = acTrans.GetObject(acCurDb.CurrentSpaceId, OpenMode.ForWrite) as BlockTableRecord; clippedPline.LayerId = pline.LayerId; acBlkTblRec.UpgradeOpen(); acBlkTblRec.Remove(per.ObjectId); acBlkTblRec.Add(clippedPline); acTrans.Commit(); } acDoc.Editor.WriteMessage("\nPolyline 裁剪完成。"); } } } ``` 你可以将上述代码保存为 .cs 文件,然后在 AutoCAD 中使用 NETLOAD 命令加载该插件,然后输入 ClipPolyline 命令即可开始裁剪 Polyline。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值