箭头_Row 发表于 2024-6-30 02:21:17

格式刷的測試例子



寫了個顏色格式刷的例子,大佬們還有哪些地方需要改?

    private static string GetPointOptionsMessage() => "\n选择图元或 [字典(D)/随层(S)] ";

    private static readonly List<string> ignorePatterName = ["SOLID", "ANSI37", "ANSI31"];
    private static readonly List<string> ignoreBlockName = ["Elevation", "ANSI37", "ANSI31"];
    private static readonly Dictionary<List<int>, (string, short, short)> reflectDic = new(){
      { , (layers.DimLayer_Name,layers.DimLayer_Color,256) },
      { , (layers.DimLayer_Name,layers.DimLayer_Color,4) }
    };
   
    public static void BBest()
    {
      PromptSelectionOptions entOpts = new()
      {
            MessageForAdding = GetPointOptionsMessage()
      };

      PromptSelectionResult r1 = Env.Editor.GetSelection(entOpts);
      if (r1.Status == PromptStatus.OK)
      {
            using DBTrans tr = new();
            List<ObjectId> entWillBeSelected = [];

            var ids = r1.Value.GetObjectIds().ToList();
            for (int i = ids.Count - 1; i >= 0; i--)
            {
                var ent = (Entity)tr.GetObject(ids);


                if (ent is Dimension dim)
                {
                  if (dim.Layer == layers.DimLayer_Name && dim.ColorIndex == 256)
                        continue;

                  using (dim.ForWrite())
                        dim.SetProperty("0", layers.DimLayer_Name, layers.DimLayer_Color);
                  entWillBeSelected.Add(ent.ObjectId);
                }

                if (ent is Hatch hatch)
                {
                  if (!ignorePatterName.Contains(hatch.PatternName))
                        continue;

                  using (hatch.ForWrite())
                        hatch.SetProperty("0", layers.EL_250_Name, layers.EL_250_Color);
                  entWillBeSelected.Add(ent.ObjectId);
                }

                if (ent is BlockReference brf)
                {
#if Debug
                  Env.Printl($"块名:{brf.Name} ,图块:{brf.Layer}");
#endif
                  var btrId = brf.BlockTableRecord;
                  var btr = (BlockTableRecord)tr.GetObject(btrId);

                  if (btr.IsFromExternalReference)
                  {
                        Env.Printl($"块名:{brf.Name} ,来自外部块!");
                        continue;
                  }

                  foreach (var entId in btr)
                  {
                        //Env.Printl($"dxfname:{entId.ObjectClass.DxfName}");
                        var bent = (Entity)tr.GetObject(entId);
                        //using (bent.ForWrite())
                        //    bent.ColorIndex = 1;

                        if (bent is Line or Polyline or Circle)
                        {
                            if (NewMethod(tr, entWillBeSelected, bent))
                              entWillBeSelected.Add(ent.ObjectId);

                            entWillBeSelected.Remove(bent.ObjectId);
                        }

                  }

                  tr.Editor?.Regen(); // 更新图纸
                }

                if (ent is Line or Polyline or Circle)
                  NewMethod(tr, entWillBeSelected, ent);

            }

            tr.Editor?.SetImpliedSelection(entWillBeSelected.ToArray());

      }
    }

    private static bool NewMethod(DBTrans tr, List<ObjectId> entWillBeSelected, Entity ent, bool isChanged = false)
    {
      if (ent is Line or Polyline or Circle)
      {
            var color = tr.GetEntityColor(ent);

            foreach (var key in reflectDic.Keys)
                if (key.Contains(color))
                {
#if Debug
                  Env.Printl($"类型:{ent.GetType().Name} ,包含:{color}");
                  var value = reflectDic;
                  Env.Printl($"字典:{value.Item1}、{value.Item2}、{value.Item3}");
#endif
                  if (ent.Layer != value.Item1)
                  {
                        isChanged = true;
                        entWillBeSelected.Add(ent.ObjectId);
                        using (ent.ForWrite())
                        {
                            ent.SetProperty("0", value.Item1, value.Item2);
                            ent.ColorIndex = value.Item3;
                        };
                  }

                }
      }

      return isChanged;
    }


namespace ArrowTools;
public static class AttributeBrushToos
{
    /// <summary>
    /// 获取实体的真实颜色值
    /// </summary>
    ///   /// <remarks>
    /// 备注:<br/>
    /// 0x01 颜色Bylayer:返回图层颜色值<br/>
    /// 0x02 颜色不随层:返回entity的颜色值<br/>
    /// </remarks>
    /// <param name="tr"></param>
    /// <param name="ent"></param>
    /// <returns>颜色真实值</returns>
    public static int GetEntityColor<T>(this DBTrans tr, T ent) where T : Entity
    {
      int colorindex = ent.ColorIndex;
      if (colorindex == 256)
      {
            var layerId = tr.LayerTable;
            var layer = (LayerTableRecord)tr.GetObject(layerId);
            colorindex = layer.Color.ColorIndex;
      }

      return colorindex;
    }
}

