cad.net 鏈式選擇和斷分標注


說明:

由於cad自身的圖元特性,標注作為一個復合型圖元卻沒有做到磁性選擇,

這樣很糟糕,而我們非自定義圖元的時候只能通過鏈式選擇和斷分標注模擬.

磁性選擇:當存在共同點的時候,可以直接吸附起來,跟磁鐵特性一樣,
不是組也不是塊參照,而是基於之間的狀態,
組可以被s命令點擊移動單個圖元...塊參照只能移動整體,塊ctrl+1特性頁不顯示標注內容.
所以才有磁鐵體,它應該顯示夾點和可以直接修改磁鐵體內的圖元,例如標注和標注,引線和文字,自動吸附起,
解開才需要命令,可惜cad並沒有這樣的東西,比較失望...
而和天正標注很不一樣的感覺是,天正標注沒有自動吸附的感覺,也就是當鼠標移動標注對齊的時候,鼠標出現捕捉點的時候是可以獲取交點圖元的,此時則可以直接利用反應器制造關聯.
啊,我才不要二次開發實現呢,一次開發做好才是最好的...不是桌子想不到,而是他們沒有動力重構了.

鏈式選擇:先選擇所有圖元,然后判斷點擊的圖元共同點碰撞到下一個圖元的公共點,則選擇起來.(這里甚至可以建設一個B+樹加快搜尋速度,我懶)

斷分標注:直接看動圖即可...

如果缺少函數,可利用搜索功能對博客進行搜索,如果真的缺了就留言吧.請登陸博客園看評論,我已經回答過全部的缺省.

源泉的作者告訴阿驚說,
標注避讓的思路是上下左右移動文字,然后有優先排序的方式,例如優先的是上下上下上下上下的排序.
但是阿驚現在已經沒空完成這個函數了...
若完成你就提供出來給大家吧.

動圖演示

mac-lee的鏈式選擇展示:點我

img

命令

//斷分標注
[CommandMethod("nn", CommandFlags.Modal | CommandFlags.UsePickSet | CommandFlags.Redraw)] //預選
public static void JJ_duanfenbiaozhu()
{
    Database db = HostApplicationServices.WorkingDatabase;//當前的數據庫
    Editor ed = Acap.DocumentManager.MdiActiveDocument.Editor;

    ed.WriteMessage(Environment.NewLine + "****驚驚連盒-斷分標注");
  
    //點選標注
    var res = ed.GetEntity(peo);
    if(res.Status != PromptStatus.OK)
    {
        return;
    }
    var baseId = res.ObjectId;
          
    var optionsA = new PromptPointOptions(Environment.NewLine + "選取[斷分/延長點]或[輸入等分段數,負數為改數值)]:<空格退出>")
    {
        AllowArbitraryInput = true, //任意輸入
    };
    try
    {
        DimInfo dimInfo = null;
        Entity ent = null;
        List<ObjectId> dimIdList = new();

        db.Action(tr => 
        {
            ent = baseId.ToEntity(tr);//ent = tr.GetObject(baseId, OpenMode.ForRead) as Entity;
            if(!(ent is RotatedDimension || ent is AlignedDimension)){return;}
            dimIdList = ed.ChainReactor(ent, tr);//鏈式選擇 
            if (dimIdList.IsNull())//判斷是空還是0數量
            {
                return;
            }
            tr.EntityRedraw(dimIdList, Bright.Highlight);//亮顯ent.Highlight();記得提權
            dimInfo = ent.GetDimInfo();//獲取標注信息
        });
        var pprA = ed.GetPoint(optionsA);
        if (pprA.Status == PromptStatus.Keyword)
        {
            //用戶輸入了數字,進行改變尺寸操作
            int.TryParse(pprA.StringResult, out int a);
            if (a < 0)
            {
                string str = (dimInfo.DimLength / -a).ToString("#0.00") + "*" + (-a).ToString() + "=<>";
                if (dimInfo.DimType == EntityType.AlignedDimension.ToString())//對齊標注
                {
                    if (ent is AlignedDimension dim)
                    {
                        dim.DimensionText = str;
                    }
                }
                else if (dimInfo.DimType == EntityType.RotatedDimension.ToString())//轉角標注
                {
                    if (ent is RotatedDimension dim)
                    {
                        dim.DimensionText = str;
                    }
                }
            }
            else
            {
                //根據等分份數生成標注
                double yifen = dimInfo.DimLength / a;
            }
        }
        else if (pprA.Status == PromptStatus.OK)
        {
            dimIdList = ed.DivideDim(ent, pprA.Value, dimIdList);
            //這里是留來寫標注避讓....
            //這里是留來寫標注避讓....
            //這里是留來寫標注避讓....
        }
        db.Action(tr =>
        {
            tr.EntityRedraw(dimIdList, Bright.Unhighlight);//取消亮顯ent.Unhighlight();記得提權
        });
    }
    catch (System.Exception e)
    {
        ed.WriteMessage("斷分標注錯誤::" + e.Message);
    }
}

