UsmanGoraya commited on
Commit
1d9fbff
·
verified ·
1 Parent(s): 57eeaa0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +34 -29
app.py CHANGED
@@ -2,6 +2,7 @@ import streamlit as st
2
  import ezdxf
3
  import io
4
  import pandas as pd
 
5
  from fpdf import FPDF
6
  from tempfile import NamedTemporaryFile
7
 
@@ -16,21 +17,20 @@ DEFAULT_WALL_THICKNESS = 0.75
16
  st.set_page_config(page_title="Building Estimator from CAD", layout="wide")
17
  st.title("🏗️ Auto Estimation from AutoCAD (.dxf) Drawing")
18
 
19
- # Upload DXF file
20
  uploaded_file = st.file_uploader("Upload your DXF file", type=["dxf"])
21
 
22
  @st.cache_data
23
  def extract_geometry(file_bytes):
24
- # Wrap file in text buffer and read as ASCII
25
  try:
26
  text_buffer = io.TextIOWrapper(file_bytes, encoding='utf-8', errors='ignore')
27
  doc = ezdxf.read(text_buffer)
28
  except Exception as e:
29
  st.error(f"Error reading DXF file: {e}")
30
- return [], 0.75, [], 1
31
 
32
  msp = doc.modelspace()
33
  rooms = []
 
34
  openings = []
35
  floors = 1
36
  wall_thickness = DEFAULT_WALL_THICKNESS
@@ -54,25 +54,21 @@ def extract_geometry(file_bytes):
54
  points = entity.get_points()
55
  x_vals = [p[0] for p in points]
56
  y_vals = [p[1] for p in points]
57
- length = abs(max(x_vals) - min(x_vals)) / 12 # inches to ft
58
  width = abs(max(y_vals) - min(y_vals)) / 12
59
- height = 10 # default wall height in ft
60
- if length > 2 and width > 2: # Room
61
  rooms.append((length, width, height))
 
62
  else:
63
  openings.append(("opening", length, height))
64
- return rooms, wall_thickness, openings, floors
65
 
66
- def estimate(rooms, wall_thickness, openings, floors):
67
- wall_volume = 0
68
- for length, width, height in rooms:
69
- wall_area = 2 * (length + width) * height
70
- wall_volume += wall_area * wall_thickness
71
 
 
 
72
  opening_volume = sum(l * h * wall_thickness for _, l, h in openings)
73
-
74
  beam_volume = sum((l + 1) * 0.75 * 0.75 for _, l, _ in openings)
75
-
76
  net_volume = (wall_volume - opening_volume - beam_volume) * floors
77
 
78
  number_of_bricks = round((net_volume / BRICK_VOLUME_CFT) * 1.05)
@@ -90,43 +86,51 @@ def generate_pdf(data_dict):
90
  pdf.set_font("Arial", size=12)
91
  pdf.cell(200, 10, "Estimation Report", ln=True, align='C')
92
  pdf.ln(10)
93
-
94
  for key, value in data_dict.items():
95
  pdf.cell(200, 10, f"{key}: {value}", ln=True)
96
-
97
  tmp = NamedTemporaryFile(delete=False, suffix=".pdf")
98
  pdf.output(tmp.name)
99
  return tmp.name
100
 
 
 
 
 
 
 
 
 
 
 
 
 
101
  if uploaded_file:
102
  file_bytes = io.BytesIO(uploaded_file.read())
103
- rooms, wall_thickness, openings, floors = extract_geometry(file_bytes)
104
 
105
  st.success(f"✔️ Parsed {len(rooms)} rooms and {len(openings)} openings across {floors} floor(s).")
106
  st.write(f"📏 Wall Thickness: {wall_thickness} ft")
107
 
108
  bricks, sand, cement = estimate(rooms, wall_thickness, openings, floors)
109
 
110
- st.subheader("📊 Estimation Result")
111
- st.write(f"🧱 **Bricks Required:** {bricks:,}")
112
- st.write(f"🏖️ **Sand Volume:** {sand:.2f} cft")
113
- st.write(f"🪣 **Cement Bags:** {cement} (50kg each)")
114
 
115
- # Table
116
- df = pd.DataFrame({
117
  "Item": ["Bricks", "Sand (cft)", "Cement (bags)"],
118
  "Quantity": [bricks, round(sand, 2), cement]
119
  })
 
120
 
121
- st.dataframe(df)
 
122
 
123
- # Export
124
  st.subheader("📤 Export")
125
  col1, col2 = st.columns(2)
126
-
127
  with col1:
128
- st.download_button("📥 Download as Excel", df.to_csv(index=False).encode(), "estimates.csv", "text/csv")
129
-
130
  with col2:
131
  pdf_file = generate_pdf({
132
  "Bricks Required": f"{bricks:,}",
@@ -134,6 +138,7 @@ if uploaded_file:
134
  "Cement Bags": f"{cement} bags"
135
  })
136
  with open(pdf_file, "rb") as f:
137
- st.download_button("📄 Download as PDF", f.read(), "estimates.pdf", "application/pdf")
 
138
 
139
 
 
2
  import ezdxf
3
  import io
