Marthee commited on
Commit
78e5766
·
verified ·
1 Parent(s): 4df4b5f

Upload dxf__omar3_2.py

Browse files
Files changed (1) hide show
  1. dxf__omar3_2.py +433 -0
dxf__omar3_2.py ADDED
@@ -0,0 +1,433 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ # -*- coding: utf-8 -*-
2
+ """Version to be deployed of 3.2 Calculating area/perimeter
3
+
4
+ Automatically generated by Colab.
5
+
6
+ Original file is located at
7
+ https://colab.research.google.com/drive/1XPeCoTBgWSNBYZ3aMKBteP4YG3w4bORs
8
+ """
9
+
10
+ # pip install ezdxf[draw]
11
+
12
+ # pip install --upgrade ezdxf
13
+
14
+ # pip install pymupdf #==1.22.5
15
+
16
+ # pip install PyPDF2
17
+
18
+ # pip install ezdxf scipy
19
+
20
+ """## Imports"""
21
+
22
+ import numpy as np
23
+ import cv2
24
+ from matplotlib import pyplot as plt
25
+ import math
26
+ from PIL import Image , ImageDraw, ImageFont , ImageColor
27
+ import fitz
28
+ import ezdxf as ez
29
+ import sys
30
+ from ezdxf import units
31
+ from ezdxf.math import OCS, Matrix44, Vec3
32
+ import ezdxf
33
+ import matplotlib.pyplot as plt
34
+ from matplotlib.patches import Polygon
35
+ from shapely.geometry import Polygon as ShapelyPolygon
36
+ from ezdxf.math import Vec2
37
+ import random
38
+ import pandas as pd
39
+ import google_sheet_Legend
40
+
41
+ """## Notes"""
42
+
43
+ #new approach to get width and height of dxf plan
44
+ '''
45
+ This portion is used to convert vertices read from dxf to pixels in order to accurately locate shapes in the image and pdf
46
+ ratio :
47
+ MeasuredMetric* PixelValue/ DxfMetric = MeasuredPixel
48
+ PixelValue: get from pixel conversion code , second number in the bracker represents the perimeter
49
+ DxfMetric: measured perimeter from foxit
50
+
51
+ divide pixelvalue by dxfmetric, will give u a ratio , this is ur dxfratio
52
+
53
+
54
+ '''
55
+
56
+
57
+ """PDF to image"""
58
+
59
+ def pdftoimg(datadoc):
60
+ doc = fitz.open('pdf',datadoc)
61
+ page=doc[0]
62
+ pix = page.get_pixmap() # render page to an image
63
+ pl=Image.frombytes('RGB', [pix.width,pix.height],pix.samples)
64
+ img=np.array(pl)
65
+ img = cv2.cvtColor(img, cv2.COLOR_RGB2BGR)
66
+ return img
67
+
68
+ """Flips image
69
+ DXF origin is at the bottom left while img origin is top left
70
+ """
71
+
72
+ def flip(img):
73
+ height, width = img.shape[:2]
74
+
75
+ # Define the rotation angle (clockwise)
76
+ angle = 180
77
+
78
+ # Calculate the rotation matrix
79
+ rotation_matrix = cv2.getRotationMatrix2D((width/2, height/2), angle, 1)
80
+
81
+ # Rotate the image
82
+ rotated_image = cv2.warpAffine(img, rotation_matrix, (width, height))
83
+ flipped_horizontal = cv2.flip(rotated_image, 1)
84
+ return flipped_horizontal
85
+
86
+ """### Hatched areas"""
87
+
88
+ def get_hatched_areas(filename):
89
+ doc = ezdxf.readfile(filename)
90
+ doc.header['$MEASUREMENT'] = 1
91
+ msp = doc.modelspace()
92
+ trial=0
93
+ hatched_areas = []
94
+
95
+ for entity in msp:
96
+ # print(entity.dxftype())
97
+ if entity.dxftype() == 'HATCH':
98
+ flag=0
99
+ trial=0
100
+ # print("Gowa el hatch")
101
+ for path in entity.paths:
102
+ # print("gowa el for")
103
+ try:
104
+ vertices = [(vertex[0], vertex[1])for vertex in path.vertices]
105
+ if(len(vertices)>3):
106
+
107
+ poly = ShapelyPolygon(vertices)
108
+
109
+ if poly.area > 0.5:
110
+ area1 = round(poly.area,3)
111
+ perimeter = round (poly.length,3)
112
+
113
+ if trial==0:
114
+ hatched_areas.append([vertices,area1,perimeter])
115
+ trial=1
116
+ # print("hatched_areas = ", hatched_areas)
117
+
118
+ else:
119
+
120
+ for i in range(len(hatched_areas)):
121
+
122
+ if(area1 == hatched_areas[i][1]):
123
+ flag=1
124
+
125
+ # if(flag==0):
126
+ # hatched_areas.append([vertices,area1])
127
+
128
+ # hatched_areas.append([vertices,area1])
129
+ # print("Gowa el hatch2")
130
+
131
+
132
+
133
+ # print("Gowa el if ely b3d el hatch")
134
+
135
+ # if entity.area > 0.5:
136
+ # hatched_areas.append([entity.area])
137
+
138
+ except:
139
+ # print("in except")
140
+ vert=[]
141
+ flag=0
142
+ flag2=0
143
+ for edge in path.edges:
144
+ x,y=edge.start
145
+ x1,y1=edge.end
146
+ # print(edge.start)
147
+ # print(edge.end)
148
+ if(flag==0):
149
+ vert=[(x,y),(x1,y1)]
150
+ else:
151
+ vert.append([x1,y1])
152
+ flag=1
153
+ # print(vert)
154
+ poly = ShapelyPolygon(vert)
155
+ # print("New Hatch Area = ",poly.area)
156
+
157
+ if (poly.area > 0.5):
158
+ area1= round(poly.area,3)
159
+ perimeter = round (poly.length,3)
160
+
161
+ for i in range(len(hatched_areas)):
162
+
163
+ if(area1 == hatched_areas[i][1]):
164
+ flag2=1
165
+
166
+ if(flag2==0):
167
+ hatched_areas.append([vert,area1,perimeter])
168
+ # hatched_areas.append([vert,area1])
169
+ # # hatched_areas.append(vertices)
170
+ # continue
171
+
172
+ elif entity.dxftype() == 'SOLID':
173
+
174
+ vertices = [entity.dxf.vtx0, entity.dxf.vtx1, entity.dxf.vtx2, entity.dxf.vtx3]
175
+ poly = ShapelyPolygon(vertices)
176
+ # print("Gowa el solid")
177
+
178
+
179
+ if poly.area > 0.5:
180
+ hatched_areas.append([vertices,poly.area,poly.length])
181
+ # print("Gowa el if ely b3d el solid")
182
+
183
+
184
+ elif entity.dxftype() == 'LWPOLYLINE':
185
+
186
+ vertices=[]
187
+ lwpolyline = entity
188
+ points = lwpolyline.get_points()
189
+ flag=0
190
+
191
+ for i in range(len(points)):
192
+ vertices.append([points[i][0],points[i][1]])
193
+ if(len(vertices)>3):
194
+
195
+ if(vertices[0][0] == vertices[len(vertices)-1][0] or vertices[0][1] == vertices[len(vertices)-1][1]):
196
+
197
+ poly=ShapelyPolygon(vertices)
198
+ # print("vertices==",vertices)
199
+
200
+ if poly.area > 0.5:
201
+
202
+ area1 = round(poly.area,3)
203
+ perimeter = round (poly.length,3)
204
+
205
+ for i in range(len(hatched_areas)):
206
+
207
+ if(area1 == hatched_areas[i][1]):
208
+ flag=1
209
+
210
+ if(flag==0):
211
+ hatched_areas.append([vertices,area1,perimeter])
212
+
213
+
214
+
215
+ elif entity.dxftype() == 'SPLINE':
216
+
217
+ spline_entity = entity
218
+
219
+ vertices = []
220
+
221
+ control_points = spline_entity.control_points
222
+
223
+
224
+ if(len(control_points)>3):
225
+
226
+ for i in range(len(control_points)):
227
+ vertices.append([control_points[i][0],control_points[i][1]])
228
+
229
+
230
+
231
+ poly=ShapelyPolygon(vertices)
232
+
233
+
234
+
235
+
236
+ if poly.area > 0.5:
237
+
238
+ area1 = round(poly.area,3)
239
+ perimeter = round (poly.length,3)
240
+
241
+ hatched_areas.append([vertices,area1,perimeter])
242
+ return hatched_areas
243
+
244
+ """### Rotate polygon"""
245
+
246
+ from math import sin, cos, radians
247
+
248
+ def rotate_point(point, angle,pdfrotation,pdfsize, center_point=(0, 0)):
249
+ """Rotates a point around center_point(origin by default)
250
+ Angle is in degrees.
251
+ Rotation is counter-clockwise
252
+ """
253
+ angle_rad = radians(angle % 360)
254
+ # Shift the point so that center_point becomes the origin
255
+ new_point = (point[0] - center_point[0], point[1] - center_point[1])
256
+ new_point = (new_point[0] * cos(angle_rad) - new_point[1] * sin(angle_rad),
257
+ new_point[0] * sin(angle_rad) + new_point[1] * cos(angle_rad))
258
+ # Reverse the shifting we have done
259
+ if pdfrotation!=0:
260
+
261
+ new_point = (new_point[0]+pdfsize[2] + center_point[0], new_point[1] + center_point[1]) #pdfsize[2] is the same as +width
262
+ else:
263
+
264
+ new_point = (new_point[0] + center_point[0], new_point[1]+ pdfsize[3] + center_point[1]) # pdfsize[3] is the same as +height
265
+ # new_point = (new_point[0] + center_point[0], new_point[1] + center_point[1])
266
+ return new_point
267
+
268
+
269
+ def rotate_polygon(polygon, angle, pdfrotation,pdfsize,center_point=(0, 0)):
270
+ """Rotates the given polygon which consists of corners represented as (x,y)
271
+ around center_point (origin by default)
272
+ Rotation is counter-clockwise
273
+ Angle is in degrees
274
+ """
275
+ rotated_polygon = []
276
+ for corner in polygon:
277
+ rotated_corner = rotate_point(corner, angle,pdfrotation,pdfsize, center_point)
278
+ rotated_polygon.append(rotated_corner)
279
+ return rotated_polygon
280
+
281
+ #create a dataframe containing color , count(how many times is this object found in the plan), area of 1 of these shapes, total area
282
+ #perimeter, totat perimeter, length, total length
283
+ #import pandas as pd
284
+ #SimilarAreaDictionary= pd.DataFrame(columns=['Guess','Color','Occurences','Area','Total Area','Perimeter','Total Perimeter','Length','Total Length','R','G','B'])
285
+ #loop 3la hatched areas and count the occurences of each shape w create a table bl hagat di
286
+
287
+ def generate_color_array(length):
288
+ colorRanges = []
289
+ while len(colorRanges) < length:
290
+ # Generate random RGB values
291
+ r = random.randint(0, 255)
292
+ g = random.randint(0, 255)
293
+ b = random.randint(0, 255)
294
+ # Ensure no duplicate colors
295
+ if (r, g, b) not in colorRanges:
296
+ colorRanges.append((r, g, b))
297
+ return colorRanges
298
+
299
+ def Create_DF(dxfpath):
300
+
301
+ hatched_areas = get_hatched_areas(dxfpath)
302
+ # SimilarAreaDictionary= pd.DataFrame(columns=['Area', 'Total Area', 'Perimeter', 'Total Perimeter', 'Occurences', 'Color'])
303
+ SimilarAreaDictionary= pd.DataFrame(columns=['Guess','Color','Occurences','Area','Total Area','Perimeter','Total Perimeter','Length','Total Length','Texts'])
304
+
305
+ colorRanges=generate_color_array(300)
306
+ TotalArea=0
307
+ TotalPerimeter=0
308
+ for i in range(len(hatched_areas)):
309
+ area = hatched_areas[i][1] # area
310
+ perimeter = hatched_areas[i][2] # perimeter
311
+ color = colorRanges[i]
312
+ TotalArea = area
313
+ TotalPerimeter = perimeter
314
+ tol=1
315
+ condition1 = (SimilarAreaDictionary['Area'] >= area - tol) & (SimilarAreaDictionary['Area'] <= area +tol)
316
+ condition2 = (SimilarAreaDictionary['Perimeter'] >= perimeter -tol) & (SimilarAreaDictionary['Perimeter'] <= perimeter +tol)
317
+ combined_condition = condition1 & condition2
318
+
319
+ if any(combined_condition):
320
+ index = np.where(combined_condition)[0][0]
321
+ SimilarAreaDictionary.at[index, 'Occurences'] += 1
322
+ SimilarAreaDictionary.at[index, 'Total Area'] = SimilarAreaDictionary.at[index, 'Area'] * SimilarAreaDictionary.at[index, 'Occurences']
323
+ SimilarAreaDictionary.at[index, 'Total Perimeter'] = SimilarAreaDictionary.at[index, 'Perimeter'] * SimilarAreaDictionary.at[index, 'Occurences']
324
+ else:
325
+ TotalArea=area
326
+ TotalPerimeter=perimeter
327
+ new_data = {'Area': area, 'Total Area': TotalArea ,'Perimeter': perimeter, 'Total Perimeter': TotalPerimeter, 'Occurences': 1, 'Color':color} #add color here and read color to insert in
328
+ SimilarAreaDictionary = pd.concat([SimilarAreaDictionary, pd.DataFrame([new_data])], ignore_index=True)
329
+
330
+ # print(SimilarAreaDictionary)
331
+ return SimilarAreaDictionary
332
+ """### Draw on Image and PDF"""
333
+
334
+ def mainFunctionDrawImgPdf(datadoc,dxfpath, dxfratio,pdfpath,pdfname):
335
+
336
+ hatched_areas = get_hatched_areas(dxfpath)
337
+ img=pdftoimg(datadoc)
338
+ flipped_horizontal=flip(img)
339
+ allcnts = []
340
+ imgg = flipped_horizontal
341
+ imgtransparent1=imgg.copy()
342
+ doc = fitz.open('pdf',datadoc)
343
+ page2 = doc[0]
344
+ rotationOld=page2.rotation
345
+ derotationMatrix=page2.derotation_matrix
346
+ pix=page2.get_pixmap()
347
+ if page2.rotation!=0:
348
+
349
+ rotationangle = page2.rotation
350
+ page2.set_rotation(0)
351
+ ratio = pix.width/ img.shape[0]
352
+ else:
353
+ ratio = pix.width/ img.shape[1]
354
+ rotationangle = 270
355
+
356
+ allshapes=[]
357
+ # Iterate through each polygon in metric units
358
+ NewColors = []
359
+ SimilarAreaDictionary=Create_DF(dxfpath)
360
+ i=0
361
+
362
+
363
+ for polygon in hatched_areas:
364
+ cntPoints = []
365
+ cntPoints1 = []
366
+ shapee = []
367
+ # Convert each vertex from metric to pixel coordinates
368
+ for vertex in polygon[0]:
369
+ x = (vertex[0]) *dxfratio
370
+ y = (vertex[1]) *dxfratio
371
+ if rotationangle==0:
372
+ if y<0:
373
+ y=y*-1
374
+ cntPoints.append([int(x), int(y)])
375
+ cntPoints1.append([x, y])
376
+
377
+
378
+
379
+ for poi in np.array(cntPoints1):
380
+ x1, y1 = poi
381
+ p1 = fitz.Point(x1,y1)
382
+ # p1 = fitz.Point(x1,y1)
383
+ p1=p1*derotationMatrix
384
+ shapee.append([p1[0],p1[1]])
385
+
386
+ shapee=np.flip(shapee,1)
387
+ shapee=rotate_polygon(shapee,rotationangle,rotationOld,page2.mediabox)
388
+
389
+
390
+ tol=1
391
+ condition1 = (SimilarAreaDictionary['Area'] >= polygon[1] - tol) & (SimilarAreaDictionary['Area'] <= polygon[1] +tol)
392
+ condition2 = (SimilarAreaDictionary['Perimeter'] >= polygon[2] -tol) & (SimilarAreaDictionary['Perimeter'] <= polygon[2] +tol)
393
+ combined_condition = condition1 & condition2
394
+
395
+ if any(combined_condition):
396
+
397
+ index = np.where(combined_condition)[0][0]
398
+ # print(SimilarAreaDictionary.at[index, 'Color'])
399
+ NewColors=SimilarAreaDictionary.at[index, 'Color']
400
+ else:
401
+ NewColors=SimilarAreaDictionary.at[i, 'Color']
402
+
403
+ # cv2.drawContours(imgg, [np.array(cntPoints)], -1, (NewColors), thickness=2)
404
+ cv2.drawContours(imgg, [np.array(cntPoints)], -1, ([NewColors[2],NewColors[1],NewColors[0]]), thickness=-1)
405
+ annot11 = page2.add_polygon_annot( points=shapee) # 'Polygon'
406
+ annot11.set_border(width=0.2)
407
+ annot11.set_colors(stroke=(int(NewColors[0])/255,int(NewColors[1])/255,int(NewColors[2])/255), fill= (int(NewColors[0])/255,int(NewColors[1])/255,int(NewColors[2])/255) )
408
+ annot11.set_info(content='Area='+str(polygon[1])+' m^2',subject='ADR Team')
409
+ annot11.set_opacity(0.8)
410
+ # annot.set_line_ends(fitz.PDF_ANNOT_LE_DIAMOND, fitz.PDF_ANNOT_LE_CIRCLE)
411
+ annot11.update()
412
+
413
+
414
+
415
+ annot12 = page2.add_polygon_annot( points=shapee) # 'Polygon'
416
+ annot12.set_border(width=0.2)
417
+ annot12.set_colors(stroke=(int(NewColors[0])/255,int(NewColors[1])/255,int(NewColors[2])/255))
418
+ annot12.set_info(content='Perimeter='+str(polygon[2])+' m',subject='ADR Team')
419
+ annot12.set_opacity(0.8)
420
+ # annot.set_line_ends(fitz.PDF_ANNOT_LE_DIAMOND, fitz.PDF_ANNOT_LE_CIRCLE)
421
+ annot12.update()
422
+ i += 1
423
+ alpha = 0.8 # Transparency factor.
424
+
425
+ page2.set_rotation(rotationOld)
426
+ Correct_img=flip(imgg)
427
+
428
+ image_new1 = cv2.addWeighted(Correct_img, alpha, img, 1 - alpha, 0)
429
+ SimilarAreaDictionary = SimilarAreaDictionary.fillna(' ')
430
+ gc,spreadsheet_service,spreadsheetId, spreadsheet_url , namepathArr=google_sheet_Legend.legendGoogleSheets(SimilarAreaDictionary , pdfname,pdfpath)
431
+
432
+ return doc,image_new1, SimilarAreaDictionary ,spreadsheetId, spreadsheet_url , namepathArr
433
+