Я использую язык 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. Я не знаю.
К сожалению, я не нашел решения с использованием ActiveX (COM), главным образом потому, что в Hatch нет метода разнесения. Я предлагаю использовать PyRx — обертку Python над Object ARX.
В двух словах:
import traceback
from itertools import pairwise
from typing import Iterable, Tuple
import numpy as np
import shapely
from pyrx_imp import Db, Ge
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
Алгоритм требует доработки у штриховки внешнего края; начало и конец полилинии, входящей в состав шестиугольника, соединяются прямо, а не по внешнему контуру штриховки; Я предлагаю поиграть с shapely
— создайте HEX-штриховку, контур которой больше целевой штриховки, и вырежьте полилинии (get_plines()
выше) этой штриховки из многоугольника (shapely.Polygon
) целевой штриховки.
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
Мой код Python создает штриховки в разных областях. В одной области может быть более одного люка. Как создать каждую новую штриховку, чтобы ее острова были элементами предыдущих штриховок? Вот мой код - pastebin.com/n36JBs2W Если нужно - откроем чат для обсуждения. Я буду очень рад вашей помощи
Я отредактировал ответ, в hex_lines_points
была ошибка, я изменил понимание генератора на понимание списка.
неоткрытые библиотеки — проверьте это github.com/CEXT-Dan/PyRx/issues/3
Спасибо, проверьте мой комментарий выше, пожалуйста
Пожалуйста, покажите примеры данных и ожидаемый эффект, а также текущий код (весь).
Давайте продолжим обсуждение в чате.
Почему Pyrx и PyRxDebug отображаются в vscode как неоткрытые библиотеки? И когда я запускаю команду DOIT, я получаю ошибку — pastebin.com/263bwv6e .