4
  import pandas as pd
5
+ import matplotlib.pyplot as plt
6
  from fpdf import FPDF
7
  from tempfile import NamedTemporaryFile
8
 
 
17
  st.set_page_config(page_title="Building Estimator from CAD", layout="wide")
18
  st.title("🏗️ Auto Estimation from AutoCAD (.dxf) Drawing")
19
 
 
20
  uploaded_file = st.file_uploader("Upload your DXF file", type=["dxf"])
21
 
22
  @st.cache_data
23
  def extract_geometry(file_bytes):
 
24
  try:
25
  text_buffer = io.TextIOWrapper(file_bytes, encoding='utf-8', errors='ignore')
26
  doc = ezdxf.read(text_buffer)
27
  except Exception as e:
28
  st.error(f"Error reading DXF file: {e}")
29
+ return [], 0.75, [], 1, []
30
 
31
  msp = doc.modelspace()
32
  rooms = []
33
+ room_shapes = []
34
  openings = []
35
  floors = 1
36
  wall_thickness = DEFAULT_WALL_THICKNESS
 
54
  points = entity.get_points()
55
  x_vals = [p[0] for p in points]
56
  y_vals = [p[1] for p in points]
57
+ length = abs(max(x_vals) - min(x_vals)) / 12
58
  width = abs(max(y_vals) - min(y_vals)) / 12
59
+ height = 10
60
+ if length > 2 and width > 2:
61
  rooms.append((length, width, height))
62
+ room_shapes.append((min(x_vals), min(y_vals), max(x_vals), max(y_vals)))
63
  else:
64
  openings.append(("opening", length, height))
 
65
 
66
+ return rooms, wall_thickness, openings, floors, room_shapes
 
 
 
 
67
 
68
+ def estimate(rooms, wall_thickness, openings, floors):
69
+ wall_volume = sum(2 * (l + w) * h * wall_thickness for l, w, h in rooms)
70
  opening_volume = sum(l * h * wall_thickness for _, l, h in openings)
 
71
  beam_volume = sum((l + 1) * 0.75 * 0.75 for _, l, _ in openings)
 
72
  net_volume = (wall_volume - opening_volume - beam_volume) * floors
73
 
74
  number_of_bricks = round((net_volume / BRICK_VOLUME_CFT) * 1.05)
 
86
  pdf.set_font("Arial", size=12)
87
  pdf.cell(200, 10, "Estimation Report", ln=True, align='C')
88
  pdf.ln(10)
 
89
  for key, value in data_dict.items():
90
  pdf.cell(200, 10, f"{key}: {value}", ln=True)
 
91
  tmp = NamedTemporaryFile(delete=False, suffix=".pdf")
92
  pdf.output(tmp.name)
93
  return tmp.name
94
 
95
+ def plot_rooms(shapes):
96
+ fig, ax = plt.subplots()
97
+ for x0, y0, x1, y1 in shapes:
98
+ width = (x1 - x0)
99
+ height = (y1 - y0)
100
+ rect = plt.Rectangle((x0, y0), width, height, fill=False, edgecolor='blue', linewidth=2)
101
+ ax.add_patch(rect)
102
+ ax.set_title("🧭 2D Floor Plan")
103
+ ax.set_aspect("equal")
104
+ ax.axis("off")
105
+ st.pyplot(fig)
106
+
107
  if uploaded_file:
108
  file_bytes = io.BytesIO(uploaded_file.read())
109
+ rooms, wall_thickness, openings, floors, room_shapes = extract_geometry(file_bytes)
110
 
111
  st.success(f"✔️ Parsed {len(rooms)} rooms and {len(openings)} openings across {floors} floor(s).")
112
  st.write(f"📏 Wall Thickness: {wall_thickness} ft")
113
 
114
  bricks, sand, cement = estimate(rooms, wall_thickness, openings, floors)
115
 
116
+ st.subheader("📐 Room Dimensions")
117
+ df_rooms = pd.DataFrame(rooms, columns=["Length (ft)", "Width (ft)", "Height (ft)"])
118
+ st.dataframe(df_rooms)
 
119
 
120
+ st.subheader("🧱 Estimation Result")
121
+ df_result = pd.DataFrame({
122
  "Item": ["Bricks", "Sand (cft)", "Cement (bags)"],
123
  "Quantity": [bricks, round(sand, 2), cement]
124
  })
125
+ st.dataframe(df_result)
126
 
127
+ st.subheader("🖼️ 2D Floor Plan")
128
+ plot_rooms(room_shapes)
129
 
 
130
  st.subheader("📤 Export")
131
  col1, col2 = st.columns(2)
 
132
  with col1:
133
+ st.download_button("⬇️ Download Excel", df_result.to_csv(index=False).encode(), "estimates.csv", "text/csv")
 
134
  with col2:
135
  pdf_file = generate_pdf({
136
  "Bricks Required": f"{bricks:,}",
 
138
  "Cement Bags": f"{cement} bags"
139
  })
140
  with open(pdf_file, "rb") as f:
141
+ st.download_button("⬇️ Download PDF", f.read(), "estimates.pdf", "application/pdf")
142
+
143
 
144