循環分裂標注

/// <summary>
/// 循環分裂標注
/// </summary>
/// <param name="ent">選中的圖元</param>
/// <param name="getpoint">分裂點</param>
/// <param name="idArr">選擇集數組</param> 
/// <returns>最終鏈條上面的圖元</returns>
private static List<ObjectId> DivideDim(this Editor ed, Entity ent, Point3d? getpoint, IEnumerable<ObjectId> idArr)
{
    ed.GetWcsUcs(out _, out CoordinateSystem3d ucs);

    //獲取標注信息
    DimInfo entInfo = ent.GetDimInfo();

    //鏈條的角度
    double angle;

    var arr = new Point3d[] { entInfo.DimLinePoint, entInfo.DimLinePointN };
    if (arr.Point3dArrayCompositor().ToArray()[0] == entInfo.DimLinePoint)
    {
        angle = -(entInfo.DimLinePoint.GetAngle2XAxis(entInfo.DimLinePointN));
    }
    else
    {
        angle = -(entInfo.DimLinePointN.GetAngle2XAxis(entInfo.DimLinePoint));
    }

    ed.WriteMessage(Environment.NewLine + "繼續分裂/延長點");
    PromptPointOptions optionsA = new PromptPointOptions("")
    {
        AllowArbitraryInput = true, //任意輸入
    };

    //遍歷鏈式選擇集
    var dimIdList = idArr.ToList();

    bool getPointBool = true;
    while (getPointBool)
    {
        ent.Database.Action(tr =>{                
            //第二次才執行
            if (getpoint == null)
            {
                PromptPointResult ppr = ed.GetPoint(optionsA);
                if (ppr.Status != PromptStatus.OK)
                {
                    getPointBool = false;
                    return;
                }
                getpoint = ppr.Value;
            }

            //鏈條前后兩個點
            Point3d[] dimMinToMax = GetDimLinePoints(tr, dimIdList).Point3dArrayCompositor().ToArray();
            Point3d dimMinPoint = dimMinToMax[0];
            Point3d dimMaxPoint = dimMinToMax[dimMinToMax.Length - 1];

            //增點旋轉到x軸
            Point3d getpointRo = getpoint.Value.RotateBy(angle, ucs.Zaxis, dimMinPoint);
            Point3d dimMaxRo = dimMaxPoint.RotateBy(angle, ucs.Zaxis, dimMinPoint);

            //那ent到的頂點作為新圖元的延伸點
            Point3d entXLine1PointRo = entInfo.XLine1Point.RotateBy(angle, ucs.Zaxis, dimMinPoint);
            var shengchengList = new List<Point3d[]>();

            Entity entok = null;//更改點最近的圖元

            //判斷增點是否在范圍外,是就補充尺寸,否就分裂尺寸
            //pprARo只能夠判斷方向用
            //用ent的點作為生成點 
            if (getpointRo.X < dimMinPoint.X)  //增點在左外
            {
                var ddd = new Point3d[]
                {
                    new Point3d( dimMinPoint.X, entXLine1PointRo.Y, entXLine1PointRo.Z),//標注邊點2
                    dimMinPoint,//標注確認點
                };
                shengchengList.Add(ddd);
            }
            else if (getpointRo.X > dimMaxRo.X)  //增點在右外
            {
                Point3d[] ddd = new Point3d[]
                {
                    new Point3d(dimMaxRo.X, entXLine1PointRo.Y, entXLine1PointRo.Z), //標注邊點2
                    dimMaxRo,//標注確認點
                };
                shengchengList.Add(ddd);
            }
            else  //增點在中  getpointRo 在鏈表中間的那個位置 
            {
                //獲取鏈條上所有的確認點的位置,判斷分裂位置. 
                List<double> lenthList = new List<double>();
                foreach (Point3d item in dimMinToMax)
                {
                    Point3d pt = item.RotateBy(angle, ucs.Zaxis, dimMinPoint);
                    lenthList.Add(pt.X - getpointRo.X);
                }
                //這里就是一個一維坐標值,通過x判斷,負值到正值之間,大於0,然后前一個和它就是之間了
                var newDimTwo = new Point3d[2];
                for (int i = 0; i < lenthList.Count; i++)
                {
                    if (lenthList[i] > 0)
                    {
                        newDimTwo[0] = dimMinToMax[i - 1];
                        newDimTwo[1] = dimMinToMax[i];
                        break;
                    }
                }
                //獲取選擇集上面與其相同點的 
                foreach (ObjectId item in dimIdList)
                {
                    Entity entN = item.ToEntity(tr);
                    DimInfo dimInfoN = entN.GetDimInfo();
                    if (dimInfoN.DimLinePoint == newDimTwo[0] && dimInfoN.DimLinePointN == newDimTwo[1] ||
                        (dimInfoN.DimLinePoint == newDimTwo[1] && dimInfoN.DimLinePointN == newDimTwo[0])
                       )
                    {
                        entok = entN;
                        break;
                    }
                }
                if (entok != null)
                {
                    //獲取標注信息
                    DimInfo dimInfoOk = entok.GetDimInfo();
                    Point3d xLine1OkRo = dimInfoOk.XLine1Point.RotateBy(angle, ucs.Zaxis, dimMinPoint);
                    Point3d xLine2OkRo = dimInfoOk.XLine2Point.RotateBy(angle, ucs.Zaxis, dimMinPoint);

                    //添加到生成表
                    var ddd = new Point3d[]
                    {
                        new Point3d(xLine1OkRo.X,entXLine1PointRo.Y, dimMinPoint.Z),//標注邊點2 
                        new Point3d(xLine1OkRo.X,dimMinPoint.Y, dimMinPoint.Z)//標注確認點
                    };
                    shengchengList.Add(ddd);
                    ddd = new Point3d[]
                    {
                        new Point3d(xLine2OkRo.X,entXLine1PointRo.Y, dimMinPoint.Z),//標注邊點2
                        new Point3d(xLine2OkRo.X,dimMinPoint.Y, dimMinPoint.Z)//標注確認點
                    };
                    shengchengList.Add(ddd);
                }
            }

            //新建標注                     
            Point3d bdq1 = new Point3d(getpointRo.X, entXLine1PointRo.Y, entXLine1PointRo.Z);//標注邊點1
            bool fa = true;
            bool del = true;
            if (entok == null)//不是分裂的時候就為空
            {
                entok = ent;
                del = false;
            }
            foreach (var bdq in shengchengList)
            {
                //點1 == 點2 表示標注值為0,點在了標注的腳上面
                if (bdq1 == bdq[0])
                {
                    fa = false;
                    break;
                }
            }
            if (fa)
            {
                var idsnew = new List<ObjectId>();
                foreach (var bdq in shengchengList)
                {
                    ObjectId id = entok.AddCreateDimToMsPs(tr, entInfo, bdq1, bdq[0], bdq[1]);
                    if (id != null)
                    {
                        idsnew.Add(id);//新圖元用來旋轉 
                        dimIdList.Add(id); //新圖元加入鏈條 
                    }
                }
                //新增標注旋轉回去.
                tr.EntityRotate(idsnew.ToArray(), -angle, ucs.Zaxis, dimMinPoint);
                if (del)
                {
                    //刪除原本,在增設的時候不刪,在分裂的時候刪掉
                    tr.EntityErase(entok.ObjectId.ToIEnumerable());
                    dimIdList.Remove(entok.ObjectId);
                }
            }
        }); 

        ent.Database.Action(tr =>
                            {
                                tr.EntityRedraw(dimIdList.ToArray(), Bright.Highlight);//亮顯
                            }); 
        getpoint = null;//設置為空才重新點選 
    }
    return dimIdList;
}

