明经CAD社区

 找回密码
 注册

QQ登录

只需一步,快速开始

搜索
12
返回列表 发新帖
楼主: wang2006zhi

[【IFoxCAD】] 查找相同的种子集-四叉树示例

[复制链接]
发表于 2024-8-21 10:29:42 | 显示全部楼层
dcl1214 发表于 2024-8-21 07:22
我们用go语言很多年了

go还不够,图形学不能绕过SIMD
 楼主| 发表于 2024-8-22 23:40:35 | 显示全部楼层
本帖最后由 wang2006zhi 于 2024-8-24 13:06 编辑
你有种再说一遍 发表于 2024-8-19 21:21
并行必然多线程...去搜搜吧
这个么
Parallel.ForEach(list,e =>{});
 楼主| 发表于 2024-8-28 12:24:47 | 显示全部楼层
采用线程查找计算相同样本集合,,与插块(费时较多)

[CommandMethod("W_TKPL")]
    public static void BlockSame()
    {
        using var tr = new DBTrans();

        if (!Env.Editor.GetSelRect(out Rect selRec))
            return;
        //过滤块实体
        var fil = OpFilter.Build(e => e.Dxf(0) != "INSERT");
        if (!Env.Editor.SelEnts(out List<Entity> ents, selRec.GetPointCollection(), fil))
            return;
        //选取种子集
        if (!Env.Editor.GetEnts(out List<Entity> entsTemp, msg: "请选择要基准集:", fil: fil))
            return;
        // 种子
        var ceSeed = new CadEntity(entsTemp[0].ObjectId, entsTemp[0].GetRect());
        // 样本集
        var oneGrop = new List<CadEntity>();
        foreach (var ent in entsTemp)
        {
            var cadEnt = new CadEntity(ent.ObjectId, ent.GetRect());
            cadEnt.IsUsed = true;
            oneGrop.Add(cadEnt);
        }
        
        //构造种子集
        var cesSeed = new List<CadEntity>();
        //构造四叉树
        var treeRoot = new QuadTree<CadEntity>(AppX.InfoRect);
        //获取四叉树数据及种子集
        for (int i = ents.Count - 1; i >= 0; i--)
        {
            var ent = ents;
            var cadEnt = new CadEntity(ent.ObjectId, ent.GetRect())
            {
                IsUsed = false,
            };
            if (cadEnt.IsSameEnt(ceSeed))
                cesSeed.Add(cadEnt);
            treeRoot.Insert(cadEnt);
        }
        
        //线程任务查找相同种子集合
        Task<List<List<CadEntity>>> runTask = Task.Run(() => cesSeed.FindGroup(ceSeed,treeRoot,oneGrop));
        var result = runTask.Result;
        InsertBlocks(result);
        Env.Editor.WriteMessage($"\n 已完成{result.Count}个块添加");
        
        void InsertBlocks(List<List<CadEntity>> list)
        {
            // 样本集块
            var btrId = entsTemp.MakeBlock("HesiBlk_" + DateTime.Now.ToString("yyyyMMdd_HHmmss"));
            var max = list.Count;
            //创建一个CAD进度条
            var pm = new ProgressMeter();
            //添加提示语言
            pm.Start($"正在插入{max}图块...");
            //设置总进度
            pm.SetLimit(max);
            for (int i = max - 1; i >= 0; i--)
            {
                pm.MeterProgress();
                var oneSameEs = list;
                if (oneSameEs == null || !oneSameEs.Any())
                    return;
                var pt = GetCesRect(oneSameEs).CenterPoint.Point3d();
                var bId = DBTrans.GetTop(btrId.Database).CurrentSpace.InsertBlock(pt, btrId);
                if (bId.GetObject<BlockReference>() is not { } brf)
                    return;
                brf.Layer = "0";
                brf.Draw();
                oneSameEs.ForEach(x => x.ObjectId.GetObject<Entity>()?.ForWrite(e => e.Erase(true)));
            }
            pm.Stop();
        }
    }
   
    /// <summary>
    /// 查找相同样本
    /// </summary>
    /// <param name="cesTemp">种子集</param>
    /// <param name="ceSeed">参考种子</param>
    /// <param name="treeRoot">四叉树数据</param>
    /// <param name="oneGrop">样本集</param>
    /// <returns></returns>
    static List<List<CadEntity>> FindGroup(this List<CadEntity> cesTemp,
        CadEntity ceSeed,
        QuadTree<CadEntity> treeRoot,
        List<CadEntity> oneGrop)
    {
       //样本集一起外包。。相比与每个实体两点构造两个外包搜索快
        var oRect = oneGrop.GetCesRect();
        // 样本集相同的集
        var oneSameGropTemp = new List<List<CadEntity>>(){oneGrop};
        //遍历所有种子集合,不可避免的多重循环,小循环写在最外层相比与内部节约时间
        for (int i = cesTemp.Count - 1; i >= 0; i--)
        {
            //临时种子与种子相对关系
            var vec = cesTemp.CenterPoint - ceSeed.CenterPoint;
            var nRect = new Rect(oRect.MinPoint + vec, oRect.MaxPoint + vec);
            // 用相对外包搜索实体
            var cesSearchTemp = treeRoot.Query(nRect.Expand(2), QuadTreeSelectMode.Contains);
            if (!cesSearchTemp.Any())
                continue;
            //临时样本集
            var oneGropTemp = new List<CadEntity>();
            //过滤掉与样本集不同的实体
            //遍历样本集
            for (int k = oneGrop.Count - 1; k >= 0; k--)
            {
                var ceK = oneGrop[k];
                //遍历搜索集中的可能实体
                for (int j = cesSearchTemp.Count - 1; j >= 0; j--)
                {
                    var ceJ = cesSearchTemp[j];
                    if (!ceJ.IsUsed && ceJ.IsSameEnt(ceK))
                    {
                        oneGropTemp.Add(ceJ);
                        ceJ.IsUsed = true;
                    }
                }
            }
            // 与种子集数目相同时看为一组
            if (oneGropTemp.Count != oneGrop.Count)
                continue;
            oneSameGropTemp.Add(oneGropTemp);
        }
        return oneSameGropTemp;
    }
   
    /// <summary>
    /// 获取集合的边界
    /// </summary>
    /// <param name="ces">四叉树数据集</param>
    /// <returns></returns>
    private static Rect GetCesRect(this List<CadEntity> ces)
    {
        var xMin = ces.Min(x => x.X);
        var yMin = ces.Min(x => x.Y);
        var tMax = ces.Max(x => x.Top);
        var rMax = ces.Max(x => x.Right);
        return new Rect(xMin, yMin, rMax, tMax);
    }
您需要登录后才可以回帖 登录 | 注册

本版积分规则

小黑屋|手机版|CAD论坛|CAD教程|CAD下载|联系我们|关于明经|明经通道 ( 粤ICP备05003914号 )  
©2000-2023 明经通道 版权所有 本站代码,在未取得本站及作者授权的情况下,不得用于商业用途

GMT+8, 2024-11-25 06:36 , Processed in 0.155212 second(s), 17 queries , Gzip On.

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表