diff --git a/lib/elemente/kreisel.py b/lib/elemente/kreisel.py index c3bb170..1e1d708 100644 --- a/lib/elemente/kreisel.py +++ b/lib/elemente/kreisel.py @@ -6,7 +6,6 @@ # KreiselLabelSetup, KreiselLabelPos, KreiselLabelHoehe # ============================================ -import os import math import PyRx as Rx @@ -15,6 +14,18 @@ import PyDb as Db import PyEd as Ed import wx +from elemente.utils import ( + get_block_path, + component_next_number, + merge_attribs, + read_block_attribs, + ensure_layer, + ensure_textstyle, + ensure_block_from_dwg, + create_attrib_defs, + insert_block_with_attribs, +) + # ============================================================ # Konstanten (aus KreiselInsert.lsp) # ============================================================ @@ -46,7 +57,6 @@ KREISEL_AUSRICHTUNGEN = [ ] # Globaler Zustand (pro Sitzung) -_kreisel_letzte_nr = 0 _kreisel_typ = "STANDARD" # Beschriftungs-Einstellungen @@ -59,68 +69,9 @@ _beschriftung_abstand_y = 0.0 # ============================================================ -# Hilfsfunktionen +# Kreisel-spezifische Hilfsfunktionen # ============================================================ -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 kreisel_next_number(db): - """Naechste freie Kreisel-Nummer ermitteln.""" - global _kreisel_letzte_nr - 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("KREISEL_"): - 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 = _kreisel_letzte_nr - - _kreisel_letzte_nr = max_nr + 1 - return _kreisel_letzte_nr - - -def merge_attribs(overrides, attrib_defs): - """Attribut-Defaults mit Ueberschreibungen zusammenfuehren.""" - 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 rotation_to_idx(rot): """Rotation (Grad) -> Index in KREISEL_AUSRICHTUNGEN.""" best_idx = 0 @@ -136,49 +87,6 @@ def idx_to_rotation(idx): return KREISEL_AUSRICHTUNGEN[idx][1] -def ensure_textstyle(db, style_name="Kreisel_Arial", font="Arial"): - """Textstil 'Kreisel_Arial' 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_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_block_from_dwg(db, dwg_name, block_path): - """Externen DWG-Block in die Datenbank laden falls nicht vorhanden.""" - 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 - - # ============================================================ # Kern-Funktion: draw_module (entspricht draw-module in LISP) # ============================================================ @@ -222,7 +130,7 @@ def draw_module(db, base_point, abstand, rotation_deg, attribs=None): except ValueError: kreisel_nummer = 0 if kreisel_nummer <= 0: - kreisel_nummer = kreisel_next_number(db) + kreisel_nummer = component_next_number(db, "KREISEL_") merged["NUMMER"] = str(kreisel_nummer) merged["NAME"] = f"Kreisel{kreisel_nummer}" @@ -326,49 +234,18 @@ def draw_module(db, base_point, abstand, rotation_deg, attribs=None): new_btr.appendAcDbEntity(txt) # Unsichtbare Attribut-Definitionen - y_pos = 0.0 - text_height = 50.0 - for tag, default in KREISEL_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) - new_btr.appendAcDbEntity(attdef) - y_pos -= text_height * 2.0 + create_attrib_defs(new_btr, KREISEL_ATTRIB_DEFS) print(f"\n-> Neue Blockdefinition: {bname}") else: print(f"\n-> Verwende bestehende Blockdefinition: {bname}") # Block am Zielpunkt einfuegen - block_id = bt.getAt(bname) - model = Db.BlockTableRecord(db.modelSpaceId(), Db.OpenMode.kForWrite) pt = Ge.Point3d(base_point.x, base_point.y, z_hoehe) - bref = Db.BlockReference(pt, block_id) - bref.setRotation(math.radians(rotation_deg)) - model.appendAcDbEntity(bref) - - # Attribute 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 = merged.get(attdef.tag(), attdef.textString()) - attref.setTextString(val) - bref.appendAttribute(attref) + obj_id = insert_block_with_attribs(db, bname, pt, rotation_deg, merged) print(f"\n-> Kreisel #{kreisel_nummer} eingefuegt: {bname} (Hoehe={z_hoehe:.0f})") - return bref.objectId() + return obj_id # ============================================================ @@ -378,7 +255,6 @@ def draw_module(db, base_point, abstand, rotation_deg, attribs=None): @Rx.command("KreiselInsert") def cmd_kreisel_insert(): """KreiselInsert: Manuell Position + Parameter.""" - global _kreisel_typ ed = Ed.Editor() db = Db.HostApplicationServices().workingDatabase() diff --git a/lib/utils.py b/lib/omniflo_utils.py similarity index 100% rename from lib/utils.py rename to lib/omniflo_utils.py diff --git a/lib/set_einfuegepkt.py b/lib/set_einfuegepkt.py index 6830692..64fb8ee 100644 --- a/lib/set_einfuegepkt.py +++ b/lib/set_einfuegepkt.py @@ -31,7 +31,7 @@ import sys import ezdxf -from utils import ( +from omniflo_utils import ( ROW_GROUPS, TEXT_HEIGHT, TEXT_MARGIN, CROSS_SIZE, ROW_LABEL_WIDTH, SWITCH_FILTERS, build_row_layout, import_element_as_block, draw_cross, diff --git a/lib/set_koords.py b/lib/set_koords.py index 43c6eef..2102386 100644 --- a/lib/set_koords.py +++ b/lib/set_koords.py @@ -53,7 +53,7 @@ import sys import ezdxf from ezdxf.math import Matrix44 -from utils import ( +from omniflo_utils import ( ROW_GROUPS, TEXT_HEIGHT, TEXT_MARGIN, CROSS_SIZE, ROW_LABEL_WIDTH, SWITCH_FILTERS, load_omniflo_data, build_row_layout, import_element_as_block,