create_example prüft die Sinnhaftigkeit der position der frames
This commit is contained in:
@@ -10,7 +10,7 @@
|
|||||||
"count": 3,
|
"count": 3,
|
||||||
"layout_type": "horizontal",
|
"layout_type": "horizontal",
|
||||||
"base_x": 1500,
|
"base_x": 1500,
|
||||||
"base_y": 1000,
|
"base_y": 1300,
|
||||||
"spacing": 1450
|
"spacing": 1450
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
"name": "MA-2@@_bottom",
|
"name": "MA-2@@_bottom",
|
||||||
"count": 3,
|
"count": 3,
|
||||||
"layout_type": "horizontal_offset",
|
"layout_type": "horizontal_offset",
|
||||||
"base_x": 1500,
|
"base_x": 2000,
|
||||||
"base_y": 400,
|
"base_y": 400,
|
||||||
"spacing": 1450
|
"spacing": 1450
|
||||||
}
|
}
|
||||||
@@ -37,9 +37,9 @@
|
|||||||
"kennzeichnung": "A01+UH00",
|
"kennzeichnung": "A01+UH00",
|
||||||
"layer_name": "ILS_MOTOR",
|
"layer_name": "ILS_MOTOR",
|
||||||
"direction": "LEFT_RIGHT",
|
"direction": "LEFT_RIGHT",
|
||||||
"x": 700,
|
"x": 800,
|
||||||
"y": 800,
|
"y": 800,
|
||||||
"width": 3600,
|
"width": 4000,
|
||||||
"height": 450,
|
"height": 450,
|
||||||
"use_polyline": false
|
"use_polyline": false
|
||||||
},
|
},
|
||||||
@@ -50,7 +50,7 @@
|
|||||||
"layer_name": "ILS_MOTOR",
|
"layer_name": "ILS_MOTOR",
|
||||||
"direction": "LEFT_RIGHT",
|
"direction": "LEFT_RIGHT",
|
||||||
"x": 450,
|
"x": 450,
|
||||||
"y": 150,
|
"y": 100,
|
||||||
"width": 1400,
|
"width": 1400,
|
||||||
"height": 480,
|
"height": 480,
|
||||||
"use_polyline": true
|
"use_polyline": true
|
||||||
|
|||||||
+134
-159
@@ -29,6 +29,7 @@ class TestDataGenerator:
|
|||||||
self.doc = None
|
self.doc = None
|
||||||
self.msp = None
|
self.msp = None
|
||||||
self.config = None
|
self.config = None
|
||||||
|
self.generated_symbols = [] # Liste von (x, y, io_pattern, group_name) für Validierung
|
||||||
|
|
||||||
# Lade Config-Datei (muss immer angegeben werden)
|
# Lade Config-Datei (muss immer angegeben werden)
|
||||||
if config_file:
|
if config_file:
|
||||||
@@ -570,8 +571,7 @@ class TestDataGenerator:
|
|||||||
print(f"Verwende JSON-Config für {scene_name}...")
|
print(f"Verwende JSON-Config für {scene_name}...")
|
||||||
self._generate_nummerierung_from_config(scene_name)
|
self._generate_nummerierung_from_config(scene_name)
|
||||||
else:
|
else:
|
||||||
print("Verwende Hard-coded Defaults für Nummerierung...")
|
print("Fehler in Config ... terminating")
|
||||||
self._generate_nummerierung_hardcoded()
|
|
||||||
|
|
||||||
def _generate_ma_group(self, group, ma_defaults, width_per_char, fixed_height, spacing_factor, y_offsets_list):
|
def _generate_ma_group(self, group, ma_defaults, width_per_char, fixed_height, spacing_factor, y_offsets_list):
|
||||||
"""
|
"""
|
||||||
@@ -622,19 +622,12 @@ class TestDataGenerator:
|
|||||||
print(f"Unbekannter Layout-Typ: {layout_type}")
|
print(f"Unbekannter Layout-Typ: {layout_type}")
|
||||||
continue
|
continue
|
||||||
|
|
||||||
# Erstelle Block-Referenz
|
|
||||||
# Der Insert-Punkt soll an der oberen linken Ecke des TEXT-D liegen
|
|
||||||
# TEXT-D ist bei (772.87, 110.44) relativ zum Block, Höhe 63.75
|
|
||||||
# Die obere linke Ecke von TEXT-D ist bei (772.87, 110.44 + 63.75) = (772.87, 174.19) relativ zum Block
|
|
||||||
# Daher muss der Block um diese Werte verschoben werden
|
|
||||||
text_d_x_offset = 772.87
|
|
||||||
text_d_y_offset = 110.44 + 63.75 # Basis + Höhe = obere linke Ecke
|
|
||||||
block_insert_x = x - text_d_x_offset
|
|
||||||
block_insert_y = y - text_d_y_offset
|
|
||||||
|
|
||||||
blockref = self.msp.add_blockref(
|
blockref = self.msp.add_blockref(
|
||||||
'io',
|
'io',
|
||||||
insert=(block_insert_x, block_insert_y),
|
#insert=(block_insert_x, block_insert_y),
|
||||||
|
insert=(x, y),
|
||||||
dxfattribs={'layer': layer}
|
dxfattribs={'layer': layer}
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -645,6 +638,15 @@ class TestDataGenerator:
|
|||||||
|
|
||||||
blockref.add_auto_attribs(attrib_values)
|
blockref.add_auto_attribs(attrib_values)
|
||||||
|
|
||||||
|
# Speichere Symbol-Position für spätere Validierung
|
||||||
|
self.generated_symbols.append({
|
||||||
|
'x': x,
|
||||||
|
'y': y,
|
||||||
|
'io': io_pattern,
|
||||||
|
'group_name': name,
|
||||||
|
'layer': layer
|
||||||
|
})
|
||||||
|
|
||||||
def _generate_nummerierung_from_config(self, scene_name='Nummerierung1'):
|
def _generate_nummerierung_from_config(self, scene_name='Nummerierung1'):
|
||||||
"""
|
"""
|
||||||
Generiert Nummerierung-Testdaten aus JSON-Config
|
Generiert Nummerierung-Testdaten aus JSON-Config
|
||||||
@@ -696,166 +698,139 @@ class TestDataGenerator:
|
|||||||
use_polyline=frame_config.get('use_polyline', False)
|
use_polyline=frame_config.get('use_polyline', False)
|
||||||
)
|
)
|
||||||
|
|
||||||
def _generate_nummerierung_hardcoded(self):
|
# Prüfe ob alle generierten Symbole in einem Renamer-Frame liegen
|
||||||
"""Generiert Nummerierung-Testdaten mit Hard-coded Werten (Fallback)"""
|
self._validate_symbols_in_frames(scene)
|
||||||
|
|
||||||
# Berechne Symbol-Ausdehnung für korrekte Positionierung
|
def _point_in_rectangle(self, point, rect_x, rect_y, rect_width, rect_height):
|
||||||
ma1_width, ma1_height = self.calculate_symbol_extent('MA-1@@')
|
"""
|
||||||
ma2_width, ma2_height = self.calculate_symbol_extent('MA-2@@')
|
Prüft ob ein Punkt innerhalb eines Rechtecks liegt.
|
||||||
|
|
||||||
# Abstand zwischen Symbolen (20% der Breite als Puffer)
|
Args:
|
||||||
spacing = ma1_width * 1.2
|
point: (x, y) Tupel
|
||||||
|
rect_x, rect_y: Linke obere Ecke des Rechtecks
|
||||||
|
rect_width, rect_height: Breite und Höhe des Rechtecks
|
||||||
|
"""
|
||||||
|
x, y = point
|
||||||
|
return (rect_x <= x <= rect_x + rect_width and
|
||||||
|
rect_y <= y <= rect_y + rect_height)
|
||||||
|
|
||||||
# Definiere Positionen
|
def _point_in_polygon(self, point, polygon):
|
||||||
# Rechts oben: 3x MA-1@@ nebeneinander
|
"""
|
||||||
top_right_y = 1000
|
Prüft, ob ein Punkt innerhalb eines Polygons liegt (Ray-casting Algorithmus).
|
||||||
top_right_x_start = 1500
|
"""
|
||||||
|
x, y = point
|
||||||
|
n = len(polygon)
|
||||||
|
inside = False
|
||||||
|
|
||||||
# Der Insert-Punkt soll an der oberen linken Ecke des TEXT-D liegen
|
p1x, p1y = polygon[0]
|
||||||
text_d_x_offset = 772.87
|
for i in range(1, n + 1):
|
||||||
text_d_y_offset = 110.44 + 63.75 # Basis + Höhe = obere linke Ecke
|
p2x, p2y = polygon[i % n]
|
||||||
|
if y > min(p1y, p2y):
|
||||||
|
if y <= max(p1y, p2y):
|
||||||
|
if x <= max(p1x, p2x):
|
||||||
|
if p1y != p2y:
|
||||||
|
xinters = (y - p1y) * (p2x - p1x) / (p2y - p1y) + p1x
|
||||||
|
if p1x == p2x or x <= xinters:
|
||||||
|
inside = not inside
|
||||||
|
p1x, p1y = p2x, p2y
|
||||||
|
|
||||||
for i in range(3):
|
return inside
|
||||||
x = top_right_x_start + i * spacing
|
|
||||||
block_insert_x = x - text_d_x_offset
|
|
||||||
block_insert_y = top_right_y - text_d_y_offset
|
|
||||||
blockref = self.msp.add_blockref(
|
|
||||||
'io',
|
|
||||||
# insert=(block_insert_x, block_insert_y),
|
|
||||||
insert=(x, y),
|
|
||||||
dxfattribs={'layer': 'ILS_MOTOR'}
|
|
||||||
)
|
|
||||||
# Erzeuge Attribut-Instanzen aus ATTDEFs mit Werten
|
|
||||||
blockref.add_auto_attribs({
|
|
||||||
'SPS': '1',
|
|
||||||
'IO': 'MA-1@@',
|
|
||||||
'VERW': 'Motor',
|
|
||||||
'BEZEICHNUNG': 'Motor MA-1@@',
|
|
||||||
'ARTIKELNR': '790902001',
|
|
||||||
'ARTIKELBEZEICHN': 'E-Teile für SEW Motor ASE1-HAN10ES-BG',
|
|
||||||
'KENNZEICHNUNG': '=A01+UH00',
|
|
||||||
'TEXT-D': '',
|
|
||||||
'TEXT-E': '',
|
|
||||||
'TEXT-ES': '',
|
|
||||||
'TEXT-F': '',
|
|
||||||
'TEXT-I': '',
|
|
||||||
'ID': '',
|
|
||||||
'REALE_POSITION': 'x',
|
|
||||||
})
|
|
||||||
|
|
||||||
# Links unten: 1x MA-1@@
|
def _validate_symbols_in_frames(self, scene):
|
||||||
left_bottom_x = 500
|
"""
|
||||||
left_bottom_y = 200
|
Prüft ob alle generierten Symbole aus ma_groups in mindestens einem Renamer-Frame liegen.
|
||||||
# Der Insert-Punkt soll an der oberen linken Ecke des TEXT-D liegen
|
Gibt Warnungen aus für Symbole, die außerhalb liegen.
|
||||||
text_d_x_offset = 772.87
|
"""
|
||||||
text_d_y_offset = 110.44 + 63.75 # Basis + Höhe = obere linke Ecke
|
if not self.generated_symbols:
|
||||||
block_insert_x = left_bottom_x - text_d_x_offset
|
return
|
||||||
block_insert_y = left_bottom_y - text_d_y_offset
|
|
||||||
blockref = self.msp.add_blockref(
|
|
||||||
'io',
|
|
||||||
#insert=(block_insert_x, block_insert_y),
|
|
||||||
insert=(left_bottom_x, left_bottom_y),
|
|
||||||
dxfattribs={'layer': 'ILS_MOTOR'}
|
|
||||||
)
|
|
||||||
blockref.add_auto_attribs({
|
|
||||||
'SPS': '1',
|
|
||||||
'IO': 'MA-1@@',
|
|
||||||
'VERW': 'Motor',
|
|
||||||
'BEZEICHNUNG': 'Motor MA-1@@',
|
|
||||||
'ARTIKELNR': '790902001',
|
|
||||||
'ARTIKELBEZEICHN': 'E-Teile für SEW Motor ASE1-HAN10ES-BG',
|
|
||||||
'KENNZEICHNUNG': '=A01+UH00',
|
|
||||||
'TEXT-D': '',
|
|
||||||
'TEXT-E': '',
|
|
||||||
'TEXT-F': '',
|
|
||||||
'TEXT-ES': '',
|
|
||||||
'ID': '',
|
|
||||||
'REALE_POSITION': 'x'
|
|
||||||
})
|
|
||||||
|
|
||||||
# Rechts unten: 3x MA-2@@ leicht versetzt
|
print("\n" + "="*60)
|
||||||
bottom_right_y_start = 400
|
print("Prüfe ob alle generierten Symbole in Renamer-Frames liegen")
|
||||||
bottom_right_x_start = top_right_x_start
|
print("="*60)
|
||||||
y_offsets = [0, -50, 50] # Leichte vertikale Versetzung (angepasst an Symbol-Höhe)
|
|
||||||
|
|
||||||
# Der Insert-Punkt soll an der oberen linken Ecke des TEXT-D liegen
|
# Sammle alle Frame-Boundaries
|
||||||
text_d_x_offset = 772.87
|
frame_boundaries = []
|
||||||
text_d_y_offset = 110.44 + 63.75 # Basis + Höhe = obere linke Ecke
|
for frame_config in scene.get('renaming_frames', []):
|
||||||
|
frame_type = frame_config.get('type', 'rectangle')
|
||||||
|
layer_name = frame_config.get('layer_name', '')
|
||||||
|
|
||||||
for i in range(3):
|
if frame_type == 'polyline_path':
|
||||||
x = bottom_right_x_start + i * spacing
|
# Polyline-Pfad: verwende path_points direkt
|
||||||
y = bottom_right_y_start + y_offsets[i]
|
path_points = frame_config.get('path_points', [])
|
||||||
block_insert_x = x - text_d_x_offset
|
if path_points:
|
||||||
block_insert_y = y - text_d_y_offset
|
polygon = [(p['x'], p['y']) for p in path_points]
|
||||||
blockref = self.msp.add_blockref(
|
frame_boundaries.append({
|
||||||
'io',
|
'type': 'polygon',
|
||||||
#insert=(block_insert_x, block_insert_y),
|
'boundary': polygon,
|
||||||
insert=(x, y),
|
'name': frame_config.get('name', 'UNKNOWN'),
|
||||||
dxfattribs={'layer': 'ILS_MOTOR'}
|
'layer_name': layer_name
|
||||||
)
|
})
|
||||||
blockref.add_auto_attribs({
|
else:
|
||||||
'SPS': '1',
|
# Rechteck: berechne Eckpunkte
|
||||||
'IO': 'MA-2@@',
|
rect_x = frame_config.get('x', 0)
|
||||||
'VERW': 'Motor',
|
rect_y = frame_config.get('y', 0)
|
||||||
'BEZEICHNUNG': 'Motor MA-2@@',
|
rect_width = frame_config.get('width', 0)
|
||||||
'ARTIKELNR': '790902001',
|
rect_height = frame_config.get('height', 0)
|
||||||
'ARTIKELBEZEICHN': 'E-Teile für SEW Motor ASE1-HAN10ES-BG',
|
|
||||||
'KENNZEICHNUNG': '=A01+UH00',
|
|
||||||
'TEXT-D': '',
|
|
||||||
'TEXT-ES': '',
|
|
||||||
'TEXT-F': '',
|
|
||||||
'ID': '',
|
|
||||||
'REALE_POSITION': 'x'
|
|
||||||
})
|
|
||||||
|
|
||||||
# Renamer-Rahmen erstellen (mit angepassten Größen basierend auf Symbol-Ausdehnung)
|
# Erstelle Rechteck als Polygon (4 Eckpunkte)
|
||||||
# Puffer für Rahmen
|
polygon = [
|
||||||
frame_padding = 100
|
(rect_x, rect_y),
|
||||||
|
(rect_x + rect_width, rect_y),
|
||||||
|
(rect_x + rect_width, rect_y + rect_height),
|
||||||
|
(rect_x, rect_y + rect_height)
|
||||||
|
]
|
||||||
|
frame_boundaries.append({
|
||||||
|
'type': 'rectangle',
|
||||||
|
'boundary': polygon,
|
||||||
|
'rect_x': rect_x,
|
||||||
|
'rect_y': rect_y,
|
||||||
|
'rect_width': rect_width,
|
||||||
|
'rect_height': rect_height,
|
||||||
|
'name': frame_config.get('name', 'UNKNOWN'),
|
||||||
|
'layer_name': layer_name
|
||||||
|
})
|
||||||
|
|
||||||
# Rahmen 1: Rechts oben (Rechteck) - umschließt die 3 MA-1@@
|
# Prüfe jedes generierte Symbol
|
||||||
frame1_width = 3 * spacing + ma1_width * 0.2
|
symbols_outside = []
|
||||||
frame1_height = ma1_height + 2 * frame_padding
|
for symbol in self.generated_symbols:
|
||||||
self.create_renamer_frame(
|
symbol_point = (symbol['x'], symbol['y'])
|
||||||
insert_point=(top_right_x_start - frame_padding, top_right_y + frame_padding),
|
in_any_frame = False
|
||||||
width=frame1_width,
|
|
||||||
height=frame1_height,
|
for frame in frame_boundaries:
|
||||||
name='MA-1@@',
|
# Prüfe ob Symbol auf dem richtigen Layer ist
|
||||||
kennzeichnung='A01+UH00',
|
if frame['layer_name'] and symbol['layer'] != frame['layer_name']:
|
||||||
layer_name='ILS_MOTOR',
|
continue
|
||||||
direction='LEFT_RIGHT',
|
|
||||||
use_polyline=False
|
# Prüfe ob Symbol innerhalb des Frames liegt
|
||||||
)
|
if frame['type'] == 'rectangle':
|
||||||
|
if self._point_in_rectangle(
|
||||||
|
symbol_point,
|
||||||
|
frame['rect_x'],
|
||||||
|
frame['rect_y'],
|
||||||
|
frame['rect_width'],
|
||||||
|
frame['rect_height']
|
||||||
|
):
|
||||||
|
in_any_frame = True
|
||||||
|
break
|
||||||
|
else: # polygon
|
||||||
|
if self._point_in_polygon(symbol_point, frame['boundary']):
|
||||||
|
in_any_frame = True
|
||||||
|
break
|
||||||
|
|
||||||
|
if not in_any_frame:
|
||||||
|
symbols_outside.append(symbol)
|
||||||
|
|
||||||
|
# Gib Warnungen aus
|
||||||
|
if symbols_outside:
|
||||||
|
print(f"\nWARNUNG: {len(symbols_outside)} Symbol(e) liegen außerhalb aller Renamer-Frames:")
|
||||||
|
for symbol in symbols_outside:
|
||||||
|
print(f" Symbol IO='{symbol['io']}' aus Gruppe '{symbol['group_name']}' "
|
||||||
|
f"an Position ({symbol['x']:.1f}, {symbol['y']:.1f}) "
|
||||||
|
f"auf Layer '{symbol['layer']}' liegt in keinem Renamer-Frame")
|
||||||
|
else:
|
||||||
|
print(f"\n✓ Alle {len(self.generated_symbols)} generierten Symbole liegen in Renamer-Frames")
|
||||||
|
|
||||||
# Rahmen 2: Links unten (Polylinie) - umschließt das einzelne MA-1@@
|
|
||||||
# Schmaler machen - nur 15% breiter als das Symbol
|
|
||||||
frame2_padding = 50 # Kleinerer Puffer für schmalen Rahmen
|
|
||||||
frame2_width = ma1_width * 1.15
|
|
||||||
frame2_height = ma1_height + 2 * frame2_padding
|
|
||||||
self.create_renamer_frame(
|
|
||||||
insert_point=(left_bottom_x - frame2_padding, left_bottom_y - frame2_padding),
|
|
||||||
width=frame2_width,
|
|
||||||
height=frame2_height,
|
|
||||||
name='MA-1@@',
|
|
||||||
kennzeichnung='A01+UH00',
|
|
||||||
layer_name='ILS_MOTOR',
|
|
||||||
direction='TOP_BOTTOM/LEFT_RIGHT',
|
|
||||||
use_polyline=True
|
|
||||||
)
|
|
||||||
|
|
||||||
# Rahmen 3: Rechts unten (Rechteck) - umschließt die 3 MA-2@@
|
|
||||||
# Berücksichtige die vertikalen Offsets (max offset = 50)
|
|
||||||
frame3_width = 3 * spacing + ma2_width * 0.2
|
|
||||||
frame3_height = ma2_height + 2 * frame_padding + 100 # Extra für y_offsets
|
|
||||||
self.create_renamer_frame(
|
|
||||||
insert_point=(bottom_right_x_start - frame_padding, bottom_right_y_start - frame_padding - 50),
|
|
||||||
width=frame3_width,
|
|
||||||
height=frame3_height,
|
|
||||||
name='MA-2@@',
|
|
||||||
kennzeichnung='A01+UH00',
|
|
||||||
layer_name='ILS_MOTOR',
|
|
||||||
direction='TOP_BOTTOM',
|
|
||||||
use_polyline=False
|
|
||||||
)
|
|
||||||
|
|
||||||
def generate(self):
|
def generate(self):
|
||||||
"""Generiert die Testdaten basierend auf dem Test-Typ"""
|
"""Generiert die Testdaten basierend auf dem Test-Typ"""
|
||||||
|
|||||||
Reference in New Issue
Block a user