標注信息

/// <summary>
/// 獲取標注的信息
/// </summary> 
public static DimInfo GetDimInfo(this Entity ent)
{
    DimInfo dimre = null;
    if (ent is AlignedDimension al)//對齊標注
    {
        dimre = new DimInfo(al);
    }
    else if (ent is RotatedDimension ro)//轉角標注
    {
        dimre = new DimInfo(ro);
    }
    return dimre;
}
/// <summary>
/// 新建標注所需信息
/// </summary>
public class DimInfo
{
    /// <summary>
    /// 求標注的未知點
    /// </summary>
    /// <param name="xLine1Point">點1</param>
    /// <param name="dimLinePoint">旋轉點</param>
    /// <param name="dimAngle">角度</param>
    /// <returns>未知點</returns>
    private static Point3d DimPointN(Point3d xLine1Point, Point3d dimLinePoint, double dimAngle)
    {
        //求出標注第一點下面那點
        Point3d dimLinePointN = new Point3d(xLine1Point.RotateBy(-dimAngle, Vector3d.ZAxis, dimLinePoint).X, dimLinePoint.Y, dimLinePoint.Z);
        dimLinePointN = dimLinePointN.RotateBy(dimAngle, Vector3d.ZAxis, dimLinePoint);
        return dimLinePointN;
    }

