Marthee commited on
Commit
89d7ec0
·
verified ·
1 Parent(s): 4d219e8

Update dxf__omar3_2.py

Browse files
Files changed (1) hide show
  1. dxf__omar3_2.py +112 -77
dxf__omar3_2.py CHANGED
@@ -49,6 +49,9 @@ from PyPDF2.generic import NameObject, TextStringObject, DictionaryObject, Float
49
  from typing import NewType
50
  from ctypes import sizeof
51
 
 
 
 
52
  import numpy as np
53
  import cv2
54
  from matplotlib import pyplot as plt
@@ -75,6 +78,12 @@ import google_sheet_Legend
75
  from PyPDF2 import PdfReader
76
  from io import BytesIO
77
 
 
 
 
 
 
 
78
  """## Notes"""
79
 
80
  #new approach to get width and height of dxf plan
@@ -1130,10 +1139,32 @@ def Create_DF(dxfpath,datadoc,hatched_areas,pdf_content=0):
1130
  # print(SimilarAreaDictionary)
1131
  return SimilarAreaDictionary
1132
  """### Draw on Image and PDF"""
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1133
 
1134
  def adjustannotations(OutputPdfStage1,text_with_positions):
1135
  input_pdf_path = OutputPdfStage1
1136
  output_pdf_path = "Final-WallsAdjusted.pdf"
 
1137
 
1138
  # Load the input PDF
1139
  pdf_bytes_io = BytesIO(OutputPdfStage1)
@@ -1149,83 +1180,87 @@ def adjustannotations(OutputPdfStage1,text_with_positions):
1149
  writer.add_metadata(metadata)
1150
 
1151
  for page_index, page in enumerate(writer.pages):
1152
- if "/Annots" in page:
1153
- annotations = page["/Annots"]
1154
- for annot_index, annot in enumerate(annotations):
1155
- obj = annot.get_object()
1156
-
1157
- # print("obj", obj)
1158
- # print(obj.get("/IT"))
1159
-
1160
- if obj.get("/Subtype") == "/Line":
1161
- # print("AWL ANNOT IF")
1162
- # Check the /IT value to differentiate annotations
1163
- # if "/Contents" in obj and "m" in obj["/Contents"]:
1164
- if "/Subj" in obj and "Perimeter Measurement" in obj["/Subj"]:
1165
- # print("Tany IF")
1166
- obj.update({
1167
- NameObject("/Measure"): DictionaryObject({
1168
- NameObject("/Type"): NameObject("/Measure"),
1169
- NameObject("/L"): DictionaryObject({
1170
- NameObject("/G"): FloatObject(1),
1171
- NameObject("/U"): TextStringObject("m"), # Unit of measurement for area
1172
- }),
1173
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1174
  }),
1175
- NameObject("/IT"): NameObject("/LineDimension"), # Use more distinctive name
1176
- NameObject("/Subj"): TextStringObject("Length Measurement"), # Intent explicitly for Area
1177
- })
1178
- # print(obj)
1179
-
1180
- if obj.get("/Subtype") in ["/Line", "/PolyLine"] and "/C" in obj:
1181
- # Normalize and match the color
1182
- annot_color = normalize_color(obj["/C"])
1183
- matched_entry = next(
1184
- ((text, NBS) for text,NBS, _, color in text_with_positions if color_close_enough(annot_color, color)),
1185
- (None, None)
1186
- )
1187
- # print("matched_entry = ",matched_entry)
1188
- matched_text, matched_nbs = matched_entry
1189
-
1190
- combined_text = ""
1191
- if matched_text and matched_nbs:
1192
- combined_text = f"{matched_text} - {matched_nbs}"
1193
- elif matched_text:
1194
- combined_text = matched_text
1195
- elif matched_nbs:
1196
- combined_text = matched_nbs
1197
-
1198
- obj.update({
1199
- NameObject("/T"): TextStringObject(combined_text), # Custom text for "Comment" column
1200
- })
1201
-
1202
- elif (obj.get("/Subtype") == "/Polygon" and "/C" in obj):
1203
- # Normalize and match the color
1204
- annot_color = normalize_color(obj["/C"])
1205
- # print("annot_color = ",annot_color)
1206
- # print("LASTarray = ",text_with_positions)
1207
- # matched_entry = next(
1208
- # ((text, NBS) for text,NBS, _, color in text_with_positions if annot_color == color),
1209
- # (None, None)
1210
- # )
1211
- matched_entry = next(
1212
- ((text, NBS) for text,NBS, _, color in text_with_positions if color_close_enough(annot_color, color)),
1213
- (None, None)
1214
- )
1215
- # print("matched_entry = ",matched_entry)
1216
- matched_text, matched_nbs = matched_entry
1217
-
1218
- combined_text = ""
1219
- if matched_text and matched_nbs:
1220
- combined_text = f"{matched_text} - {matched_nbs}"
1221
- elif matched_text:
1222
- combined_text = matched_text
1223
- elif matched_nbs:
1224
- combined_text = matched_nbs
1225
-
1226
- obj.update({
1227
- NameObject("/T"): TextStringObject(combined_text), # Custom text for "Comment" column
1228
- })
1229
 
