Python Routinen mit PyRx als Ersatz für die .lsp Routinen verwendet.
This commit is contained in:
@@ -0,0 +1,194 @@
|
||||
# elemente/utils.py
|
||||
# Gemeinsame Hilfsfunktionen fuer alle ILS-Elemente (Kreisel, Eckrad, etc.)
|
||||
# ============================================
|
||||
|
||||
import os
|
||||
import math
|
||||
|
||||
import PyDb as Db
|
||||
import PyGe as Ge
|
||||
|
||||
# Globale Zaehler pro Komponententyp (pro Sitzung)
|
||||
_letzte_nummern = {}
|
||||
|
||||
|
||||
def get_block_path():
|
||||
"""Block-Pfad aus Umgebungsvariable DXFM_BLOCKS lesen."""
|
||||
bp = os.environ.get("DXFM_BLOCKS", "")
|
||||
if not bp:
|
||||
bp = "C:/Users/y.wang/Documents/dxfmakros/Blocks/"
|
||||
print(f"\nUmgebungsvariable DXFM_BLOCKS nicht gefunden. Nutze Standardpfad: {bp}")
|
||||
bp = bp.replace("\\", "/").rstrip("/") + "/"
|
||||
return bp
|
||||
|
||||
|
||||
def component_next_number(db, prefix):
|
||||
"""Naechste freie Nummer fuer einen Komponententyp ermitteln.
|
||||
|
||||
Scannt alle INSERT-Entities im Modelspace deren Blockname mit
|
||||
`prefix` beginnt (z.B. "ECKRAD_", "KREISEL_") und liest das
|
||||
NUMMER-Attribut aus. Gibt die naechste freie Nummer zurueck.
|
||||
|
||||
Entspricht component-next-number aus KreiselInsert.lsp.
|
||||
|
||||
Parameter:
|
||||
db - aktuelle Datenbank
|
||||
prefix - Blockname-Praefix, z.B. "ECKRAD_" oder "KREISEL_"
|
||||
Rueckgabe: naechste freie Nummer (int)
|
||||
"""
|
||||
global _letzte_nummern
|
||||
prefix_upper = prefix.upper()
|
||||
max_nr = 0
|
||||
|
||||
model = Db.BlockTableRecord(db.modelSpaceId(), Db.OpenMode.kForRead)
|
||||
for obj_id in model:
|
||||
ent = Db.Entity(obj_id, Db.OpenMode.kForRead)
|
||||
if not ent.isKindOf(Db.BlockReference.desc()):
|
||||
continue
|
||||
bref = Db.BlockReference(obj_id, Db.OpenMode.kForRead)
|
||||
btr = Db.BlockTableRecord(bref.blockTableRecord(), Db.OpenMode.kForRead)
|
||||
bname = btr.getName()
|
||||
if not bname.upper().startswith(prefix_upper):
|
||||
continue
|
||||
for att_id in bref.attributeIds():
|
||||
att = Db.AttributeReference(att_id, Db.OpenMode.kForRead)
|
||||
if att.tag().upper() == "NUMMER":
|
||||
try:
|
||||
val = int(att.textString())
|
||||
if val > max_nr:
|
||||
max_nr = val
|
||||
except ValueError:
|
||||
pass
|
||||
|
||||
if max_nr == 0:
|
||||
max_nr = _letzte_nummern.get(prefix_upper, 0)
|
||||
|
||||
_letzte_nummern[prefix_upper] = max_nr + 1
|
||||
return _letzte_nummern[prefix_upper]
|
||||
|
||||
|
||||
def merge_attribs(overrides, attrib_defs):
|
||||
"""Attribut-Defaults mit Ueberschreibungen zusammenfuehren.
|
||||
|
||||
Parameter:
|
||||
overrides - dict mit Ueberschreibungen (darf None sein)
|
||||
attrib_defs - Liste von (TAG, DEFAULT) Tupeln
|
||||
Rueckgabe: dict mit allen Tags
|
||||
"""
|
||||
result = {tag: default for tag, default in attrib_defs}
|
||||
if overrides:
|
||||
result.update(overrides)
|
||||
return result
|
||||
|
||||
|
||||
def read_block_attribs(bref):
|
||||
"""Alle Attribute einer BlockReference als dict lesen."""
|
||||
attribs = {}
|
||||
for att_id in bref.attributeIds():
|
||||
att = Db.AttributeReference(att_id, Db.OpenMode.kForRead)
|
||||
attribs[att.tag()] = att.textString()
|
||||
return attribs
|
||||
|
||||
|
||||
def ensure_layer(db, layer_name, color_index, set_active=False):
|
||||
"""Layer anlegen falls nicht vorhanden, optional aktiv setzen."""
|
||||
lt = Db.LayerTable(db.layerTableId(), Db.OpenMode.kForRead)
|
||||
if not lt.has(layer_name):
|
||||
lt.upgradeOpen()
|
||||
lr = Db.LayerTableRecord()
|
||||
lr.setName(layer_name)
|
||||
c = Db.Color()
|
||||
c.setColorIndex(int(color_index))
|
||||
lr.setColor(c)
|
||||
lt.add(lr)
|
||||
if set_active:
|
||||
layer_id = lt.getAt(layer_name)
|
||||
db.setClayer(layer_id)
|
||||
|
||||
|
||||
def ensure_textstyle(db, style_name="Kreisel_Arial", font="Arial"):
|
||||
"""Textstil anlegen falls nicht vorhanden."""
|
||||
tst = Db.TextStyleTable(db.textStyleTableId(), Db.OpenMode.kForRead)
|
||||
if not tst.has(style_name):
|
||||
tst.upgradeOpen()
|
||||
ts = Db.TextStyleTableRecord()
|
||||
ts.setName(style_name)
|
||||
ts.setFont(font, False, False, 0, 0)
|
||||
tst.add(ts)
|
||||
return style_name
|
||||
|
||||
|
||||
def ensure_block_from_dwg(db, dwg_name, block_path=None):
|
||||
"""Externen DWG-Block in die Datenbank laden falls nicht vorhanden."""
|
||||
if block_path is None:
|
||||
block_path = get_block_path()
|
||||
bt = Db.BlockTable(db.blockTableId(), Db.OpenMode.kForRead)
|
||||
base_name = os.path.splitext(dwg_name)[0]
|
||||
if not bt.has(base_name):
|
||||
dwg_path = block_path + dwg_name
|
||||
if not os.path.isfile(dwg_path):
|
||||
print(f"\nFehler: {dwg_name} nicht gefunden unter: {dwg_path}")
|
||||
return False
|
||||
aux_db = Db.Database(False, True)
|
||||
aux_db.readDwg(dwg_path)
|
||||
db.insert(aux_db, base_name)
|
||||
return True
|
||||
|
||||
|
||||
def create_attrib_defs(btr, attrib_defs, text_height=50.0):
|
||||
"""Unsichtbare Attribut-Definitionen in einer BlockTableRecord erzeugen.
|
||||
|
||||
Parameter:
|
||||
btr - Db.BlockTableRecord (kForWrite)
|
||||
attrib_defs - Liste von (TAG, DEFAULT) Tupeln
|
||||
text_height - Texthoehe der ATTDEFs
|
||||
"""
|
||||
y_pos = 0.0
|
||||
for tag, default in attrib_defs:
|
||||
attdef = Db.AttributeDefinition()
|
||||
attdef.setPosition(Ge.Point3d(0, y_pos, 0))
|
||||
attdef.setHeight(text_height)
|
||||
attdef.setTextString(default)
|
||||
attdef.setPrompt(tag)
|
||||
attdef.setTag(tag)
|
||||
attdef.setInvisible(True)
|
||||
btr.appendAcDbEntity(attdef)
|
||||
y_pos -= text_height * 2.0
|
||||
|
||||
|
||||
def insert_block_with_attribs(db, bname, insert_point, rotation_deg, attrib_values):
|
||||
"""Block einfuegen und Attribute aus dict setzen.
|
||||
|
||||
Parameter:
|
||||
db - aktuelle Datenbank
|
||||
bname - Name der Blockdefinition
|
||||
insert_point - Ge.Point3d
|
||||
rotation_deg - Drehwinkel in Grad
|
||||
attrib_values - dict {TAG: Wert}
|
||||
Rueckgabe: ObjectId der eingefuegten BlockReference
|
||||
"""
|
||||
bt = Db.BlockTable(db.blockTableId(), Db.OpenMode.kForRead)
|
||||
block_id = bt.getAt(bname)
|
||||
model = Db.BlockTableRecord(db.modelSpaceId(), Db.OpenMode.kForWrite)
|
||||
|
||||
bref = Db.BlockReference(insert_point, block_id)
|
||||
bref.setRotation(math.radians(rotation_deg))
|
||||
model.appendAcDbEntity(bref)
|
||||
|
||||
# Attribute aus Block-Definition erzeugen und Werte setzen
|
||||
btr = Db.BlockTableRecord(block_id, Db.OpenMode.kForRead)
|
||||
for ent_id in btr:
|
||||
ent = Db.Entity(ent_id, Db.OpenMode.kForRead)
|
||||
if ent.isKindOf(Db.AttributeDefinition.desc()):
|
||||
attdef = Db.AttributeDefinition(ent_id, Db.OpenMode.kForRead)
|
||||
attref = Db.AttributeReference()
|
||||
attref.setPropertiesFrom(attdef)
|
||||
attref.setTag(attdef.tag())
|
||||
attref.setInvisible(attdef.isInvisible())
|
||||
attref.setPosition(attdef.position())
|
||||
attref.setHeight(attdef.height())
|
||||
val = attrib_values.get(attdef.tag(), attdef.textString())
|
||||
attref.setTextString(val)
|
||||
bref.appendAttribute(attref)
|
||||
|
||||
return bref.objectId()
|
||||
Reference in New Issue
Block a user