create_example prüft die Sinnhaftigkeit der position der frames
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
"count": 3,
|
||||
"layout_type": "horizontal",
|
||||
"base_x": 1500,
|
||||
"base_y": 1000,
|
||||
"base_y": 1300,
|
||||
"spacing": 1450
|
||||
},
|
||||
{
|
||||
@@ -25,7 +25,7 @@
|
||||
"name": "MA-2@@_bottom",
|
||||
"count": 3,
|
||||
"layout_type": "horizontal_offset",
|
||||
"base_x": 1500,
|
||||
"base_x": 2000,
|
||||
"base_y": 400,
|
||||
"spacing": 1450
|
||||
}
|
||||
@@ -37,9 +37,9 @@
|
||||
"kennzeichnung": "A01+UH00",
|
||||
"layer_name": "ILS_MOTOR",
|
||||
"direction": "LEFT_RIGHT",
|
||||
"x": 700,
|
||||
"x": 800,
|
||||
"y": 800,
|
||||
"width": 3600,
|
||||
"width": 4000,
|
||||
"height": 450,
|
||||
"use_polyline": false
|
||||
},
|
||||
@@ -50,7 +50,7 @@
|
||||
"layer_name": "ILS_MOTOR",
|
||||
"direction": "LEFT_RIGHT",
|
||||
"x": 450,
|
||||
"y": 150,
|
||||
"y": 100,
|
||||
"width": 1400,
|
||||
"height": 480,
|
||||
"use_polyline": true
|
||||
|
||||
+141
-166
@@ -29,6 +29,7 @@ class TestDataGenerator:
|
||||
self.doc = None
|
||||
self.msp = 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)
|
||||
if config_file:
|
||||
@@ -570,8 +571,7 @@ class TestDataGenerator:
|
||||
print(f"Verwende JSON-Config für {scene_name}...")
|
||||
self._generate_nummerierung_from_config(scene_name)
|
||||
else:
|
||||
print("Verwende Hard-coded Defaults für Nummerierung...")
|
||||
self._generate_nummerierung_hardcoded()
|
||||
print("Fehler in Config ... terminating")
|
||||
|
||||
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}")
|
||||
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(
|
||||
'io',
|
||||
insert=(block_insert_x, block_insert_y),
|
||||
#insert=(block_insert_x, block_insert_y),
|
||||
insert=(x, y),
|
||||
dxfattribs={'layer': layer}
|
||||
)
|
||||
|
||||
@@ -644,6 +637,15 @@ class TestDataGenerator:
|
||||
attrib_values['BEZEICHNUNG'] = f"Motor {io_pattern}"
|
||||
|
||||
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'):
|
||||
"""
|
||||
@@ -695,167 +697,140 @@ class TestDataGenerator:
|
||||
direction=frame_config['direction'],
|
||||
use_polyline=frame_config.get('use_polyline', False)
|
||||
)
|
||||
|
||||
# Prüfe ob alle generierten Symbole in einem Renamer-Frame liegen
|
||||
self._validate_symbols_in_frames(scene)
|
||||
|
||||
def _generate_nummerierung_hardcoded(self):
|
||||
"""Generiert Nummerierung-Testdaten mit Hard-coded Werten (Fallback)"""
|
||||
def _point_in_rectangle(self, point, rect_x, rect_y, rect_width, rect_height):
|
||||
"""
|
||||
Prüft ob ein Punkt innerhalb eines Rechtecks liegt.
|
||||
|
||||
Args:
|
||||
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)
|
||||
|
||||
# Berechne Symbol-Ausdehnung für korrekte Positionierung
|
||||
ma1_width, ma1_height = self.calculate_symbol_extent('MA-1@@')
|
||||
ma2_width, ma2_height = self.calculate_symbol_extent('MA-2@@')
|
||||
def _point_in_polygon(self, point, polygon):
|
||||
"""
|
||||
Prüft, ob ein Punkt innerhalb eines Polygons liegt (Ray-casting Algorithmus).
|
||||
"""
|
||||
x, y = point
|
||||
n = len(polygon)
|
||||
inside = False
|
||||
|
||||
# Abstand zwischen Symbolen (20% der Breite als Puffer)
|
||||
spacing = ma1_width * 1.2
|
||||
p1x, p1y = polygon[0]
|
||||
for i in range(1, n + 1):
|
||||
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
|
||||
|
||||
# Definiere Positionen
|
||||
# Rechts oben: 3x MA-1@@ nebeneinander
|
||||
top_right_y = 1000
|
||||
top_right_x_start = 1500
|
||||
return inside
|
||||
|
||||
# Der Insert-Punkt soll an der oberen linken Ecke des TEXT-D liegen
|
||||
text_d_x_offset = 772.87
|
||||
text_d_y_offset = 110.44 + 63.75 # Basis + Höhe = obere linke Ecke
|
||||
def _validate_symbols_in_frames(self, scene):
|
||||
"""
|
||||
Prüft ob alle generierten Symbole aus ma_groups in mindestens einem Renamer-Frame liegen.
|
||||
Gibt Warnungen aus für Symbole, die außerhalb liegen.
|
||||
"""
|
||||
if not self.generated_symbols:
|
||||
return
|
||||
|
||||
print("\n" + "="*60)
|
||||
print("Prüfe ob alle generierten Symbole in Renamer-Frames liegen")
|
||||
print("="*60)
|
||||
|
||||
# Sammle alle Frame-Boundaries
|
||||
frame_boundaries = []
|
||||
for frame_config in scene.get('renaming_frames', []):
|
||||
frame_type = frame_config.get('type', 'rectangle')
|
||||
layer_name = frame_config.get('layer_name', '')
|
||||
|
||||
if frame_type == 'polyline_path':
|
||||
# Polyline-Pfad: verwende path_points direkt
|
||||
path_points = frame_config.get('path_points', [])
|
||||
if path_points:
|
||||
polygon = [(p['x'], p['y']) for p in path_points]
|
||||
frame_boundaries.append({
|
||||
'type': 'polygon',
|
||||
'boundary': polygon,
|
||||
'name': frame_config.get('name', 'UNKNOWN'),
|
||||
'layer_name': layer_name
|
||||
})
|
||||
else:
|
||||
# Rechteck: berechne Eckpunkte
|
||||
rect_x = frame_config.get('x', 0)
|
||||
rect_y = frame_config.get('y', 0)
|
||||
rect_width = frame_config.get('width', 0)
|
||||
rect_height = frame_config.get('height', 0)
|
||||
|
||||
# Erstelle Rechteck als Polygon (4 Eckpunkte)
|
||||
polygon = [
|
||||
(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
|
||||
})
|
||||
|
||||
# Prüfe jedes generierte Symbol
|
||||
symbols_outside = []
|
||||
for symbol in self.generated_symbols:
|
||||
symbol_point = (symbol['x'], symbol['y'])
|
||||
in_any_frame = False
|
||||
|
||||
for frame in frame_boundaries:
|
||||
# Prüfe ob Symbol auf dem richtigen Layer ist
|
||||
if frame['layer_name'] and symbol['layer'] != frame['layer_name']:
|
||||
continue
|
||||
|
||||
# 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")
|
||||
|
||||
for i in range(3):
|
||||
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@@
|
||||
left_bottom_x = 500
|
||||
left_bottom_y = 200
|
||||
# Der Insert-Punkt soll an der oberen linken Ecke des TEXT-D liegen
|
||||
text_d_x_offset = 772.87
|
||||
text_d_y_offset = 110.44 + 63.75 # Basis + Höhe = obere linke Ecke
|
||||
block_insert_x = left_bottom_x - text_d_x_offset
|
||||
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
|
||||
bottom_right_y_start = 400
|
||||
bottom_right_x_start = top_right_x_start
|
||||
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
|
||||
text_d_x_offset = 772.87
|
||||
text_d_y_offset = 110.44 + 63.75 # Basis + Höhe = obere linke Ecke
|
||||
|
||||
for i in range(3):
|
||||
x = bottom_right_x_start + i * spacing
|
||||
y = bottom_right_y_start + y_offsets[i]
|
||||
block_insert_x = x - text_d_x_offset
|
||||
block_insert_y = 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'}
|
||||
)
|
||||
blockref.add_auto_attribs({
|
||||
'SPS': '1',
|
||||
'IO': 'MA-2@@',
|
||||
'VERW': 'Motor',
|
||||
'BEZEICHNUNG': 'Motor MA-2@@',
|
||||
'ARTIKELNR': '790902001',
|
||||
'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)
|
||||
# Puffer für Rahmen
|
||||
frame_padding = 100
|
||||
|
||||
# Rahmen 1: Rechts oben (Rechteck) - umschließt die 3 MA-1@@
|
||||
frame1_width = 3 * spacing + ma1_width * 0.2
|
||||
frame1_height = ma1_height + 2 * frame_padding
|
||||
self.create_renamer_frame(
|
||||
insert_point=(top_right_x_start - frame_padding, top_right_y + frame_padding),
|
||||
width=frame1_width,
|
||||
height=frame1_height,
|
||||
name='MA-1@@',
|
||||
kennzeichnung='A01+UH00',
|
||||
layer_name='ILS_MOTOR',
|
||||
direction='LEFT_RIGHT',
|
||||
use_polyline=False
|
||||
)
|
||||
|
||||
# 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):
|
||||
"""Generiert die Testdaten basierend auf dem Test-Typ"""
|
||||
|
||||
Reference in New Issue
Block a user