buildinves commited on
Commit
e6e3a8d
·
verified ·
1 Parent(s): a8cf587

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +114 -211
app.py CHANGED
@@ -31,17 +31,6 @@ class AdvancedGridOptimizer:
31
  16.8: {"depths": [30, 32], "type": "Corner-Premium", "squares": "26-32"}
32
  }
33
 
34
- # Rescode setback requirements
35
- self.setback_rules = {
36
- 'front': 6.0, # 6m front setback
37
- 'rear': 6.0, # 6m rear setback
38
- 'side': 1.0, # 1m side setback (single story)
39
- 'side_2story': 1.5, # 1.5m side setback (two story)
40
- 'corner_secondary': 3.0, # 3m setback on secondary street for corners
41
- 'garage_front': 5.5, # 5.5m garage setback from front
42
- 'alfresco_rear': 3.0 # 3m minimum for alfresco area
43
- }
44
-
45
  self.slhc_widths = [8.5, 10.5]
46
  self.standard_widths = [12.5, 14.0]
47
  self.premium_widths = [16.0, 18.0]
@@ -50,53 +39,53 @@ class AdvancedGridOptimizer:
50
  # Define corner_widths as all widths suitable for corners
51
  self.corner_widths = self.corner_specific + [14.0, 16.0, 18.0]
52
 
53
- # Enhanced color palette with gradients
54
  self.color_schemes = {
55
- 'modern': {
56
- 8.5: '#FF6B6B', # Vibrant Red
57
- 10.5: '#4ECDC4', # Teal
58
- 12.5: '#45B7D1', # Sky Blue
59
- 14.0: '#96CEB4', # Sage Green
60
- 16.0: '#DDA0DD', # Lavender
61
- 18.0: '#FFD93D', # Golden
62
- 11.0: '#FFA07A', # Coral
63
- 13.3: '#98D8C8', # Mint
64
- 14.8: '#F7DC6F', # Butter
65
- 16.8: '#BB8FCE' # Orchid
66
  },
67
- 'professional': {
68
- 8.5: '#E74C3C', # Professional Red
69
- 10.5: '#3498DB', # Professional Blue
70
- 12.5: '#2ECC71', # Professional Green
71
- 14.0: '#F39C12', # Professional Orange
72
- 16.0: '#9B59B6', # Professional Purple
73
- 18.0: '#1ABC9C', # Professional Turquoise
74
- 11.0: '#E67E22', # Professional Dark Orange
75
- 13.3: '#16A085', # Professional Teal
76
- 14.8: '#F1C40F', # Professional Yellow
77
- 16.8: '#8E44AD' # Professional Dark Purple
78
  },
79
- 'neon': {
80
- 8.5: '#FF073A', # Neon Red
81
- 10.5: '#0AEFFF', # Neon Cyan
82
- 12.5: '#39FF14', # Neon Green
83
- 14.0: '#FF6600', # Neon Orange
84
- 16.0: '#BF00FF', # Neon Purple
85
- 18.0: '#FFFF00', # Neon Yellow
86
- 11.0: '#FF1493', # Neon Pink
87
- 13.3: '#00FFFF', # Neon Aqua
88
- 14.8: '#FFF700', # Bright Yellow
89
- 16.8: '#FF00FF' # Neon Magenta
90
  }
91
  }
92
 
93
- self.current_scheme = 'neon'
94
  self.current_solution = None # Store current AI solution
95
 
96
- def create_enhanced_visualization(self, solution, stage_width, stage_depth=32, title="Premium Grid Layout", show_variance=None, show_setbacks=True):
97
- """Create a clean 2D visualization with corner splays and buildable boundaries"""
98
  fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(18, 12), gridspec_kw={'height_ratios': [3, 1]},
99
- facecolor='#1a1a1a')
100
 
101
  # Main visualization
102
  colors = self.color_schemes[self.current_scheme]
@@ -104,28 +93,28 @@ class AdvancedGridOptimizer:
104
  x_pos = 0
105
  lot_num = 1
106
 
107
- # Set up main plot with dark background
108
  ax1.set_xlim(-5, stage_width + 5)
109
  ax1.set_ylim(-10, 50)
110
- ax1.set_facecolor('#1a1a1a')
111
 
112
  # Add title with variance if provided
113
  if show_variance is not None:
114
- variance_color = '#39FF14' if abs(show_variance) < 0.001 else '#FF073A'
115
  title_text = f"{title}\nGrid Variance: {show_variance:+.1f}m"
116
  ax1.set_title(title_text, fontsize=28, fontweight='bold', pad=25, color='white')
117
  else:
118
  ax1.set_title(title, fontsize=28, fontweight='bold', pad=25, color='white')
119
 
120
- # Add subtle dark gradient background
121
- gradient = np.linspace(0.2, 0, 100).reshape(1, -1)
122
  ax1.imshow(gradient, extent=[-5, stage_width + 5, -10, 50], aspect='auto',
123
  cmap='Greys', alpha=0.3, zorder=0)
124
 
125
  # Add street with label
126
  street = Rectangle((-5, -8), stage_width + 10, 12,
127
- facecolor='#2c2c2c', alpha=0.9, zorder=1,
128
- edgecolor='#444444', linewidth=2)
129
  ax1.add_patch(street)
130
  ax1.text(stage_width/2, -2, 'STREET', ha='center', va='center',
131
  fontsize=20, color='white', fontweight='bold')
@@ -134,9 +123,6 @@ class AdvancedGridOptimizer:
134
  splay_size = 3 # 3m corner splay
135
  lot_height = 28 # UNIFORM HEIGHT FOR ALL LOTS
136
 
137
- # Track maximum buildable area info
138
- max_buildable_areas = []
139
-
140
  for i, (width, lot_type) in enumerate(solution):
141
  # Get base color
142
  if width in colors:
@@ -208,63 +194,6 @@ class AdvancedGridOptimizer:
208
  zorder=2)
209
  ax1.add_patch(glow)
210
 
211
- # Add buildable boundaries if enabled
212
- if show_setbacks:
213
- # Determine if lot likely has 2 stories
214
- two_story = width > 14 # Premium lots likely 2 story
215
- side_setback = self.setback_rules['side_2story'] if two_story else self.setback_rules['side']
216
-
217
- if is_corner:
218
- # Corner lot buildable area
219
- if i == 0: # First corner
220
- buildable_x = x_pos + max(splay_size + self.setback_rules['corner_secondary'], side_setback)
221
- buildable_y = 8 + self.setback_rules['front']
222
- buildable_width = width - max(splay_size + self.setback_rules['corner_secondary'], side_setback) - side_setback
223
- buildable_height = lot_height - self.setback_rules['front'] - self.setback_rules['rear']
224
- else: # Last corner
225
- buildable_x = x_pos + side_setback
226
- buildable_y = 8 + self.setback_rules['front']
227
- buildable_width = width - side_setback - max(splay_size + self.setback_rules['corner_secondary'], side_setback)
228
- buildable_height = lot_height - self.setback_rules['front'] - self.setback_rules['rear']
229
- else:
230
- # Regular lot buildable area
231
- buildable_x = x_pos + side_setback
232
- buildable_y = 8 + self.setback_rules['front']
233
- buildable_width = width - 2 * side_setback
234
- buildable_height = lot_height - self.setback_rules['front'] - self.setback_rules['rear']
235
-
236
- # Draw buildable boundary with dotted lines
237
- buildable_rect = Rectangle(
238
- (buildable_x, buildable_y),
239
- buildable_width,
240
- buildable_height,
241
- fill=False,
242
- edgecolor='white',
243
- linewidth=1.5,
244
- linestyle='--',
245
- alpha=0.7,
246
- zorder=4
247
- )
248
- ax1.add_patch(buildable_rect)
249
-
250
- # Add small label for max house size
251
- max_house_area = buildable_width * buildable_height
252
- max_buildable_areas.append(max_house_area)
253
-
254
- # Show dimensions on hover-like annotation
255
- ax1.text(buildable_x + buildable_width/2, buildable_y + buildable_height/2,
256
- f'{buildable_width:.1f}×{buildable_height:.1f}m\n({max_house_area:.0f}m²)',
257
- ha='center', va='center', fontsize=8, color='white', alpha=0.5,
258
- bbox=dict(boxstyle="round,pad=0.2", facecolor='black', alpha=0.5))
259
-
260
- # Add setback dimension indicators
261
- # Front setback
262
- ax1.plot([x_pos + width*0.1, x_pos + width*0.1], [8, buildable_y],
263
- 'gray', linewidth=0.5, alpha=0.3)
264
- ax1.text(x_pos + width*0.1, 8 + self.setback_rules['front']/2,
265
- f"{self.setback_rules['front']}m",
266
- ha='right', va='center', fontsize=6, color='gray', alpha=0.5)
267
-
268
  # Add rear alignment line to emphasize equal depth
269
  rear_y = 8 + lot_height
270
  ax1.plot([x_pos, x_pos + width], [rear_y, rear_y],
@@ -294,7 +223,7 @@ class AdvancedGridOptimizer:
294
 
295
  ax1.text(x_pos + width/2, 23, lot_type_text,
296
  ha='center', va='center', fontsize=11,
297
- bbox=dict(boxstyle="round,pad=0.3", facecolor='#333333',
298
  edgecolor='white', alpha=0.9), color='white')
299
 
300
  # Dimension lines
@@ -307,26 +236,11 @@ class AdvancedGridOptimizer:
307
 
308
  # Add rear alignment line across all lots
309
  ax1.plot([0, stage_width], [8 + lot_height, 8 + lot_height],
310
- 'cyan', linewidth=2, alpha=0.8, linestyle='-')
311
  ax1.text(stage_width/2, 8 + lot_height + 1, 'REAR ALIGNMENT LINE',
312
- ha='center', va='bottom', fontsize=12, color='cyan', alpha=0.8,
313
- bbox=dict(boxstyle="round,pad=0.3", facecolor='#1a1a1a',
314
- edgecolor='cyan', alpha=0.8))
315
-
316
- # Add setback legend
317
- if show_setbacks:
318
- legend_text = (
319
- "SETBACK REQUIREMENTS:\n"
320
- f"Front: {self.setback_rules['front']}m | Rear: {self.setback_rules['rear']}m\n"
321
- f"Side (1 story): {self.setback_rules['side']}m | Side (2 story): {self.setback_rules['side_2story']}m\n"
322
- f"Corner secondary street: {self.setback_rules['corner_secondary']}m"
323
- )
324
- ax1.text(0.02, 0.98, legend_text,
325
- transform=ax1.transAxes,
326
- fontsize=10, color='white', alpha=0.7,
327
- bbox=dict(boxstyle="round,pad=0.5", facecolor='#2a2a2a',
328
- edgecolor='white', alpha=0.7),
329
- verticalalignment='top')
330
 
331
  # Add stage dimensions
332
  arrow_props = dict(arrowstyle='<->', color='white', lw=3)
@@ -342,7 +256,7 @@ class AdvancedGridOptimizer:
342
 
343
  # Metrics panel
344
  ax2.axis('off')
345
- ax2.set_facecolor('#1a1a1a')
346
 
347
  # Calculate metrics with diversity score
348
  total_lots = len(solution)
@@ -364,21 +278,11 @@ class AdvancedGridOptimizer:
364
  variance = total_width - stage_width
365
  efficiency = "100%" if abs(variance) < 0.001 else f"{(total_width/stage_width)*100:.1f}%"
366
 
367
- # Calculate buildable area stats
368
- if max_buildable_areas:
369
- avg_buildable = np.mean(max_buildable_areas)
370
- min_buildable = min(max_buildable_areas)
371
- max_buildable = max(max_buildable_areas)
372
- buildable_stats = f"Buildable: {min_buildable:.0f}-{max_buildable:.0f}m² (avg: {avg_buildable:.0f}m²)"
373
- else:
374
- buildable_stats = "Buildable area calculation pending"
375
-
376
  metrics_lines = [
377
  f"📊 TOTAL LOTS: {total_lots}",
378
  f"📐 LAND EFFICIENCY: {efficiency}",
379
  f"🎯 DIVERSITY: {diversity_score:.0%} ({unique_widths} types)",
380
  f"📏 GRID VARIANCE: {variance:+.2f}m",
381
- f"🏠 {buildable_stats}",
382
  "",
383
  f"SLHC (≤10.5m): {slhc_count} lots",
384
  f"Standard (11-14m): {standard_count} lots",
@@ -388,20 +292,20 @@ class AdvancedGridOptimizer:
388
  f"💰 Revenue: ${total_lots * 0.5:.1f}M - ${total_lots * 1.2:.1f}M"
389
  ]
390
 
391
- col1_text = '\n'.join(metrics_lines[:6])
392
- col2_text = '\n'.join(metrics_lines[6:])
393
 
394
  ax2.text(0.05, 0.5, col1_text, transform=ax2.transAxes,
395
  fontsize=14, verticalalignment='center', fontweight='bold',
396
  color='white',
397
- bbox=dict(boxstyle="round,pad=0.5", facecolor='#2a2a2a',
398
- edgecolor='#444444', alpha=0.8))
399
 
400
  ax2.text(0.55, 0.5, col2_text, transform=ax2.transAxes,
401
  fontsize=14, verticalalignment='center', fontweight='bold',
402
  color='white',
403
- bbox=dict(boxstyle="round,pad=0.5", facecolor='#2a2a2a',
404
- edgecolor='#444444', alpha=0.8))
405
 
406
  plt.tight_layout()
407
  return fig
@@ -1007,7 +911,6 @@ class AdvancedGridOptimizer:
1007
  report += f"- All lots have identical rear alignment for visual consistency\n"
1008
  report += f"- Diverse lot mix ensures varied streetscape\n"
1009
  report += f"- SLHC lots grouped for efficient garbage collection\n"
1010
- report += f"- Buildable areas shown with rescode-compliant setbacks\n"
1011
 
1012
  report += f"\n---\n*Report generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*"
1013
 
@@ -1031,7 +934,7 @@ def create_advanced_app():
1031
  stage_depth,
1032
  enable_8_5, enable_10_5, enable_12_5, enable_14, enable_16, enable_18,
1033
  enable_corners, enable_11, enable_13_3, enable_14_8, enable_16_8,
1034
- allow_custom_corners, optimization_strategy, color_scheme, show_setbacks
1035
  ):
1036
  # Update color scheme
1037
  optimizer.current_scheme = color_scheme
@@ -1054,15 +957,10 @@ def create_advanced_app():
1054
  if not enabled_widths:
1055
  return None, None, pd.DataFrame(), "Please select at least one lot width!", "", ""
1056
 
1057
- # Run optimization based on strategy
1058
- if optimization_strategy == "diversity_focus":
1059
- optimized_solution = optimizer.optimize_with_flexible_corners(
1060
- stage_width, enabled_widths, allow_custom_corners
1061
- )
1062
- else: # balanced approach
1063
- optimized_solution = optimizer.optimize_with_corners_diverse(
1064
- stage_width, enabled_widths, None
1065
- )
1066
 
1067
  # Store current solution for manual adjustment
1068
  optimizer.current_solution = optimized_solution
@@ -1089,12 +987,11 @@ def create_advanced_app():
1089
  3. Try common stage widths: 84m, 105m, 126m
1090
  """, "", ""
1091
 
1092
- # Create visualizations with variance indicator and setbacks
1093
  fig_2d = optimizer.create_enhanced_visualization(
1094
  optimized_solution, stage_width, stage_depth,
1095
- "AI-Optimized Diverse Subdivision Layout",
1096
- show_variance=variance,
1097
- show_setbacks=show_setbacks
1098
  )
1099
 
1100
  # Create results table
@@ -1175,7 +1072,7 @@ def create_advanced_app():
1175
 
1176
  return fig_2d, results_df, summary, report, manual_edit_string
1177
 
1178
- def update_manual_adjustment(manual_widths_text, stage_width, stage_depth, color_scheme, show_setbacks):
1179
  """Update visualization based on manual adjustment"""
1180
  optimizer.current_scheme = color_scheme
1181
 
@@ -1199,53 +1096,65 @@ def create_advanced_app():
1199
  fig = optimizer.create_enhanced_visualization(
1200
  solution, stage_width, stage_depth,
1201
  "Manually Adjusted Layout",
1202
- show_variance=variance,
1203
- show_setbacks=show_setbacks
1204
  )
1205
 
1206
  return fig, feedback
1207
 
1208
  # Create Gradio interface
1209
  with gr.Blocks(
1210
- title="Advanced AI Grid Optimizer",
1211
  theme=gr.themes.Base(),
1212
  css="""
1213
  .gradio-container {
1214
- font-family: 'Segoe UI', sans-serif;
1215
- background: #1a1a1a;
1216
  color: white;
1217
  }
1218
  .gr-button-primary {
1219
- background: linear-gradient(45deg, #FF073A 30%, #0AEFFF 90%);
1220
  border: none;
1221
- box-shadow: 0 3px 5px 2px rgba(255, 7, 58, .3);
 
 
 
1222
  }
1223
  h1 {
1224
- background: linear-gradient(45deg, #FF073A, #0AEFFF);
1225
- -webkit-background-clip: text;
1226
- -webkit-text-fill-color: transparent;
1227
  text-align: center;
1228
  font-size: 2.5em;
 
 
 
 
1229
  }
1230
  .gr-form {
1231
- background: rgba(42, 42, 42, 0.9);
1232
  border-radius: 10px;
1233
  padding: 20px;
1234
- border: 1px solid #444;
1235
  }
1236
  .gr-input {
1237
- background-color: #2a2a2a;
1238
  color: white;
1239
- border: 1px solid #444;
1240
  }
1241
  .gr-check-radio {
1242
- background-color: #2a2a2a;
 
 
 
 
 
 
1243
  }
1244
  """
1245
  ) as demo:
1246
  gr.Markdown("""
1247
- # 🏗️ Advanced AI Grid Cut Optimizer Pro
1248
- ### AI-Powered Subdivision Planning with Buildable Boundaries
 
 
1249
  """)
1250
 
1251
  with gr.Row():
@@ -1290,7 +1199,7 @@ def create_advanced_app():
1290
  enable_16_8 = gr.Checkbox(label="16.8m", value=True)
1291
 
1292
  with gr.Column(scale=1):
1293
- gr.Markdown("### ⚙️ Advanced Settings")
1294
 
1295
  allow_custom_corners = gr.Checkbox(
1296
  label="🎯 Allow Flexible Corner Widths",
@@ -1298,28 +1207,15 @@ def create_advanced_app():
1298
  info="Enables 13.8m, 13.9m etc. for perfect fits"
1299
  )
1300
 
1301
- show_setbacks = gr.Checkbox(
1302
- label="🏠 Show Buildable Boundaries",
1303
- value=True,
1304
- info="Display maximum house envelope with rescode setbacks"
1305
- )
1306
-
1307
- optimization_strategy = gr.Radio(
1308
- ["diversity_focus", "balanced"],
1309
- label="Optimization Strategy",
1310
- value="diversity_focus",
1311
- info="Diversity creates more interesting layouts"
1312
- )
1313
-
1314
  color_scheme = gr.Radio(
1315
- ["modern", "professional", "neon"],
1316
  label="🎨 Color Scheme",
1317
- value="neon",
1318
- info="Neon colors work best with dark background"
1319
  )
1320
 
1321
  optimize_btn = gr.Button(
1322
- "🚀 Optimize with AI",
1323
  variant="primary",
1324
  size="lg",
1325
  elem_id="optimize-button"
@@ -1327,17 +1223,17 @@ def create_advanced_app():
1327
 
1328
  gr.Markdown("""
1329
  ### 💡 Quick Tips:
1330
- - **Buildable Areas**: Dotted lines show max house size
1331
- - **Setbacks**: Front/Rear: 6m, Side: 1m (1.5m for 2-story)
1332
- - **Corner Lots**: Extra 3m setback on secondary street
1333
  - **Manual Adjust**: Edit the result below after optimization
 
1334
  """)
1335
 
1336
  with gr.Row():
1337
- plot_2d = gr.Plot(label="2D Layout with Buildable Boundaries")
1338
 
1339
  # Manual adjustment section
1340
- gr.Markdown("### ✏️ Fine-Tune AI Result")
1341
  with gr.Row():
1342
  with gr.Column(scale=2):
1343
  manual_widths = gr.Textbox(
@@ -1370,19 +1266,26 @@ def create_advanced_app():
1370
  stage_depth,
1371
  enable_8_5, enable_10_5, enable_12_5, enable_14, enable_16, enable_18,
1372
  enable_corners, enable_11, enable_13_3, enable_14_8, enable_16_8,
1373
- allow_custom_corners, optimization_strategy, color_scheme, show_setbacks
1374
  ],
1375
  outputs=[plot_2d, results_table, summary_output, report_output, manual_widths]
1376
  )
1377
 
1378
  update_btn.click(
1379
  update_manual_adjustment,
1380
- inputs=[manual_widths, stage_width, stage_depth, color_scheme, show_setbacks],
1381
  outputs=[plot_2d, adjustment_feedback]
1382
  )
1383
 
1384
  return demo
1385
 
 
 
 
 
 
 
 
1386
  # Create and launch
1387
  if __name__ == "__main__":
1388
  app = create_advanced_app()
 
31
  16.8: {"depths": [30, 32], "type": "Corner-Premium", "squares": "26-32"}
32
  }
33
 
 
 
 
 
 
 
 
 
 
 
 
34
  self.slhc_widths = [8.5, 10.5]
35
  self.standard_widths = [12.5, 14.0]
36
  self.premium_widths = [16.0, 18.0]
 
39
  # Define corner_widths as all widths suitable for corners
40
  self.corner_widths = self.corner_specific + [14.0, 16.0, 18.0]
41
 
42
+ # Enhanced color palette with RPM brand colors
43
  self.color_schemes = {
44
+ 'rpm_primary': {
45
+ 8.5: '#802B2B', # Burgundy for SLHC
46
+ 10.5: '#AB3838', # Burgundy 75%
47
+ 12.5: '#216767', # Teal
48
+ 14.0: '#2E3E2F', # RPM Green (hero color)
49
+ 16.0: '#415B6E', # Blue
50
+ 18.0: '#FF8E3C', # Yellow
51
+ 11.0: '#4F8585', # Teal 75%
52
+ 13.3: '#545D51', # RPM Green 75%
53
+ 14.8: '#697687', # Blue 75%
54
+ 16.8: '#FFCF6D' # Yellow 75%
55
  },
56
+ 'rpm_contrast': {
57
+ 8.5: '#D69C9C', # Burgundy 50%
58
+ 10.5: '#E2C1B7', # Burgundy 25%
59
+ 12.5: '#95B5B5', # Teal 50%
60
+ 14.0: '#80857B', # RPM Green 50%
61
+ 16.0: '#99AFC9', # Blue 50%
62
+ 18.0: '#FFDF9D', # Yellow 50%
63
+ 11.0: '#D6E3E3', # Teal 25%
64
+ 13.3: '#B6B8B2', # RPM Green 25%
65
+ 14.8: '#CCD7E4', # Blue 25%
66
+ 16.8: '#FFEFCE' # Yellow 25%
67
  },
68
+ 'rpm_monochrome': {
69
+ 8.5: '#2E3E2F', # RPM Green 100%
70
+ 10.5: '#545D51', # RPM Green 75%
71
+ 12.5: '#80857B', # RPM Green 50%
72
+ 14.0: '#B6B8B2', # RPM Green 25%
73
+ 16.0: '#636466', # Black 75%
74
+ 18.0: '#939598', # Black 50%
75
+ 11.0: '#D1D3D4', # Black 25%
76
+ 13.3: '#216767', # Teal (accent)
77
+ 14.8: '#415B6E', # Blue (accent)
78
+ 16.8: '#FF8E3C' # Yellow (accent)
79
  }
80
  }
81
 
82
+ self.current_scheme = 'rpm_primary'
83
  self.current_solution = None # Store current AI solution
84
 
85
+ def create_enhanced_visualization(self, solution, stage_width, stage_depth=32, title="Premium Grid Layout", show_variance=None):
86
+ """Create a clean 2D visualization with corner splays"""
87
  fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(18, 12), gridspec_kw={'height_ratios': [3, 1]},
88
+ facecolor='#2E3E2F')
89
 
90
  # Main visualization
91
  colors = self.color_schemes[self.current_scheme]
 
93
  x_pos = 0
94
  lot_num = 1
95
 
96
+ # Set up main plot with RPM green background
97
  ax1.set_xlim(-5, stage_width + 5)
98
  ax1.set_ylim(-10, 50)
99
+ ax1.set_facecolor('#2E3E2F')
100
 
101
  # Add title with variance if provided
102
  if show_variance is not None:
103
+ variance_color = '#216767' if abs(show_variance) < 0.001 else '#802B2B'
104
  title_text = f"{title}\nGrid Variance: {show_variance:+.1f}m"
105
  ax1.set_title(title_text, fontsize=28, fontweight='bold', pad=25, color='white')
106
  else:
107
  ax1.set_title(title, fontsize=28, fontweight='bold', pad=25, color='white')
108
 
109
+ # Add subtle gradient background
110
+ gradient = np.linspace(0.3, 0.1, 100).reshape(1, -1)
111
  ax1.imshow(gradient, extent=[-5, stage_width + 5, -10, 50], aspect='auto',
112
  cmap='Greys', alpha=0.3, zorder=0)
113
 
114
  # Add street with label
115
  street = Rectangle((-5, -8), stage_width + 10, 12,
116
+ facecolor='#000000', alpha=0.8, zorder=1,
117
+ edgecolor='#636466', linewidth=2)
118
  ax1.add_patch(street)
119
  ax1.text(stage_width/2, -2, 'STREET', ha='center', va='center',
120
  fontsize=20, color='white', fontweight='bold')
 
123
  splay_size = 3 # 3m corner splay
124
  lot_height = 28 # UNIFORM HEIGHT FOR ALL LOTS
125
 
 
 
 
126
  for i, (width, lot_type) in enumerate(solution):
127
  # Get base color
128
  if width in colors:
 
194
  zorder=2)
195
  ax1.add_patch(glow)
196
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
  # Add rear alignment line to emphasize equal depth
198
  rear_y = 8 + lot_height
199
  ax1.plot([x_pos, x_pos + width], [rear_y, rear_y],
 
223
 
224
  ax1.text(x_pos + width/2, 23, lot_type_text,
225
  ha='center', va='center', fontsize=11,
226
+ bbox=dict(boxstyle="round,pad=0.3", facecolor='#545D51',
227
  edgecolor='white', alpha=0.9), color='white')
228
 
229
  # Dimension lines
 
236
 
237
  # Add rear alignment line across all lots
238
  ax1.plot([0, stage_width], [8 + lot_height, 8 + lot_height],
239
+ '#216767', linewidth=2, alpha=0.8, linestyle='-')
240
  ax1.text(stage_width/2, 8 + lot_height + 1, 'REAR ALIGNMENT LINE',
241
+ ha='center', va='bottom', fontsize=12, color='#216767', alpha=0.8,
242
+ bbox=dict(boxstyle="round,pad=0.3", facecolor='#2E3E2F',
243
+ edgecolor='#216767', alpha=0.8))
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
244
 
245
  # Add stage dimensions
246
  arrow_props = dict(arrowstyle='<->', color='white', lw=3)
 
256
 
257
  # Metrics panel
258
  ax2.axis('off')
259
+ ax2.set_facecolor('#2E3E2F')
260
 
261
  # Calculate metrics with diversity score
262
  total_lots = len(solution)
 
278
  variance = total_width - stage_width
279
  efficiency = "100%" if abs(variance) < 0.001 else f"{(total_width/stage_width)*100:.1f}%"
280
 
 
 
 
 
 
 
 
 
 
281
  metrics_lines = [
282
  f"📊 TOTAL LOTS: {total_lots}",
283
  f"📐 LAND EFFICIENCY: {efficiency}",
284
  f"🎯 DIVERSITY: {diversity_score:.0%} ({unique_widths} types)",
285
  f"📏 GRID VARIANCE: {variance:+.2f}m",
 
286
  "",
287
  f"SLHC (≤10.5m): {slhc_count} lots",
288
  f"Standard (11-14m): {standard_count} lots",
 
292
  f"💰 Revenue: ${total_lots * 0.5:.1f}M - ${total_lots * 1.2:.1f}M"
293
  ]
294
 
295
+ col1_text = '\n'.join(metrics_lines[:5])
296
+ col2_text = '\n'.join(metrics_lines[5:])
297
 
298
  ax2.text(0.05, 0.5, col1_text, transform=ax2.transAxes,
299
  fontsize=14, verticalalignment='center', fontweight='bold',
300
  color='white',
301
+ bbox=dict(boxstyle="round,pad=0.5", facecolor='#545D51',
302
+ edgecolor='#216767', alpha=0.8))
303
 
304
  ax2.text(0.55, 0.5, col2_text, transform=ax2.transAxes,
305
  fontsize=14, verticalalignment='center', fontweight='bold',
306
  color='white',
307
+ bbox=dict(boxstyle="round,pad=0.5", facecolor='#545D51',
308
+ edgecolor='#216767', alpha=0.8))
309
 
310
  plt.tight_layout()
311
  return fig
 
911
  report += f"- All lots have identical rear alignment for visual consistency\n"
912
  report += f"- Diverse lot mix ensures varied streetscape\n"
913
  report += f"- SLHC lots grouped for efficient garbage collection\n"
 
914
 
915
  report += f"\n---\n*Report generated: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}*"
916
 
 
934
  stage_depth,
935
  enable_8_5, enable_10_5, enable_12_5, enable_14, enable_16, enable_18,
936
  enable_corners, enable_11, enable_13_3, enable_14_8, enable_16_8,
937
+ allow_custom_corners, color_scheme
938
  ):
939
  # Update color scheme
940
  optimizer.current_scheme = color_scheme
 
957
  if not enabled_widths:
958
  return None, None, pd.DataFrame(), "Please select at least one lot width!", "", ""
959
 
960
+ # Run optimization with diversity focus
961
+ optimized_solution = optimizer.optimize_with_flexible_corners(
962
+ stage_width, enabled_widths, allow_custom_corners
963
+ )
 
 
 
 
 
964
 
965
  # Store current solution for manual adjustment
966
  optimizer.current_solution = optimized_solution
 
987
  3. Try common stage widths: 84m, 105m, 126m
988
  """, "", ""
989
 
990
+ # Create visualizations with variance indicator
991
  fig_2d = optimizer.create_enhanced_visualization(
992
  optimized_solution, stage_width, stage_depth,
993
+ "RPM Grid Cut Optimization",
994
+ show_variance=variance
 
995
  )
996
 
997
  # Create results table
 
1072
 
1073
  return fig_2d, results_df, summary, report, manual_edit_string
1074
 
1075
+ def update_manual_adjustment(manual_widths_text, stage_width, stage_depth, color_scheme):
1076
  """Update visualization based on manual adjustment"""
1077
  optimizer.current_scheme = color_scheme
1078
 
 
1096
  fig = optimizer.create_enhanced_visualization(
1097
  solution, stage_width, stage_depth,
1098
  "Manually Adjusted Layout",
1099
+ show_variance=variance
 
1100
  )
1101
 
1102
  return fig, feedback
1103
 
1104
  # Create Gradio interface
1105
  with gr.Blocks(
1106
+ title="RPM Grid Cut Optimizer",
1107
  theme=gr.themes.Base(),
1108
  css="""
1109
  .gradio-container {
1110
+ font-family: 'Arial', sans-serif;
1111
+ background: #2E3E2F;
1112
  color: white;
1113
  }
1114
  .gr-button-primary {
1115
+ background: #216767;
1116
  border: none;
1117
+ box-shadow: 0 3px 5px 2px rgba(33, 103, 103, .3);
1118
+ }
1119
+ .gr-button-primary:hover {
1120
+ background: #4F8585;
1121
  }
1122
  h1 {
1123
+ color: white;
 
 
1124
  text-align: center;
1125
  font-size: 2.5em;
1126
+ margin-bottom: 0.5em;
1127
+ }
1128
+ h3 {
1129
+ color: #FFCF6D;
1130
  }
1131
  .gr-form {
1132
+ background: rgba(84, 93, 81, 0.9);
1133
  border-radius: 10px;
1134
  padding: 20px;
1135
+ border: 1px solid #216767;
1136
  }
1137
  .gr-input {
1138
+ background-color: #545D51;
1139
  color: white;
1140
+ border: 1px solid #216767;
1141
  }
1142
  .gr-check-radio {
1143
+ background-color: #545D51;
1144
+ }
1145
+ .gr-checkbox {
1146
+ background-color: #545D51;
1147
+ }
1148
+ label {
1149
+ color: white !important;
1150
  }
1151
  """
1152
  ) as demo:
1153
  gr.Markdown("""
1154
+ <div style='text-align: center; margin-bottom: 2em;'>
1155
+ <h1 style='color: white; margin-bottom: 0;'>RPM Grid Cut Optimizer</h1>
1156
+ <p style='color: #216767; font-size: 1.2em;'>AI-Powered Subdivision Planning</p>
1157
+ </div>
1158
  """)
1159
 
1160
  with gr.Row():
 
1199
  enable_16_8 = gr.Checkbox(label="16.8m", value=True)
1200
 
1201
  with gr.Column(scale=1):
1202
+ gr.Markdown("### ⚙️ Settings")
1203
 
1204
  allow_custom_corners = gr.Checkbox(
1205
  label="🎯 Allow Flexible Corner Widths",
 
1207
  info="Enables 13.8m, 13.9m etc. for perfect fits"
1208
  )
1209
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1210
  color_scheme = gr.Radio(
1211
+ ["rpm_primary", "rpm_contrast", "rpm_monochrome"],
1212
  label="🎨 Color Scheme",
1213
+ value="rpm_primary",
1214
+ info="RPM brand color palettes"
1215
  )
1216
 
1217
  optimize_btn = gr.Button(
1218
+ "🚀 Optimize Grid Cut",
1219
  variant="primary",
1220
  size="lg",
1221
  elem_id="optimize-button"
 
1223
 
1224
  gr.Markdown("""
1225
  ### 💡 Quick Tips:
1226
+ - **Corner Lots**: Always wider than internals
1227
+ - **Grid Variance**: Shows if layout is perfect (0.0m)
 
1228
  - **Manual Adjust**: Edit the result below after optimization
1229
+ - **Diversity Focus**: Maximizes lot variety
1230
  """)
1231
 
1232
  with gr.Row():
1233
+ plot_2d = gr.Plot(label="2D Layout with Corner Splays")
1234
 
1235
  # Manual adjustment section
1236
+ gr.Markdown("### ✏️ Fine-Tune Result")
1237
  with gr.Row():
1238
  with gr.Column(scale=2):
1239
  manual_widths = gr.Textbox(
 
1266
  stage_depth,
1267
  enable_8_5, enable_10_5, enable_12_5, enable_14, enable_16, enable_18,
1268
  enable_corners, enable_11, enable_13_3, enable_14_8, enable_16_8,
1269
+ allow_custom_corners, color_scheme
1270
  ],
1271
  outputs=[plot_2d, results_table, summary_output, report_output, manual_widths]
1272
  )
1273
 
1274
  update_btn.click(
1275
  update_manual_adjustment,
1276
+ inputs=[manual_widths, stage_width, stage_depth, color_scheme],
1277
  outputs=[plot_2d, adjustment_feedback]
1278
  )
1279
 
1280
  return demo
1281
 
1282
+ # Create and launch
1283
+ if __name__ == "__main__":
1284
+ app = create_advanced_app()
1285
+ app.launch()
1286
+
1287
+ return demo
1288
+
1289
  # Create and launch
1290
  if __name__ == "__main__":
1291
  app = create_advanced_app()