Storm Sewer: interactive in-app network — snapping, tracked objects, analyze the drawing
Replaces the .ssn-file workflow with an interactive one driven by the canvas: - Structures (SS_INLET / SS_JUNCTION / SS_OUTFALL) prompt invert/rim/area/C on the command line and commit a CIRCLE tagged with STORMSEWER_STRUCT XDATA [kind, invert, rim, area, C]. Outfalls skip area/C. - SS_PIPE picks a START and END structure (entity-pick), snapping its endpoints to their centers, prompts diameter/n, and stores connectivity (the two structure handles) in STORMSEWER_PIPE XDATA [diameter, n, from, to]. - SS_ANALYZE / SS_REPORT / SS_PROFILE rebuild the network from the drawn entities (data.rs::network_from_entities) and analyze it directly; SS_ANALYZE overlays flow/HGL labels without redrawing the geometry. Because the data lives on the entities as XDATA, the network round-trips to DWG/DXF. One additive line in src/app/update.rs adds SS_PIPE to the inject_picked_entity allow-list so the command can read the picked structure's center for snapping. 15 module tests cover the XDATA round-trip, analyze-from-drawing, and the command step machines. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
9b44eb6400
commit
1e68219b43
7 changed files with 609 additions and 104 deletions
|
|
@ -32,34 +32,31 @@ impl OpenCADStudio {
|
|||
// ── Storm Sewer module ──────────────────────────────────────────
|
||||
"SS_ANALYZE" => {
|
||||
use crate::modules::storm_sewer::analysis as ss;
|
||||
match ss::pick_ssn_file() {
|
||||
Some(read) => match read.and_then(|t| ss::analyze_text(&t)) {
|
||||
Ok((ents, report)) => {
|
||||
for e in ents {
|
||||
let _ = self.tabs[i].scene.add_entity(e);
|
||||
}
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
for line in report.lines() {
|
||||
self.command_line.push_output(line);
|
||||
}
|
||||
let result = ss::analyze_doc(self.tabs[i].scene.document.entities());
|
||||
match result {
|
||||
Ok((ents, report)) => {
|
||||
for e in ents {
|
||||
let _ = self.tabs[i].scene.add_entity(e);
|
||||
}
|
||||
Err(e) => self.command_line.push_error(&e),
|
||||
},
|
||||
None => self.command_line.push_info("Storm sewer: open cancelled."),
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
self.command_line
|
||||
.push_info("Storm sewer: analyzed drawn network (default IDF 60/(t+10)^0.8).");
|
||||
for line in report.lines() {
|
||||
self.command_line.push_output(line);
|
||||
}
|
||||
}
|
||||
Err(e) => self.command_line.push_error(&e),
|
||||
}
|
||||
}
|
||||
"SS_REPORT" => {
|
||||
use crate::modules::storm_sewer::analysis as ss;
|
||||
match ss::pick_ssn_file() {
|
||||
Some(read) => match read.and_then(|t| ss::report_text_from(&t)) {
|
||||
Ok(report) => {
|
||||
for line in report.lines() {
|
||||
self.command_line.push_output(line);
|
||||
}
|
||||
match ss::report_doc(self.tabs[i].scene.document.entities()) {
|
||||
Ok(report) => {
|
||||
for line in report.lines() {
|
||||
self.command_line.push_output(line);
|
||||
}
|
||||
Err(e) => self.command_line.push_error(&e),
|
||||
},
|
||||
None => self.command_line.push_info("Storm sewer: open cancelled."),
|
||||
}
|
||||
Err(e) => self.command_line.push_error(&e),
|
||||
}
|
||||
}
|
||||
"SS_INLET" | "SS_JUNCTION" | "SS_OUTFALL" => {
|
||||
|
|
@ -79,18 +76,16 @@ impl OpenCADStudio {
|
|||
}
|
||||
"SS_PROFILE" => {
|
||||
use crate::modules::storm_sewer::analysis as ss;
|
||||
match ss::pick_ssn_file() {
|
||||
Some(read) => match read.and_then(|t| ss::profile_text(&t)) {
|
||||
Ok(ents) => {
|
||||
for e in ents {
|
||||
let _ = self.tabs[i].scene.add_entity(e);
|
||||
}
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
self.command_line.push_info("Storm sewer HGL profile drawn.");
|
||||
let result = ss::profile_doc(self.tabs[i].scene.document.entities());
|
||||
match result {
|
||||
Ok(ents) => {
|
||||
for e in ents {
|
||||
let _ = self.tabs[i].scene.add_entity(e);
|
||||
}
|
||||
Err(e) => self.command_line.push_error(&e),
|
||||
},
|
||||
None => self.command_line.push_info("Storm sewer: open cancelled."),
|
||||
self.tabs[i].scene.bump_geometry();
|
||||
self.command_line.push_info("Storm sewer HGL profile drawn.");
|
||||
}
|
||||
Err(e) => self.command_line.push_error(&e),
|
||||
}
|
||||
}
|
||||
"NEW" => return Task::done(Message::TabNew),
|
||||
|
|
|
|||
|
|
@ -2812,7 +2812,7 @@ impl OpenCADStudio {
|
|||
.map(|c| {
|
||||
matches!(
|
||||
c.name(),
|
||||
"DIMTEDIT" | "MLEADERADD" | "MLEADERREMOVE"
|
||||
"DIMTEDIT" | "MLEADERADD" | "MLEADERREMOVE" | "SS_PIPE"
|
||||
)
|
||||
})
|
||||
.unwrap_or(false);
|
||||
|
|
|
|||
Loading…
Reference in a new issue