use of org.hortonmachine.gears.libs.modules.NetLink in project hortonmachine by TheHortonMachine.
the class OmsNetNumbering method printLinkAsGeoframe.
private void printLinkAsGeoframe(NetLink node, StringBuilder sb) {
for (NetLink upNode : node.getUpStreamLinks()) {
sb.append(upNode.num).append(" ").append(node.num).append("\n");
printLinkAsGeoframe(upNode, sb);
}
}
use of org.hortonmachine.gears.libs.modules.NetLink in project hortonmachine by TheHortonMachine.
the class OmsNetNumbering method printLinkAsIdOutletUpstreamArea.
private void printLinkAsIdOutletUpstreamArea(NetLink node, GridCoverage2D inTca, GridGeometry2D gridGeometry2D, StringBuilder sb) {
Coordinate coordinate = CoverageUtilities.coordinateFromColRow(node.downCol, node.downRow, gridGeometry2D);
int tca = node.getTca();
double area = xres * yres * tca;
sb.append(node.num).append(";").append(coordinate.x).append(";").append(coordinate.y).append(";").append(area).append("\n");
for (NetLink upNode : node.getUpStreamLinks()) {
printLinkAsIdOutletUpstreamArea(upNode, inTca, gridGeometry2D, sb);
}
}
use of org.hortonmachine.gears.libs.modules.NetLink in project hortonmachine by TheHortonMachine.
the class OmsNetNumbering method process.
@Execute
public void process() throws Exception {
if (!concatOr(outNetnum == null, doReset)) {
return;
}
checkNull(inFlow, inNet);
RegionMap regionMap = CoverageUtilities.getRegionParamsFromGridCoverage(inFlow);
nCols = regionMap.getCols();
nRows = regionMap.getRows();
xres = regionMap.getXres();
yres = regionMap.getYres();
RenderedImage flowRI = inFlow.getRenderedImage();
WritableRaster flowWR = CoverageUtilities.renderedImage2IntWritableRaster(flowRI, true);
WritableRandomIter flowIter = RandomIterFactory.createWritable(flowWR, null);
RandomIter netIter = CoverageUtilities.getRandomIterator(inNet);
List<Geometry> pointsList = null;
if (inPoints != null) {
pointsList = FeatureUtilities.featureCollectionToGeometriesList(inPoints, true, null);
}
WritableRandomIter netNumIter = null;
try {
List<NetLink> linksList = new ArrayList<NetLink>();
WritableRaster netNumWR = ModelsEngine.netNumbering(inFlow, inNet, inTca, pointsList, linksList, pm);
outNetnum = CoverageUtilities.buildCoverage("netnum", netNumWR, regionMap, inFlow.getCoordinateReferenceSystem());
netNumIter = RandomIterFactory.createWritable(netNumWR, null);
int novalue = HMConstants.getIntNovalue(inFlow);
WritableRaster basinWR = ModelsEngine.extractSubbasins(flowIter, novalue, netIter, netNumIter, nRows, nCols, pm);
outBasins = CoverageUtilities.buildCoverage("subbasins", basinWR, regionMap, inFlow.getCoordinateReferenceSystem());
RandomIter subbasinIter = CoverageUtilities.getRandomIterator(outBasins);
int validCount = 0;
int invalidCount = 0;
try {
for (int r = 0; r < nRows; r++) {
for (int c = 0; c < nCols; c++) {
int value = subbasinIter.getSample(c, r, 0);
if (!isNovalue(value)) {
validCount++;
} else {
invalidCount++;
}
}
}
// now handle basin hierarchy
for (NetLink nl1 : linksList) {
for (NetLink nl2 : linksList) {
if (!nl1.equals(nl2)) {
nl1.connect(nl2);
}
}
}
List<NetLink> rootNetLink = linksList.stream().filter(n -> n.getDownStreamLink() == null).collect(Collectors.toList());
if (rootNetLink.size() > 1) {
throw new ModelsRuntimeException("More than one link found to be root link. Check the dataset.", this);
}
// create mindmap
NetLink rootLink = rootNetLink.get(0);
StringBuilder sb = new StringBuilder();
sb.append("@startmindmap\n");
sb.append("* <b>basin stats</b>\\nvalid basin cells: " + validCount + "\\ntotal cells: " + (invalidCount + validCount) + "\\ntotal basin area: " + (validCount * xres * yres) + "\\nx res: " + xres + "\\ny res: " + yres + "\n");
String level = "*";
printLinkAsMindMap(rootLink, level, sb);
sb.append("@endmindmap\n");
outMindmap = sb.toString();
if (pDesiredArea != null) {
HashMap<Integer, Integer> conversionMap = new HashMap<>();
double desArea = pDesiredArea;
double minArea = desArea - desArea * pDesiredAreaDelta / 100.0;
for (NetLink netLink : linksList) {
// first handle the most upstream ones and aggregate them with their parents
List<NetLink> upStreamLinks = netLink.getUpStreamLinks();
if (!netLink.isFixed() && upStreamLinks.isEmpty()) {
double area = getLinkOnlyArea(netLink);
if (area < minArea) {
NetLink parentLink = netLink.getDownStreamLink();
if (parentLink != null) {
netLink.desiredChainNetLink = parentLink.num;
conversionMap.put(netLink.num, parentLink.num);
parentLink.getUpStreamLinks().remove(netLink);
}
}
}
// point)
if (upStreamLinks.size() == 1 && upStreamLinks.get(0).isFixed()) {
NetLink fixed = upStreamLinks.get(0);
double area = getLinkOnlyArea(netLink);
if (area < minArea && !netLink.isFixed()) {
// if the area is too small we need to merge it downstream,
// but only if the basin itself is not fixed. In that case
// it just can't be changed in size, period.
NetLink parentLink = netLink.getDownStreamLink();
if (parentLink != null) {
netLink.desiredChainNetLink = parentLink.num;
conversionMap.put(netLink.num, parentLink.num);
parentLink.getUpStreamLinks().remove(netLink);
parentLink.getUpStreamLinks().add(fixed);
}
}
}
}
int convertedSize;
int postConvertedSize;
do {
convertedSize = conversionMap.size();
List<NetLink> links = Arrays.asList(rootLink);
aggregateBasins(links, conversionMap, minArea, desArea, 0);
postConvertedSize = conversionMap.size();
} while (postConvertedSize - convertedSize > 0);
// if (pMaxAllowedConfluences > 0) {
// // review the tree and solve junctions with more than that number of
// upstreams
// do {
// convertedSize = conversionMap.size();
// List<NetLink> links = Arrays.asList(rootLink);
// fixManyChannels(links, conversionMap);
// postConvertedSize = conversionMap.size();
// } while( postConvertedSize - convertedSize > 0 );
// }
sb = new StringBuilder();
sb.append("@startmindmap\n");
sb.append("* <b>basin stats</b>\\nvalid basin cells: " + validCount + "\\ntotal cells: " + (invalidCount + validCount) + "\\ntotal basin area: " + (validCount * xres * yres) + "\\nx res: " + xres + "\\ny res: " + yres + "\\ndesired cells: " + (desArea / xres / yres) + "\n");
level = "*";
printLinkAsMindMap(rootLink, level, sb);
sb.append("@endmindmap\n");
outDesiredMindmap = sb.toString();
// build basins info
StringBuilder basinsInfoSb = new StringBuilder();
basinsInfoSb.append("basinid;outletX;outletY;area\n");
printLinkAsIdOutletUpstreamArea(rootLink, inTca, inTca.getGridGeometry(), basinsInfoSb);
outBasinsInfo = basinsInfoSb.toString();
WritableRaster desiredSubbasinsWR = CoverageUtilities.createWritableRaster(nCols, nRows, Integer.class, null, HMConstants.intNovalue);
WritableRandomIter desiredSubbasinsWIter = RandomIterFactory.createWritable(desiredSubbasinsWR, null);
for (int r = 0; r < nRows; r++) {
for (int c = 0; c < nCols; c++) {
int value = subbasinIter.getSample(c, r, 0);
if (!isNovalue(value)) {
Integer convertedBasinNum = conversionMap.get(value);
if (convertedBasinNum != null) {
// check if the converted has been converted also in some
// different thread
Integer convertedBasinNumTmp = conversionMap.get(convertedBasinNum);
while (convertedBasinNumTmp != null) {
convertedBasinNum = convertedBasinNumTmp;
convertedBasinNumTmp = conversionMap.get(convertedBasinNumTmp);
}
desiredSubbasinsWIter.setSample(c, r, 0, convertedBasinNum);
} else {
desiredSubbasinsWIter.setSample(c, r, 0, value);
}
}
}
}
desiredSubbasinsWIter.done();
outDesiredBasins = CoverageUtilities.buildCoverageWithNovalue("desiredsubbasins", desiredSubbasinsWR, regionMap, inFlow.getCoordinateReferenceSystem(), HMConstants.intNovalue);
}
// build geoframe topology input
StringBuilder geoframeSb = new StringBuilder();
geoframeSb.append(rootLink.num).append(" ").append(0).append("\n");
printLinkAsGeoframe(rootLink, geoframeSb);
outGeoframeTopology = geoframeSb.toString();
} finally {
subbasinIter.done();
}
} finally {
flowIter.done();
netIter.done();
if (netNumIter != null)
netNumIter.done();
}
}
use of org.hortonmachine.gears.libs.modules.NetLink in project hortonmachine by TheHortonMachine.
the class OmsNetNumbering method getLinkOnlyTca.
private int getLinkOnlyTca(NetLink netLink) {
int upLinksTca = 0;
for (NetLink nl : netLink.getUpStreamLinks()) {
upLinksTca += nl.getTca();
}
int tca = netLink.getTca() - upLinksTca;
return tca;
}
use of org.hortonmachine.gears.libs.modules.NetLink in project hortonmachine by TheHortonMachine.
the class OmsNetNumbering method aggregateBasins.
private void aggregateBasins(List<NetLink> currentLevelLinks, HashMap<Integer, Integer> conversionMap, double minArea, double desArea, int level) throws Exception {
for (NetLink netLink : currentLevelLinks) {
List<NetLink> ups = netLink.getUpStreamLinks();
double area = getLinkOnlyArea(netLink);
if (area < minArea) {
if (!ups.isEmpty()) {
while (area < minArea) {
// find nearest to area
double minDelta = Double.POSITIVE_INFINITY;
NetLink minDeltaLink = null;
double minAddArea = 0;
boolean hadOne = false;
int fixedCounts = 0;
for (NetLink nl : ups) {
if (nl.isFixed()) {
// fixed ones can't be joined to downstream
fixedCounts++;
continue;
}
// check if it wasn't used already (i.e. it has no parent)
if (nl.desiredChainNetLink == null) {
hadOne = true;
double nlArea = getLinkOnlyArea(nl);
double delta = Math.abs(desArea - (area + nlArea));
if (delta < minDelta) {
minDelta = delta;
minDeltaLink = nl;
minAddArea = nlArea;
}
}
}
if (fixedCounts == ups.size() && fixedCounts != 0) {
if (!netLink.isFixed()) {
// all upstream are fixed and area is small, aggregate downstream
// if the last basin is too small, let's aggregate it with the
// parent
NetLink parentLink = netLink.getDownStreamLink();
netLink.desiredChainNetLink = parentLink.num;
conversionMap.put(netLink.num, parentLink.num);
parentLink.getUpStreamLinks().remove(netLink);
for (NetLink nl : ups) {
nl.setDownStreamLink(parentLink);
}
parentLink.getUpStreamLinks().addAll(ups);
break;
} else {
// nothing to do here, go up one level and break out
aggregateBasins(ups, conversionMap, minArea, desArea, level + 1);
break;
}
} else {
if (!hadOne) {
// seems like the basins are not enough
break;
}
if (minDeltaLink != null) {
minDeltaLink.desiredChainNetLink = netLink.num;
area += minAddArea;
// adjust the upstream channel end and area
conversionMap.put(minDeltaLink.num, netLink.num);
ups.remove(minDeltaLink);
List<NetLink> minDeltaUpstreamLinks = minDeltaLink.getUpStreamLinks();
for (NetLink nl : minDeltaUpstreamLinks) {
nl.setDownStreamLink(netLink);
}
ups.addAll(minDeltaUpstreamLinks);
}
}
}
} else {
// if the last basin is too small, let's aggregate it with the parent
if (!netLink.isFixed()) {
NetLink parentLink = netLink.getDownStreamLink();
netLink.desiredChainNetLink = parentLink.num;
conversionMap.put(netLink.num, parentLink.num);
parentLink.getUpStreamLinks().remove(netLink);
}
}
} else {
// go up one level
if (!ups.isEmpty()) {
aggregateBasins(ups, conversionMap, minArea, desArea, level + 1);
}
}
}
}
Aggregations