1230
 
1231
 
@@ -1234,7 +1269,7 @@ def adjustannotations(OutputPdfStage1,text_with_positions):
1234
  output_pdf_io.seek(0)
1235
 
1236
  print(f"Annotations updated and saved to {output_pdf_path}")
1237
- return output_pdf_io.read()
1238
 
1239
 
1240
 
@@ -1487,7 +1522,7 @@ def mainFunctionDrawImgPdf(datadoc,dxfpath, dxfratio,SearchArray,pdfpath=0,pdfna
1487
  # doc.save(OutputPdfStage1)
1488
  modified_pdf_data = doc.tobytes()
1489
  # OutputPdfStage2=adjustannotations(modified_pdf_data)
1490
- OutputPdfStage2=adjustannotations(modified_pdf_data,Legendarray)
1491
 
1492
 
1493
  # with open("Adjusted_PDF.pdf", "wb") as f:
 
49
  from typing import NewType
50
  from ctypes import sizeof
51
 
52
+ from PyPDF2 import PdfReader, PdfWriter
53
+ from PyPDF2.generic import NameObject, TextStringObject, FloatObject, DictionaryObject
54
+
55
  import numpy as np
56
  import cv2
57
  from matplotlib import pyplot as plt
 
78
  from PyPDF2 import PdfReader
79
  from io import BytesIO
80
 
81
+ from ezdxf.colors import aci2rgb
82
+ from collections import Counter
83
+
84
+ from math import isclose
85
+
86
+
87
  """## Notes"""
88
 
89
  #new approach to get width and height of dxf plan
 
1139
  # print(SimilarAreaDictionary)
1140
  return SimilarAreaDictionary
1141
  """### Draw on Image and PDF"""
1142
+ def color_close_enough(c1, c2, threshold=10):
1143
+ return all(abs(a - b) <= threshold for a, b in zip(c1, c2))
1144
+
1145
+
1146
+
1147
+ def group_vertices(raw):
1148
+ """Convert flat list [x1,y1,x2,y2,...] into [[x1,y1],[x2,y2],...]"""
1149
+ if not raw or len(raw) < 2:
1150
+ return []
1151
+ return [[raw[i], raw[i+1]] for i in range(0, len(raw), 2)]
1152
+
1153
+
1154
+ def extract_measurement(obj):
1155
+ """Extract numeric measurement from annotation's /Contents field."""
1156
+ contents = obj.get("/Contents")
1157
+ if not contents:
1158
+ return None
1159
+ # Find first numeric occurrence
1160
+ text = str(contents)
1161
+ m = re.search(r"([0-9]*\.?[0-9]+)", text)
1162
+ return float(m.group(1)) if m else None
1163
 
1164
  def adjustannotations(OutputPdfStage1,text_with_positions):
1165
  input_pdf_path = OutputPdfStage1
1166
  output_pdf_path = "Final-WallsAdjusted.pdf"
1167
+ annotations_data = []
1168
 
1169
  # Load the input PDF
1170
  pdf_bytes_io = BytesIO(OutputPdfStage1)
 
1180
  writer.add_metadata(metadata)
1181
 
1182
  for page_index, page in enumerate(writer.pages):
1183
+ if "/Annots" not in page:
1184
+ continue
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1185
 
1186
+ for annot in page["/Annots"]:
1187
+ obj = annot.get_object()
1188
+ subtype = obj.get("/Subtype")
1189
+
1190
+ # Group vertices for metadata
1191
+ if subtype == "/Line":
1192
+ raw_vertices = obj.get("/L", [])
1193
+ else:
1194
+ raw_vertices = obj.get("/Vertices", [])
1195
+ vertices = group_vertices(raw_vertices)
1196
+
1197
+ # Normalize color
1198
+ raw_color = obj.get("/C")
1199
+ try:
1200
+ annot_color = normalize_color(raw_color)
1201
+ except:
1202
+ annot_color = raw_color
1203
+
1204
+ # Extract measurement from annotation content
1205
+ measurement = extract_measurement(obj)
1206
+ # Assign to area or perimeter based on subtype
1207
+ area = measurement if subtype == "/Polygon" else None
1208
+ perimeter = measurement if subtype in ["/Line", "/PolyLine"] else None
1209
+
1210
+ # Match text and NBS
1211
+ matched_text = None
1212
+ matched_nbs = None
1213
+ if subtype in ["/Line", "/PolyLine", "/Polygon"] and raw_color:
1214
+ matched_entry = next(
1215
+ ((t, n) for t, n, _, c in text_with_positions if color_close_enough(annot_color, c)),
1216
+ (None, None)
1217
+ )
1218
+ matched_text, matched_nbs = matched_entry
1219
+ combined = ""
1220
+ if matched_text and matched_nbs:
1221
+ combined = f"{matched_text} - {matched_nbs}"
1222
+ elif matched_text:
1223
+ combined = matched_text
1224
+ elif matched_nbs:
1225
+ combined = matched_nbs
1226
+ if combined:
1227
+ obj.update({NameObject("/T"): TextStringObject(combined)})
1228
+
1229
+ # Update annotation dictionaries for measurement type
1230
+ if subtype == "/Line" and obj.get("/Subj", "") == "Perimeter Measurement":
1231
+ obj.update({
1232
+ NameObject("/Measure"): DictionaryObject({
1233
+ NameObject("/Type"): NameObject("/Measure"),
1234
+ NameObject("/L"): DictionaryObject({
1235
+ NameObject("/G"): FloatObject(1),
1236
+ NameObject("/U"): TextStringObject("m"),
1237
  }),
1238
+ }),
1239
+ NameObject("/IT"): NameObject("/LineDimension"),
1240
+ NameObject("/Subj"): TextStringObject("Length Measurement"),
1241
+ })
1242
+ if subtype == "/Polygon" and obj.get("/Subj", "") == "Area Measurement":
1243
+ obj.update({
1244
+ NameObject("/Measure"): DictionaryObject({
1245
+ NameObject("/Type"): NameObject("/Measure"),
1246
+ NameObject("/Area"): DictionaryObject({
1247
+ NameObject("/G"): FloatObject(1),
1248
+ NameObject("/U"): TextStringObject("sq m"),
1249
+ }),
1250
+ }),
1251
+ NameObject("/IT"): NameObject("/Area_Annotation"),
1252
+ NameObject("/Subj"): TextStringObject("Area Measurement"),
1253
+ })
1254
+
1255
+ # Append metadata
1256
+ annotations_data.append([
1257
+ vertices,
1258
+ area,
1259
+ perimeter,
1260
+ annot_color,
1261
+ matched_text,
1262
+ matched_nbs,
1263
+ ])
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1264
 
1265
 
1266
 
 
1269
  output_pdf_io.seek(0)
1270
 
1271
  print(f"Annotations updated and saved to {output_pdf_path}")
1272
+ return output_pdf_io.read() , annotations_data
1273
 
1274
 
1275
 
 
1522
  # doc.save(OutputPdfStage1)
1523
  modified_pdf_data = doc.tobytes()
1524
  # OutputPdfStage2=adjustannotations(modified_pdf_data)
1525
+ OutputPdfStage2,annotations_data=adjustannotations(modified_pdf_data,Legendarray)
1526
 
1527
 
1528
  # with open("Adjusted_PDF.pdf", "wb") as f: