如何在 AutoCAD 中添加剖面线以使它们相互重叠?

问题描述 投票:0回答:1

我正在使用 Python 语言和 win32com.client 库向绘图添加剖面线。

以下是实现阴影线创建的代码:

import win32com.client
import pythoncom

acad = win32com.client.Dispatch("AutoCAD.Application")
acadModel = acad.ActiveDocument.ModelSpace 

def APoint(x, y, z = 0):
    return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (x, y, z))

def ADouble(xyz):
    return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_R8, (xyz))

def variants(object):
    return win32com.client.VARIANT(pythoncom.VT_ARRAY | pythoncom.VT_DISPATCH, (object))

out_loop = [acadModel.AddPolyline(ADouble([0,0,0,1000,0,0,1000,1000,0,0,1000,0,0,0,0]))]

hatch = acadModel.AddHatch(0, "HEX", True)
hatch.PatternScale = 20
hatch.AppendOuterLoop(variants(out_loop))
hatch.Evaluate()

hatch = acadModel.AddHatch(0, "ANSI31", True)
hatch.PatternScale = 10
hatch.AppendOuterLoop(variants(out_loop))
hatch.Evaluate()

任务是找到一种解决阴影线相互重叠的方法,可以使用Python来实现。想要的结果如图片右侧所示。

我可以在 autocad 中使用“爆炸”命令手动执行此任务第一个剖面线,然后添加第二个剖面线。但我需要使用Python来实现这个。

我还建议了一种使用 WipeOut 和 SuperHatch 的方法,但我仍然没有弄清楚如何在代码中实现它。 (https://stackoverflow.com/a/77905739/23389658

可能需要修改autocad脚本,用lisp或者Autolisp。我不知道。

python lisp win32com autocad autocad-plugin
1个回答
0
投票

不幸的是我还没有找到使用ActiveX(COM)的解决方案,主要是因为Hatch没有爆炸方法。我建议使用 PyRx - Object ARX 上的 Python 包装器。

简而言之:

  • 创建一个六角形舱口,
  • 分解为单行,
  • 将线连接成六边形,
  • 通过剪切六边形来添加目标阴影线。
import traceback
from itertools import pairwise
from typing import Iterable, Tuple

import numpy as np
import shapely
from pyrx_imp import Db, Ge
from PyRxDebug import startListener
from shapely.ops import linemerge


def PyRxCmd_doit():
    try:
        
        # HEX hatch
        hex_hatch = Db.Hatch()
        hex_hatch.setDatabaseDefaults()
        hex_hatch.setPattern(Db.HatchPatternType.kPreDefined, "HEX")

        outer_edges = (
            ((0.0, 0.0), (100.0, 0.0)),
            ((100.0, 0.0), (100.0, 100.0)),
            ((100.0, 100.0), (0.0, 100.0)),
            ((0.0, 100.0), (0.0, 0.0)),
        )

        outer_segments = [
            Ge.LineSeg2d(Ge.Point2d(p1), Ge.Point2d(p2)) for p1, p2 in outer_edges
        ]

        hex_hatch.appendLoopEdges(
            Db.HatchLoopType.kExternal,
            outer_segments,
            [Db.HatchEdgeType.kLine for _ in outer_segments],
        )
        hex_hatch.evaluateHatch()

        # explode hatch and get single lines
        hex_lines_ents = hex_hatch.explode()
        hex_lines = [Db.Line.cast(ent) for ent in hex_lines_ents]

        # connect individual lines in a "polyline" so that you can 
        # create loops for cutting the target hatch; round the coordinates 
        # so that the lines connect properly
        hex_lines_points = (
            (
                np.round(i.startPoint().toTuple()[:2], 6),
                np.round(i.endPoint().toTuple()[:2], 6),
            )
            for i in hex_lines
        )

        plines = get_plines(hex_lines_points)  # get_plines below

        # Target hatch
        hatch = Db.Hatch()
        hatch.setPattern(Db.HatchPatternType.kPreDefined, "ANSI31")

        hatch.appendLoopEdges(
            Db.HatchLoopType.kExternal,
            outer_segments,
            [Db.HatchEdgeType.kLine for _ in outer_edges],
        )

        for pline in plines:  # hex plines
            
            # create a list of segments that make up the polylines of one hexagon
            line_segments = [
                Ge.LineSeg2d(Ge.Point2d(p1), Ge.Point2d(p2))
                for p1, p2 in pairwise(pline)
            ]
            hatch.appendLoopEdges(
                Db.HatchLoopType.kDefault,
                line_segments,
                [Db.HatchEdgeType.kLine for _ in line_segments],
            )

        hatch.evaluateHatch()

        db = Db.HostApplicationServices().workingDatabase()
        model = Db.BlockTableRecord(db.modelSpaceId(), Db.OpenMode.kForWrite)
        model.appendAcDbEntity(hatch)  # add hatch to the model
        model.appendAcDbEntities(hex_lines)  # add hexagon lines if needed too
        model.close()
        
    except Exception:
        traceback.print_exc()


Point_T = Tuple[float, float]

def get_plines(
    line_points: Iterable[Tuple[Point_T, Point_T]]
) -> Iterable[Iterable[Point_T]]:
    line_strings = linemerge(line_points)
    if isinstance(line_strings, shapely.LineString):
        line_strings = (line_strings,)
    elif isinstance(line_strings, shapely.MultiLineString):
        pass
    else:
        raise TypeError
    for line_string in line_strings.geoms:
        ch = line_string.convex_hull
        if isinstance(ch, shapely.Polygon):
            yield ch.exterior.coords

需要解决的问题

算法需要在孵化时进行细化outer edge;作为六边形一部分的折线的起点和终点直接向前连接,而不是沿着外部剖面线轮廓线连接;我建议使用

shapely
- 创建一个轮廓大于目标剖面线的六角形剖面线,并从目标剖面线的多边形 (
get_plines()
) 中剪切该剖面线的折线(上面的
shapely.Polygon
)。


PyRx

  • 安装最新的版本
  • 启动 AutoCAD 并允许加载 PyRx.arx 插件,
  • 从命令行运行
    PYLOAD
    命令并选择包含代码的 python 模块,
  • 调用
    DOIT
    命令 (PyRxCmd_doit)。

PyRx 允许用户交互,对于用户指定外部填充轮廓,请使用

Ed
模块 (
from pyrx_imp import Ed
)

您还可以将 ActiveX(Autocad 对象模型)与 PyRx 一起使用,请查看:

from pyrx_impx import Ax

doc = Ax.getDbx()  # same as acad.ActiveDocument
© www.soinside.com 2019 - 2024. All rights reserved.