1010import uuid
1111import zipfile
1212from upload import upload_file
13+ from ezdxf import bbox
14+
1315
1416class SurveyDXFManager :
1517 def __init__ (self , plan_name : str = "Survey Plan" , scale : float = 1.0 ):
@@ -83,6 +85,93 @@ def setup_beacon_style(self, type_: str = "box", size: float = 1.0):
8385 path = hatch .paths .add_edge_path ()
8486 path .add_arc ((0 , 0 ), radius = radius , start_angle = 0 , end_angle = 360 )
8587
88+ def setup_graphical_scale_style (self , length : float = 1000 ):
89+ length = length * self .scale
90+ height = length * 0.05 # 5% of length
91+
92+ interval = length / 5 # 5 intervals
93+
94+ # Create a block for the graphical scale
95+ block = self .doc .blocks .new (name = 'GRAPHICAL_SCALE' )
96+
97+ # draw large rectangle
98+ block .add_lwpolyline (
99+ [(0 , 0 ), (length , 0 ), (length , height ), (0 , height )],
100+ close = True ,
101+ dxfattribs = {'color' : 7 } # Black/White
102+ )
103+
104+ # draw middle line
105+ block .add_line (
106+ (0 , height / 2 ),
107+ (length , height / 2 ),
108+ dxfattribs = {'color' : 7 }
109+ )
110+
111+ text_interval = 1000 / self .scale / 10 / 5
112+
113+ # draw interval lines
114+ to_shade = "up"
115+ for i in range (6 ):
116+ x = i * interval
117+ line_height = height * 1.5
118+ block .add_line (
119+ (x , 0 ),
120+ (x , line_height ),
121+ dxfattribs = {'color' : 7 }
122+ )
123+
124+ text = f"{ int ((i - 1 ) * text_interval )} "
125+ alignment = TextEntityAlignment .TOP_CENTER
126+ if i == 0 :
127+ text = f"Meters { int (text_interval )} "
128+ alignment = TextEntityAlignment .TOP_RIGHT
129+ if i == 5 :
130+ text = f"{ int ((i - 1 ) * text_interval )} Meters"
131+ alignment = TextEntityAlignment .TOP_LEFT
132+
133+
134+ # add text above line
135+ block .add_text (
136+ text ,
137+ dxfattribs = {
138+ 'height' : height * 0.5 ,
139+ 'color' : 7 ,
140+ 'style' : 'SURVEY_TEXT'
141+ }
142+ ).set_placement (
143+ (x , height * 2.3 ),
144+ align = alignment
145+ )
146+
147+
148+ if i == 5 :
149+ continue
150+
151+ if i == 0 :
152+ mini_interval = interval / 2
153+ for j in range (2 ):
154+ mini_x = j * mini_interval
155+ if to_shade == "up" :
156+ # shade first upper half
157+ hatch = block .add_hatch (color = 7 )
158+ hatch .paths .add_polyline_path ([(mini_x , height / 2 ), (mini_x + mini_interval , height / 2 ), (mini_x + mini_interval , height ), (mini_x , height )])
159+ to_shade = "down"
160+ else :
161+ # shade lower half
162+ hatch = block .add_hatch (color = 7 )
163+ hatch .paths .add_polyline_path ([(mini_x , 0 ), (mini_x + mini_interval , 0 ), (mini_x + mini_interval , height / 2 ), (mini_x , height / 2 )])
164+ to_shade = "up"
165+ else :
166+ if to_shade == "up" :
167+ hatch = block .add_hatch (color = 7 )
168+ hatch .paths .add_polyline_path ([(x , height / 2 ), (x + interval , height / 2 ), (x + interval , height ), (x , height )])
169+ to_shade = "down"
170+ else :
171+ hatch = block .add_hatch (color = 7 )
172+ hatch .paths .add_polyline_path ([(x , 0 ), (x + interval , 0 ), (x + interval , height / 2 ), (x , height / 2 )])
173+ to_shade = "up"
174+
86175 def setup_font (self , font_name : str = "Times New Roman" ):
87176 # Add a new text style with the specified font
88177 self .doc .styles .add ('SURVEY_TEXT' , font = f'{ font_name } .ttf' )
@@ -147,7 +236,7 @@ def add_text(self, text: str, x: float, y: float, angle: float = 0.0, height: fl
147236 height = height * self .scale
148237
149238 """Add arbitrary text at given coordinates with optional rotation"""
150- self .msp .add_text (
239+ text = self .msp .add_text (
151240 text ,
152241 dxfattribs = {
153242 'layer' : 'LABELS' ,
@@ -160,22 +249,57 @@ def add_text(self, text: str, x: float, y: float, angle: float = 0.0, height: fl
160249 align = TextEntityAlignment .MIDDLE_CENTER
161250 )
162251
163- def add_title (self , text : str , x : float , y : float , width : float , title_height : float = 1.0 ):
252+ def draw_title_block (self , text : str , x : float , y : float , width : float , title_height : float = 1.0 , graphical_scale_length : float = 1000.0 , origin : str = "" , area : str = "" ):
164253 x = x * self .scale
165254 y = y * self .scale
166255 title_height = title_height * self .scale
167256 width = width * self .scale
257+ graphical_scale_length = graphical_scale_length * self .scale
168258
169- # Add title block text with underline
170- title_mtext = self . msp .add_mtext (
259+ block = self . doc . blocks . new ( name = 'TITLE_BLOCK' )
260+ title_mtext = block .add_mtext (
171261 text = f"{ MTextEditor .UNDERLINE_START } { text } { MTextEditor .UNDERLINE_STOP } " ,
172- dxfattribs = {'layer' : 'TITLE_BLOCK' , ' style' : 'SURVEY_TEXT' },
262+ dxfattribs = {'style' : 'SURVEY_TEXT' },
173263 )
174- title_mtext .set_location ((x , y ))
175264 title_mtext .dxf .attachment_point = ezdxf .enums .MTextEntityAlignment .TOP_CENTER
176265 title_mtext .dxf .char_height = title_height
177266 title_mtext .dxf .width = width
178267
268+ # add block to modelspace
269+ title_ref = self .msp .add_blockref (
270+ 'TITLE_BLOCK' ,
271+ (x , y ),
272+ dxfattribs = {'layer' : 'TITLE_BLOCK' }
273+ )
274+
275+ title_box = bbox .extents (title_ref .virtual_entities ())
276+ title_min_y = title_box .extmin .y
277+ title_min_x = title_box .extmin .x
278+ title_max_x = title_box .extmax .x
279+
280+ title_length = title_max_x - title_min_x
281+ graphical_x = title_min_x + ((title_length / 2 ) - (graphical_scale_length / 2 ))
282+
283+ # add graphical scale below title
284+ graphical_ref = self .msp .add_blockref (
285+ 'GRAPHICAL_SCALE' ,
286+ (graphical_x , title_min_y - (3.5 * self .scale )),
287+ dxfattribs = {'layer' : 'TITLE_BLOCK' }
288+ )
289+
290+ graphical_box = bbox .extents (graphical_ref .virtual_entities ())
291+ graphical_min_y = graphical_box .extmin .y
292+
293+ origin_mtext = self .msp .add_mtext (
294+ text = f"{ MTextEditor .UNDERLINE_START } \C5;{ area } { MTextEditor .NEW_LINE } \C1;{ origin } { MTextEditor .UNDERLINE_STOP } " ,
295+ dxfattribs = {'style' : 'SURVEY_TEXT' },
296+ )
297+ origin_mtext .dxf .attachment_point = ezdxf .enums .MTextEntityAlignment .TOP_CENTER
298+ origin_mtext .dxf .char_height = title_height
299+ origin_mtext .dxf .width = width
300+ origin_mtext .set_location ((x , graphical_min_y - (1 * self .scale )))
301+
302+
179303 def draw_frame (self , min_x , min_y , max_x , max_y ):
180304 min_x = min_x * self .scale
181305 min_y = min_y * self .scale
0 commit comments