1+ import math
2+
13from flask import Flask , request , jsonify
24
35from dxf import SurveyDXFManager
46from models .plan import PlanProps
7+ from utils import polygon_orientation , line_normals , line_direction
58
69app = Flask (__name__ )
710app .config ["SECRET_KEY" ] = "secret"
@@ -17,29 +20,76 @@ def generate_cadastral_plan():
1720
1821 plan = PlanProps (** data )
1922 extent = plan .get_extent ()
20- beacon_size = extent * 0.05
23+ beacon_size = extent * 0.02
2124
2225 drawer = SurveyDXFManager (plan_name = plan .name , scale = plan .scale )
2326 drawer .setup_beacon_style (type_ = plan .beacon_type , size = beacon_size or 1.0 )
2427 drawer .setup_font (plan .font )
2528
29+ label_height = extent * 0.015 if extent > 0 else 1.0
30+
2631 # Draw beacon and labels
2732 for coord in plan .coordinates :
2833 drawer .add_beacon (coord .easting , coord .northing , 0 , beacon_size * 0.5 , coord .id )
2934
3035 # create a dictionary of coordinates for easy lookup
3136 coord_dict = {coord .id : coord for coord in plan .coordinates }
37+ parcel_dict = {}
3238
3339 # Draw parcels
3440 for parcel in plan .parcels :
3541 parcel_points = []
3642 for point_id in parcel .ids :
3743 if point_id in coord_dict :
3844 coord = coord_dict [point_id ]
39- parcel_points .append ((coord .easting , coord .northing , coord . elevation ))
45+ parcel_points .append ((coord .easting , coord .northing ))
4046 if parcel_points :
4147 drawer .add_parcel (parcel .name , parcel_points )
4248
49+ # add bearing and distance text
50+ orientation = polygon_orientation (parcel_points )
51+ for leg in parcel .legs :
52+ # compute rotational angle for text
53+ angle_rad = math .atan2 (leg .to .northing - leg .from_ .northing , leg .to .easting - leg .from_ .easting )
54+ angle_deg = math .degrees (angle_rad )
55+
56+ first_x = leg .from_ .easting + (0.2 * (leg .to .easting - leg .from_ .easting ))
57+ first_y = leg .from_ .northing + (0.2 * (leg .to .northing - leg .from_ .northing ))
58+ last_x = leg .from_ .easting + (0.8 * (leg .to .easting - leg .from_ .easting ))
59+ last_y = leg .from_ .northing + (0.8 * (leg .to .northing - leg .from_ .northing ))
60+ mid_x = (leg .from_ .easting + leg .to .easting ) / 2
61+ mid_y = (leg .from_ .northing + leg .to .northing ) / 2
62+
63+ # Offset text above/below the line
64+ normals = line_normals ((leg .from_ .easting , leg .from_ .northing ), (leg .to .easting , leg .to .northing ), orientation )
65+ offset_distance = extent * 0.02
66+ offset_inside_x = (normals [0 ][0 ] / math .hypot (* normals [0 ])) * offset_distance
67+ offset_inside_y = (normals [0 ][1 ] / math .hypot (* normals [0 ])) * offset_distance
68+ offset_outside_x = (normals [1 ][0 ] / math .hypot (* normals [1 ])) * offset_distance
69+ offset_outside_y = (normals [1 ][1 ] / math .hypot (* normals [1 ])) * offset_distance
70+ first_x += offset_outside_x
71+ first_y += offset_outside_y
72+ last_x += offset_outside_x
73+ last_y += offset_outside_y
74+ mid_x += offset_inside_x
75+ mid_y += offset_inside_y
76+
77+ # add texts
78+ text_angle = angle_deg
79+ if text_angle > 90 or text_angle < - 90 :
80+ text_angle += 180
81+
82+ drawer .add_text (f"{ leg .distance :.2f} m" , mid_x , mid_y , angle = text_angle , height = label_height )
83+ ld = line_direction (angle_deg )
84+ print (leg .from_ .id , leg .to .id , ld )
85+ if ld == "left → right" :
86+ drawer .add_text (f"{ leg .bearing .degrees } °" , first_x , first_y , angle = text_angle , height = label_height )
87+ drawer .add_text (f"{ leg .bearing .minutes } '" , last_x , last_y , angle = text_angle , height = label_height )
88+ else :
89+ drawer .add_text (f"{ leg .bearing .degrees } °" , last_x , last_y , angle = text_angle , height = label_height )
90+ drawer .add_text (f"{ leg .bearing .minutes } '" , first_x , first_y , angle = text_angle , height = label_height )
91+ parcel_dict [parcel .name ] = parcel_points
92+
4393 # Compute extent sizes
4494 min_x , min_y , max_x , max_y = plan .get_bounding_box ()
4595 width = max_x - min_x
@@ -55,9 +105,14 @@ def generate_cadastral_plan():
55105 offset_y = max (height , width ) * 0.78
56106 drawer .draw_frame (min_x - offset_x , min_y - offset_y , max_x + offset_x , max_y + offset_y )
57107
58- # add bearing and distance text
108+ # add title block
109+ box_width = (max_x + margin_x ) - (min_x - margin_x ) * 0.6
110+ title_x = ((min_x - margin_x ) + (max_x + margin_x )) / 2
111+ title_y = (max_y + margin_y ) - (margin_y * 0.15 )
112+ text_height = plan .font_size or ((max_y + margin_y ) - (min_y - margin_y )) * 0.02
113+ drawer .add_title (plan .title .upper (), title_x , title_y , width = box_width , height = text_height )
59114
60- drawer .dxf_to_pdf ()
115+ drawer .save_dxf ()
61116 return jsonify ({"message" : "Cadastral plan generated" , "filename" : plan .name }), 200
62117
63118if __name__ == '__main__' :
0 commit comments