Skip to content

Commit

Permalink
loading large EPANET files
Browse files Browse the repository at this point in the history
  • Loading branch information
lbutler committed Jan 19, 2020
1 parent 4f4019d commit d66b604
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 62 deletions.
12 changes: 8 additions & 4 deletions ruby/README.md
Original file line number Diff line number Diff line change
@@ -1,15 +1,19 @@
# NO LONGER IN USE, ONLY EPANET MODELS CAN BE LOADED

## Extract InfoWorks WS Pro Model to GeoJson
The script included in this directory converts a simulation in InfoWorks WS Pro into a GeoJSON file which can be opened with compatible GIS software or with the Model View application.

The script included in this directory converts a simulation in InfoWorks WS Pro into a GeoJSON file which can be opened with compatible GIS software or with the Model View application.

## Using the script

1. [Download the script](https://raw.githubusercontent.com/modelcreate/model-view/master/ruby/modelview_export_to_geojson.rb)
2. Open a simulation in InfoWorks WS Pro
3. With the geoplan open run the script by going to Network > Run Ruby Script
4. Choose a location and filename for the GeoJSON file
5. The script runs between 1 minute to 10 minutes, based on the size of your network

## Known issues/limitations
* Currently only tested with IW Pro 3.5, it may not work on older versions
* Will only extract simulation results, you can not use it on a network directly
* Which fields get extracted are currently hard-coded within the ruby script

- Currently only tested with IW Pro 3.5, it may not work on older versions
- Will only extract simulation results, you can not use it on a network directly
- Which fields get extracted are currently hard-coded within the ruby script
30 changes: 25 additions & 5 deletions src/components/App/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ import ModelDropZone from "../ModelDropZone";
import VectorMap from "../VectorMap";
import Landing from "../Landing";
import ModelInfo, { ModelInfoSetting } from "../ModelInfo";
import { EpanetResults } from "../../utils/EpanetBinary";

import ModelFeatureCollection from "../../interfaces/ModelFeatureCollection";
import "./index.css";
import "mapbox-gl/dist/mapbox-gl.css";
Expand Down Expand Up @@ -130,6 +132,7 @@ type Props = {};

interface AppState {
modelGeoJson?: FeatureCollection<Geometries, Properties>;
epanetResults?: EpanetResults;
isLoading: boolean;
isFileLoaded: boolean;
projectionString: string;
Expand Down Expand Up @@ -157,13 +160,14 @@ class App extends Component<Props, AppState> {
});
};