    /// <summary>
    /// 標注的類型
    /// </summary>
    public string DimType { get; set; }
    /// <summary>
    /// 標注的第一點
    /// </summary>
    public Point3d XLine1Point { get; set; }
    /// <summary>
    /// 標注的第二點
    /// </summary>
    public Point3d XLine2Point { get; set; }
    /// <summary>
    /// 標注的確定點與XLine2Point垂直的,甚至重合
    /// </summary>
    public Point3d DimLinePoint { get; set; }
    /// <summary>
    /// 標注的xLine1Point下面的點
    /// </summary>
    public Point3d DimLinePointN { get; set; }
    /// <summary>
    /// 標注的樣式 
    /// </summary>
    public ObjectId DimensionStyle { get; set; }
    /// <summary>
    /// 標注的測量距離
    /// </summary>
    public double DimLength { get; set; }
    /// <summary>
    /// 標注的線性比例 
    /// </summary>
    public double DimScale { get; set; }
    /// <summary>
    /// 標注的標注角度
    /// </summary>
    public double DimAngle { get; set; }
    /// <summary>
    /// 全局比例
    /// </summary>
    public double Dimscale { get; set; }

    public DimInfo(AlignedDimension dim)
    {
        DimType = dim.GetType().Name;
        XLine1Point = dim.XLine1Point;  //標注第一點
        XLine2Point = dim.XLine2Point;  //標注的第二點
        DimLinePoint = dim.DimLinePoint;//確認點,在第二點下 
        DimensionStyle = dim.DimensionStyle;//標注樣式
        DimLength = dim.Measurement;        //測量距離
        DimScale = dim.Dimlfac;             //線性比例 
        DimAngle = -(Pi2 - XLine1Point.GetAngle2XAxis(XLine2Point)); //標注角度
        DimLinePointN = DimPointN(XLine1Point, DimLinePoint, DimAngle); //求未知點 
        Dimscale = dim.Dimscale;//全局比例
    }
    public DimInfo(RotatedDimension dim)
    {
        DimType = dim.GetType().Name;
        XLine1Point = dim.XLine1Point;  //標注第一點
        XLine2Point = dim.XLine2Point;  //標注的第二點
        DimLinePoint = dim.DimLinePoint;//確認點,在第二點下 
        DimensionStyle = dim.DimensionStyle;//標注樣式
        DimLength = dim.Measurement;        //測量距離
        DimScale = dim.Dimlfac;             //線性比例 
        DimAngle = dim.Rotation;            //標注角度 
        DimLinePointN = DimPointN(XLine1Point, DimLinePoint, DimAngle);//求未知點
        Dimscale = dim.Dimscale; //全局比例
    }
}

零零散散的子函數