和尚777 发表于 2024-7-1 18:00:34

本帖最后由 和尚777 于 2024-7-1 18:02 编辑

static HashSet<string> IgnorePatterName => ["SOLID", "ANSI37", "ANSI31"];
static (string, short, short) info => ("1", 1, 256);
static Dictionary<int, (string LayerName, short Color, short ColorIndex)> ReflectDic => new(){
      { 7, info },
      { 3, info },
      { 1, ("2",2,4) }
   };

你有种再说一遍 发表于 2024-6-30 03:13:36

本帖最后由 你有种再说一遍 于 2024-6-30 03:37 编辑

foreach (var key in reflectDic.Keys)
                if (key.Contains(color))
这个数据结构看起来就有问题,
遍历了keys,然后key是list又遍历了一次,所以时间复杂度是O(n*m),
完全没有利用好hash特性嘛.
不过由于数据量太少了,所以命中比求hash还快,hash还要跑个除法器...

看起来虽然奇怪的感觉,但是跑起来也不差.
就好像肛门虽然松了,但是痔疮又很好的弥补了这一点.
如果数据量大起来再讨论这个词典的意义吧.

箭头_Row 发表于 2024-6-30 13:43:35

hash值這個是我的盲區,得補下這部份內容了。寫的時候感覺遍歷了好多次怪怪的,這麼一說確實得改進下,判斷類型那里也改進下,判斷是不是curve就得了,不然還得arc 樣條曲線、橢圓、等挨個判斷太麻煩了。

    private static bool NewMethod(DBTrans tr, List<ObjectId> entWillBeSelected, Entity ent, bool isChanged = false)
    {
      if (ent is Curve)
      {
            var color = tr.GetEntityColor(ent);

            foreach (var key in reflectDic.Keys)
                if (key.Contains(color))
                {
#if Debug
                  Env.Printl($"类型:{ent.GetType().Name} ,包含:{color}");
                  var value = reflectDic;
                  Env.Printl($"字典:{value.Item1}、{value.Item2}、{value.Item3}");
#endif
                  if (ent.Layer != value.Item1)
                  {
                        isChanged = true;
                        entWillBeSelected.Add(ent.ObjectId);
                        using (ent.ForWrite())
                        {
                            ent.SetProperty("0", value.Item1, value.Item2);
                            ent.ColorIndex = value.Item3;
                        };
                  }

                }
      }

      return isChanged;
    }

你有种再说一遍 发表于 2024-6-30 16:53:33

本帖最后由 你有种再说一遍 于 2024-6-30 19:05 编辑

箭头_Row 发表于 2024-6-30 13:43
hash值這個是我的盲區,得補下這部份內容了。寫的時候感覺遍歷了好多次怪怪的,這麼一說確實得改進下,判斷 ...
去看jdk1.8的HashMap,然后再回来对比一下c#的.
微软实际上做得比较简单,想想求余数就是一个圈,这个圈就是数组大小,hashcode%array.length=位置.
这样就能映射到数组内部了,所以它是O(1)


【动画讲解-hashMap底层实现原理-哔哩哔哩】 https://b23.tv/OYilf4o


你用的时候记住了,最适合的情况是string,
只要看到string就上hash结构,
Hashset<string>,Dictionary<string>.
你不需要List<string>,虽然浪费了些许内存,但是速度快,还能明确它是唯一不重复的意思.

而且List的Contains也是遍历来得,不要以为写了一个方法就掩盖了for...如果是有序的,还得自己实现二分法搜索.当然了,为了O(1)直接hash,value多点就多点,空间换时间.


话外题:
再深入想想,你会发现字符串可以排序,也就是在节约内存和磁盘的情况下,可以利用前缀二分法的方式来实现,
例如ES数据库.
https://b23.tv/FMG1dwQ


和尚777 发表于 2024-7-1 09:23:54

有无效if请使用else if,想办法避免大括号,不建议使用ed.regen

moranyuyan 发表于 2024-7-1 09:42:38

你有种再说一遍 发表于 2024-6-30 03:13
这个数据结构看起来就有问题,
遍历了keys,然后key是list又遍历了一次,所以时间复杂度是O(n*m),
完全没 ...

大神优化下

你有种再说一遍 发表于 2024-7-1 14:00:44

moranyuyan 发表于 2024-7-1 09:42
大神优化下

这样说应该就懂了啊,只是箭头哥不懂hash结构,你也不懂吗

moranyuyan 发表于 2024-7-1 16:14:07

你有种再说一遍 发表于 2024-7-1 14:00
这样说应该就懂了啊,只是箭头哥不懂hash结构,你也不懂吗

不懂

你有种再说一遍 发表于 2024-7-1 16:17:56

moranyuyan 发表于 2024-7-1 16:14
不懂

那我好像不知道怎么告诉你好
页: [1]
查看完整版本: 格式刷的測試例子