droppedJson = (file: ModelFeatureCollection) => {
droppedJson = (file: [ModelFeatureCollection, EpanetResults]) => {
this.setState(prevState => ({
isFileLoaded: true,
modelGeoJson: file,
modelGeoJson: file[0],
epanetResults: file[1],
setting: {
...prevState.setting,
timesteps: file.model.timesteps.map(t => new Date(t.substr(0, 16)))
timesteps: file[0].model.timesteps.map(t => new Date(t.substr(0, 16)))
}
}));
};
Expand All @@ -177,12 +181,28 @@ class App extends Component<Props, AppState> {
};

_updateSelectedFeature = (value: Feature) => {
if (value.properties !== null) {
if (value.properties !== null && this.state.epanetResults) {
const selectedFeature: { [name: string]: any } = value.properties;

const type = value.geometry && value.geometry.type;

let tsv = {};
const index = value.properties.index;
if (type === "Point") {
tsv = this.state.epanetResults.results.nodes[index];
} else if (type === "LineString") {
tsv = this.state.epanetResults.results.links[index];
}

const props = {
...selectedFeature,
...tsv
};

this.setState(prevState => ({
setting: {
...prevState.setting,
selectedFeature
selectedFeature: props
}
}));
}
Expand Down
16 changes: 2 additions & 14 deletions src/components/Landing/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,7 @@ const Landing: FunctionComponent<LandingProperties> = ({
<>
<p className="subtitle">Share and view models in the browser</p>
<p className="blurb"></p>
<p className="blurb">
View InfoWorks WS Pro model extracts or run and view EPANET water
models online.
</p>
<p className="blurb">View EPANET watermodels online.</p>
<p className="blurb">
Model View is under active development, this version is an early
preview. This application and its source code is free and open
Expand All @@ -62,7 +59,7 @@ const Landing: FunctionComponent<LandingProperties> = ({
</p>

<div className="droparea">
<p>Drop EPANET .inp file or IW WS Pro model extract here</p>
<p>Drop EPANET .inp file here</p>
<p className="blurb">
All data is proccessed client side, no model data sent to the
server.
Expand All @@ -76,15 +73,6 @@ const Landing: FunctionComponent<LandingProperties> = ({
</Button>
</div>
<div className="btns-float-left">
<Button
className={classes.button}
variant="contained"
color="primary"
href="https://github.com/modelcreate/model-view/tree/master/ruby"
>
Model Extract Guide
</Button>

<Button
className={classes.button}
variant="contained"
Expand Down
15 changes: 3 additions & 12 deletions src/components/ModelDropZone/index.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { useDropzone } from "react-dropzone";
import React, { useMemo, useCallback, FunctionComponent } from "react";
import { runEpanet } from "../../utils/epanet";
import { EpanetResults } from "../../utils/EpanetBinary";

import ModelFeatureCollection from "../../interfaces/ModelFeatureCollection";
import { geojsonType } from "@turf/invariant";

const overlayStyle = {
position: "absolute",
Expand Down Expand Up @@ -38,7 +38,7 @@ const rejectStyle = {
};

type ModelDropZone = {
onDroppedJson: (file: ModelFeatureCollection) => void;
onDroppedJson: (file: [ModelFeatureCollection, EpanetResults]) => void;
};

const ModelDropZone: FunctionComponent<ModelDropZone> = ({
Expand All @@ -51,16 +51,7 @@ const ModelDropZone: FunctionComponent<ModelDropZone> = ({
const reader = new FileReader();
reader.onload = () => {
if (typeof reader.result === "string") {
const geoJson = runEpanet(reader.result, onDroppedJson);

// const geoJson: ModelFeatureCollection = JSON.parse(reader.result);
// try {
// geojsonType(geoJson, "FeatureCollection", "Drop Zone");
// onDroppedJson(geoJson);
// } catch (e) {
// console.log(e);
// // TODO: Handle if dropped bad JSON data
// }
runEpanet(reader.result, onDroppedJson);
}
};

Expand Down
31 changes: 7 additions & 24 deletions src/utils/EpanetToGeojson/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { featureCollection, feature, Feature } from "@turf/helpers";
import { EpanetResults, NodeResults, LinkResults } from "../EpanetBinary";
import { EpanetResults } from "../EpanetBinary";

import ModelFeatureCollection from "../../interfaces/ModelFeatureCollection";

Expand Down Expand Up @@ -98,25 +98,14 @@ export function toGeoJson(

const nodeFeatures = Object.values(data.nodes).reduce(
(previousValue, currentValue, currentIndex) => {
return previousValue.concat(
pointFeature(
currentValue,
epanetResults.results.nodes[currentValue.index]
)
);
return previousValue.concat(pointFeature(currentValue));
},
[] as Feature[]
);

const linkFeatures = Object.values(data.links).reduce(
(previousValue, currentValue, currentIndex) => {
return previousValue.concat(
lineFeature(
currentValue,
data,
epanetResults.results.links[currentValue.index]
)
);
return previousValue.concat(lineFeature(currentValue, data));
},
[] as Feature[]
);
Expand Down Expand Up @@ -172,25 +161,20 @@ function readLine(
}
}

function pointFeature(node: Node, result: NodeResults): Feature {
function pointFeature(node: Node): Feature {
const geometry = {
type: "Point",
coordinates: [node.x, node.y]
};

const props = {
...node,
...result
...node
};

return feature(geometry, props);
}

function lineFeature(
link: Link,
epanetData: EpanetData,
result: LinkResults
): Feature {
function lineFeature(link: Link, epanetData: EpanetData): Feature {
const us = [
epanetData.nodes[link.us_node_id].x,
epanetData.nodes[link.us_node_id].y
Expand All @@ -210,8 +194,7 @@ function lineFeature(
};

const props = {
...link,
...result
...link
};

delete props.bends;
Expand Down
6 changes: 3 additions & 3 deletions src/utils/epanet/index.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Project, Workspace } from "epanet-js";
import { readBinary } from "../EpanetBinary";
import { readBinary, EpanetResults } from "../EpanetBinary";
import { toGeoJson } from "../EpanetToGeojson";

import ModelFeatureCollection from "../../interfaces/ModelFeatureCollection";
Expand All @@ -11,7 +11,7 @@ import ModelFeatureCollection from "../../interfaces/ModelFeatureCollection";

export function runEpanet(
fromProject: string,
openModel: (file: ModelFeatureCollection) => void
openModel: (file: [ModelFeatureCollection, EpanetResults]) => void
): void {
// Initialise a new Workspace and Project object
const ws = new Workspace();
Expand Down Expand Up @@ -51,6 +51,6 @@ export function runEpanet(
console.log(results);
console.log("Call to readBinary took " + (t3 - t2) + " milliseconds.");

openModel(geoJson);
openModel([geoJson, results]);
// };
}

0 comments on commit d66b604

Please sign in to comment.