/// <summary>
/// 標注鏈式反應器
/// </summary>
/// <param name="ed"></param>
/// <param name="ent"></param>
/// <param name="tr"></param>
/// <returns></returns>
public static List<ObjectId> ChainReactor(this Editor ed, Entity ent, Transaction tr)
{
    //清空選擇集
    ed.SetImpliedSelection(new ObjectId[0]);

    //獲取標注的后面兩個點,然后通過這兩個點獲取選中標注樣式    
    var dimInfoA = ent.GetDimInfo();

    //標注點,如果含有則選取
    var dimpts = new List<Point3d>() { dimInfoA.DimLinePoint, dimInfoA.DimLinePointN };

    //鏈式選擇根據做個選擇集  
    var ssids = new List<ObjectId>();

    //利用ssget將標注兩點的圖元選中
    //創建選擇集過濾器,只選擇標注
    TypedValue[] filList = new TypedValue[]
    {
        new TypedValue((int)DxfCode.Start, "DIMENSION")
    };
    SelectionFilter filter = new SelectionFilter(filList);
    var ss = ed.SelectAll(filter);

    if (ss.Status != PromptStatus.OK)
    {
        return null;
    }

    var ss1ids = ss.Value.GetObjectIds().ToList();
    Tolerance oldtol = Tolerance.Global; //舊容差
    Tolerance.Global = new Tolerance(1e-6, 1e-6);//新容差 
    bool fa = true;
    while (fa)
    {
        fa = false;
        foreach (ObjectId id in ss1ids.ToArray())
        {
            Entity dimN = id.ToEntity(tr);
            DimInfo dimInfoN = dimN.GetDimInfo();
            if (dimInfoN != null)
            {
                if (dimpts.Contains(dimInfoN.DimLinePoint) || dimpts.Contains(dimInfoN.DimLinePointN))
                {
                    double an = Math.Abs(dimInfoA.DimAngle - dimInfoN.DimAngle);
                    if (an < 1e-10 || Math.Abs(an - Math.PI) < 1e-10) //目標向量與X的夾角 || 目標逆向量與X的夾角
                    {
                        dimpts.Add(dimInfoN.DimLinePoint);
                        dimpts.Add(dimInfoN.DimLinePointN);
                        ssids.Add(id);//加入選擇集
                        ss1ids.Remove(id);
                        fa = true;
                    }
                }
            }
        }
        //選擇集在遍歷的時候是有順序的,但是點選並不一定在末尾位置,可能在中間,
        //所以通過點表判斷前面的圖元時,因為點表中並不存在鄰點,所以出現鏈式選擇失敗.
        //一,通過向量判斷,但是不在鏈條的同向量標注也會被選擇上.
        //二,通過反向遍歷一次,但是會增加時間,之所以要循環是因為若1,2的2在第一次沒有加入,那么543這樣加入了,導致鏈式選擇少了..
        ss1ids.Reverse();
    }
    Tolerance.Global = oldtol;//恢復舊容差   
    return ssids;
}

/// <summary>
/// 獲取標注鏈條所有的標注兩個確認點
/// </summary>
public static IEnumerable<Point3d> GetDimLinePoints(Transaction tr, IEnumerable<ObjectId> idArr)
{
    var dimPointList = new List<Point3d>();
    foreach (var id in idArr)
    {
        Entity dimN = id.ToEntity(tr);
        DimInfo dimInfoN = dimN.GetDimInfo();
        dimPointList.Add(dimInfoN.DimLinePoint);
        dimPointList.Add(dimInfoN.DimLinePointN);
    }
    return dimPointList;
}

/// <summary>
/// 獲取坐標系統三維
/// </summary>
/// <param name="ed"></param>
/// <param name="wcs"></param>
/// <param name="ucs"></param>
public static void GetWcsUcs(this Editor ed, out CoordinateSystem3d wcs, out CoordinateSystem3d ucs)
{
    Matrix3d Ide_wcs = Matrix3d.Identity;//獲取世界坐標系
    wcs = Ide_wcs.CoordinateSystem3d;
    Matrix3d used_ucs = ed.CurrentUserCoordinateSystem;//當前用戶坐標系
    ucs = used_ucs.CoordinateSystem3d;
}

(完)


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM