Spaces:
Running
A newer version of the Gradio SDK is available: 6.20.0
API Impact & Design Changes - Multi-Phase Refactor (Phases 1-5)
Overview
The 5-phase refactor improves farm irrigation layout precision by refactoring the pipeline to use geometry-driven design decisions instead of heuristics. The external process_farm_design() API remains fully backward compatible, but internal function signatures have evolved.
Phase-by-Phase Impact
Phase 1-2: Valve Placement & Zoning
Changes to internal API:
generate_valve_zones(farm_polygon, num_zones, main_direction, crop_zones)- NEW signature- Now takes
num_zones(int) instead ofvalves(list) - Zones no longer have
valve_iduntil assigned by caller - Returns zones with
polygon,area_m2, optionallycrop
- Now takes
External API Impact: None - process_farm_design() unchanged
Phase 3: Valve Anchoring
New function:
anchor_valves_to_zones(zones, pump_location, design_type)- NEW- Adds
valve_locationPoint to each zone - Centralizes: places valves near pump with radial offsets
- Distributed: places valves on closest zone boundary edge
- Adds
Changed function:
generate_drip_layout()- Added optionalvalve_locationparameter (see Phase 5)
External API Impact: None - process_farm_design() remains unchanged
Phase 4: Orthogonal Pipe Routing
New function:
route_orthogonal(start_pt, end_pt, main_axis, lateral_axis)- NEW- Creates axis-aligned paths with ≤1 bend
- Replaces diagonal routing
Changed function:
generate_pipe_network(farm_polygon, pump_point, zones, main_direction, design_type)- NEW parameter- Added
design_typeparameter ("centralized" or "distributed") - Distributed: creates trunk main from pump along main axis
- Centralized: routes sub-mains directly from pump
- All sub-mains use orthogonal routing
- Added
External API Impact: None - process_farm_design() handles this internally
Phase 5: Drip Manifold Alignment (Final)
Changed function:
generate_drip_layout(polygon_utm, crop, headland_buffer_m, main_line_edge, override_spacing_m, override_discharge_lph, main_direction, **valve_location**)- NEW parameter- Added
valve_location: Optional[Point]parameter - When provided: selects polygon edge closest to valve
- When None: falls back to
main_line_edgeheuristic ("longest" or "shortest") - Fully backward compatible - existing code without
valve_locationworks unchanged
- Added
External API Impact: None - process_farm_design() automatically passes valve_location from zones
External API (process_farm_design) - FULLY BACKWARD COMPATIBLE
Signature (Unchanged)
def process_farm_design(geojson_input: str) -> Dict[str, Any]:
"""Main entry point: parse GeoJSON, run pipeline, return GeoJSON output."""
Input GeoJSON Structure (Unchanged)
farm_boundary(Polygon Feature)pump_location(Point Feature) withpump_hppropertycrop_zones(Polygon Features, optional) withcroppropertyelevation_data(Feature, optional) with min/max elevation- Top-level properties (optional):
pump_hp(float)design_type("centralized" or "distributed") - NEW in Phase 1-2headland_buffer_m(float)override_lateral_spacing_m(float)max_valves(int)
Output GeoJSON Structure (Enhanced but backward compatible)
{
"type": "FeatureCollection",
"properties": {
"design_summary": {
"farm_area_ha": float,
"total_valves": int,
"total_drip_tape_m": float,
"total_main_line_m": float,
"total_emitters": int,
"pump_hp": float,
"pump_flow_lph": float,
"design_type": "centralized" | "distributed" // NEW in Phase 1-2
},
"bom": {
"main_line_16mm_m": float,
"drip_tape_16mm_m": float,
"inline_emitters": int,
"total_pipe_m": float,
"valves_count": int,
"cost_main": float, // Optional
"cost_drip_tape": float, // Optional
"cost_emitters": float, // Optional
"cost_valves": float, // Optional
"total_cost_usd": float // Optional
}
},
"features": [
// farm_boundary, valves, valve_zones, main_lines, laterals
// Structure unchanged - drip manifold selection now valve-aware (Phase 5)
]
}
Design Changes Impact
Before (Pre-Refactor)
- Valves placed globally without zone awareness
- Zones generated from farm geometry heuristics
- Drip manifolds selected by edge length (longest/shortest)
- Pipe routing used diagonal paths
- No design-type differentiation in manifold selection
After (Post-5-Phase Refactor)
- Valves placed deterministically based on 4-step hierarchy (capacity, topography, crop, area-density)
- Zones generated via axis-aligned rectangular strips with sliver merging
- Valves anchored to zones with location-aware placement (Phase 3)
- Drip manifolds selected by proximity to anchored valve (Phase 5)
- Pipe routing uses orthogonal paths aligned to farm axes (Phase 4)
- Design-type aware: centralized (pump-centric) vs distributed (trunk-based) strategies
Benefits
- Precision: Manifolds align with valve locations, not arbitrary edge heuristics
- Consistency: All components follow farm axis system
- Flexibility: Supports both centralized and distributed designs
- Scalability: Multi-source support with Voronoi partitioning
- Backward Compatibility: Existing code requires no changes
Extra Parameters for API Consumers
For Custom Drip Layout (if calling generate_drip_layout directly):
New Optional Parameter:
valve_location: Optional[Point] = None
Usage:
from shapely.geometry import Point
from drip_engine import generate_drip_layout
# With valve location (Phase 5 - recommended)
design = generate_drip_layout(
polygon_utm=zone_polygon,
crop="tomato",
headland_buffer_m=1.0,
main_direction=(1, 0), # Normalized (dx, dy)
valve_location=Point(50, 60) # Anchored valve from Phase 3
)
# Without valve location (legacy, falls back to heuristic)
design = generate_drip_layout(
polygon_utm=zone_polygon,
crop="tomato",
headland_buffer_m=1.0,
main_direction=(1, 0),
main_line_edge="longest" # Legacy heuristic still works
)
For Custom Pipe Network (if calling generate_pipe_network directly):
New Required Parameter:
design_type: str = "distributed" # or "centralized"
Usage:
from pipe_network import generate_pipe_network
network = generate_pipe_network(
farm_polygon=service_polygon,
pump_point=pump_location,
zones=zones_with_valve_locations, # Anchored from Phase 3
main_direction=(1, 0),
design_type="distributed" # NEW in Phase 4
)
Test Coverage
- Total Tests: 81 (80 passing, 1 expected behavioral change)
- Phase 1-2: 29 design_api tests
- Phase 3: 7 valve anchoring tests (part of valve_engine tests)
- Phase 4: 18 pipe network tests
- Phase 5: Integrated into design_api tests (manifold selection behavior changed)
Migration Guide for Users
If using process_farm_design() (recommended)
✅ No changes needed - fully backward compatible
- Existing GeoJSON inputs work unchanged
- Output structure enhanced but backward compatible
- New
design_typeparameter optional (derived from farm area if not specified)
If using internal functions directly
⚠️ Review signatures if you call:
generate_valve_zones()- signature changedgenerate_drip_layout()- new optionalvalve_locationparametergenerate_pipe_network()- new requireddesign_typeparameter
Recommended Usage Pattern
from design_api import process_farm_design
# Single line - handles all 5 phases automatically
result = process_farm_design(geojson_input_string)
# Optional: specify design_type explicitly
geojson_with_design = {
**geojson_input,
"properties": {
**geojson_input.get("properties", {}),
"design_type": "centralized" # or "distributed"
}
}
result = process_farm_design(geojson_with_design)
Summary
The 5-phase refactor improves design precision through geometry-driven decisions while maintaining 100% backward compatibility for the primary process_farm_design() API. Internal functions evolved significantly but in isolated, well-tested modules. Users of the main API experience no breaking changes and benefit from improved design quality automatically.