Skip to content

Commit

Permalink
Merge pull request #3384 from moia-oss/optimizeH3ZoneSystem
Browse files Browse the repository at this point in the history
Optimize H3 Zone System initialization
  • Loading branch information
nkuehnel authored Jul 28, 2024
2 parents ed26933 + 8091cab commit 0730d0b
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 64 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,12 @@
import org.matsim.core.utils.geometry.CoordinateTransformation;
import org.matsim.core.utils.geometry.transformations.TransformationFactory;

import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.function.Predicate;
import java.util.stream.Collectors;

/**
* @author nkuehnel / MOIA
Expand All @@ -39,41 +43,38 @@ public H3ZoneSystem(String crs, int resolution, Network network, Predicate<Zone>
this.resolution = resolution;
this.network = network;
this.filter = filter;
this.network.getLinks().values().forEach(l -> getZoneForCoord(l.getToNode().getCoord()));
init();
}


@Override
public Optional<Zone> getZoneForCoord(Coord coord) {

long h3Address = getH3Cell(coord);
Id<Zone> zoneId = Id.create(h3Address, Zone.class);

if(zones.containsKey(zoneId)) {
return Optional.of(zones.get(zoneId));
} else {
Optional<Zone> zone = H3Utils.createZone(h3Address, fromLatLong);
if(zone.isPresent() && filter.test(zone.get())) {
initZone(zone.get(), h3Address);
return zone;
} else {
return Optional.empty();
}
private void init() {
Map<Long, List<Link>> linksToH3 =
this.network.getLinks().values()
.stream()
.collect(Collectors.groupingBy(link -> getH3Cell(link.getToNode().getCoord())));
for (Map.Entry<Long, List<Link>> linksH3 : linksToH3.entrySet()) {
Optional<Zone> maybeZone = createZone(linksH3.getKey());
maybeZone.ifPresent(z -> {
zones.put(z.getId(), z);
zoneToLinksMap.put(z.getId(), linksH3.getValue());
});
}
}

private void initZone(Zone zone, long h3Address) {
if(filter.test(zone)) {
zones.put(zone.getId(), zone);
for (Link link : network.getLinks().values()) {
long linkH3Address = getH3Cell(link.getToNode().getCoord());

if (linkH3Address == h3Address) {
List<Link> links = zoneToLinksMap.computeIfAbsent(zone.getId(), id -> new ArrayList<>());
links.add(link);
}
}
private Optional<Zone> createZone(Long h3) {
Optional<Zone> zone = H3Utils.createZone(h3, fromLatLong);
if(zone.isPresent() && filter.test(zone.get())) {
return zone;
}
return Optional.empty();
}

@Override
public Optional<Zone> getZoneForCoord(Coord coord) {
long h3Address = getH3Cell(coord);
Id<Zone> zoneId = Id.create(h3Address, Zone.class);
// create new zone if absent, should not be linked to existing links in the network,
// as all of them are covered in the init() phase.
return Optional.ofNullable(zones.computeIfAbsent(zoneId, id -> createZone(h3Address).orElse(null)));
}

private long getH3Cell(Coord coord) {
Expand Down Expand Up @@ -106,4 +107,4 @@ public List<Link> getLinksForZoneId(Id<Zone> zone) {
public Map<Id<Zone>, Zone> getZones() {
return Collections.unmodifiableMap(zones);
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -66,11 +66,11 @@ public SquareGridZoneSystem(Network network, double cellSize, Predicate<Zone> zo
}
public SquareGridZoneSystem(Network network, double cellSize, boolean filterByNetwork, Predicate<Zone> zoneFilter) {
this.zoneFilter = zoneFilter;
Preconditions.checkArgument(!network.getNodes().isEmpty(), "Cannot create SquareGrid if no nodes");

this.network = network;
this.cellSize = cellSize;

Preconditions.checkArgument(!network.getNodes().isEmpty(), "Cannot create SquareGrid if no nodes");

initBounds();

this.rows = Math.max(1, (int) Math.ceil((maxY - minY) / cellSize));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
* *********************************************************************** *
*/

package org.matsim.contrib.drt.extension.h3.drtZone;
package org.matsim.contrib.common.zones.systems.h3;

import org.junit.jupiter.api.Test;
import org.matsim.api.core.v01.Id;
Expand Down Expand Up @@ -48,20 +48,20 @@ void test_Holzkirchen_Resolution3() {
Network network = getNetwork();
String crs = TransformationFactory.DHDN_GK4;
int resolution = 3;
ZoneSystem drtZonalSystem = new H3ZoneSystem(crs, resolution, network, z -> true);
ZoneSystem zoneSystem = new H3ZoneSystem(crs, resolution, network, z -> true);

assertThat(drtZonalSystem.getZones().containsKey(createZoneId("590526392240701439"))).isTrue();
assertThat(zoneSystem.getZones().containsKey(createZoneId("590526392240701439"))).isTrue();

// center of Holzkirchen
assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).orElseThrow().getId()).isEqualTo(createZoneId("590526667118608383"));
assertThat(zoneSystem.getZoneForLinkId(Id.createLinkId(358598)).orElseThrow().getId()).isEqualTo(createZoneId("590526667118608383"));
// Thanning (Western border of network)
assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).orElseThrow().getId()).isEqualTo(createZoneId("590526667118608383"));
assertThat(zoneSystem.getZoneForLinkId(Id.createLinkId(78976)).orElseThrow().getId()).isEqualTo(createZoneId("590526667118608383"));
// between Gross- and Kleinpienzenau (Southeastern border of network)
assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).orElseThrow().getId()).isEqualTo(createZoneId("590526392240701439"));
assertThat(zoneSystem.getZoneForLinkId(Id.createLinkId(59914)).orElseThrow().getId()).isEqualTo(createZoneId("590526392240701439"));

//check all links are mapped
for (Link link : network.getLinks().values()) {
assertNotNull(drtZonalSystem.getZoneForLinkId(link.getId()));
assertNotNull(zoneSystem.getZoneForLinkId(link.getId()));
}
}

Expand All @@ -71,23 +71,23 @@ void test_Holzkirchen_Resolution5() {
String crs = TransformationFactory.DHDN_GK4;
int resolution = 5;

ZoneSystem drtZonalSystem = new H3ZoneSystem(crs, resolution, network, z -> true);
ZoneSystem zoneSystem = new H3ZoneSystem(crs, resolution, network, z -> true);

assertThat(drtZonalSystem.getZones().containsKey(createZoneId("599533579684282367"))).isTrue();
assertThat(drtZonalSystem.getZones().containsKey(createZoneId("599533826644901887"))).isTrue();
assertThat(drtZonalSystem.getZones().containsKey(createZoneId("599533499153645567"))).isTrue();
assertThat(drtZonalSystem.getZones().containsKey(createZoneId("599533503448612863"))).isTrue();
assertThat(zoneSystem.getZones().containsKey(createZoneId("599533579684282367"))).isTrue();
assertThat(zoneSystem.getZones().containsKey(createZoneId("599533826644901887"))).isTrue();
assertThat(zoneSystem.getZones().containsKey(createZoneId("599533499153645567"))).isTrue();
assertThat(zoneSystem.getZones().containsKey(createZoneId("599533503448612863"))).isTrue();

// center of Holzkirchen
assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).orElseThrow().getId()).isEqualTo(createZoneId("599533826644901887"));
assertThat(zoneSystem.getZoneForLinkId(Id.createLinkId(358598)).orElseThrow().getId()).isEqualTo(createZoneId("599533826644901887"));
// Thanning (Western border of network)
assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).orElseThrow().getId()).isEqualTo(createZoneId("599533503448612863"));
assertThat(zoneSystem.getZoneForLinkId(Id.createLinkId(78976)).orElseThrow().getId()).isEqualTo(createZoneId("599533503448612863"));
// between Gross- and Kleinpienzenau (Southeastern border of network)
assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).orElseThrow().getId()).isEqualTo(createZoneId("599533579684282367"));
assertThat(zoneSystem.getZoneForLinkId(Id.createLinkId(59914)).orElseThrow().getId()).isEqualTo(createZoneId("599533579684282367"));

//check all links are mapped
for (Link link : network.getLinks().values()) {
assertNotNull(drtZonalSystem.getZoneForLinkId(link.getId()));
assertNotNull(zoneSystem.getZoneForLinkId(link.getId()));
}
}

Expand All @@ -97,18 +97,18 @@ void test_Holzkirchen_Resolution6() {
String crs = TransformationFactory.DHDN_GK4;
int resolution = 6;

ZoneSystem drtZonalSystem = new H3ZoneSystem(crs, resolution, network, z -> true);
ZoneSystem zoneSystem = new H3ZoneSystem(crs, resolution, network, z -> true);

// center of Holzkirchen
assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).orElseThrow().getId()).isEqualTo(createZoneId("604037425601183743"));
assertThat(zoneSystem.getZoneForLinkId(Id.createLinkId(358598)).orElseThrow().getId()).isEqualTo(createZoneId("604037425601183743"));
// Thanning (Western border of network)
assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).orElseThrow().getId()).isEqualTo(createZoneId("604037102136459263"));
assertThat(zoneSystem.getZoneForLinkId(Id.createLinkId(78976)).orElseThrow().getId()).isEqualTo(createZoneId("604037102136459263"));
// between Gross- and Kleinpienzenau (Southeastern border of network)
assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).orElseThrow().getId()).isEqualTo(createZoneId("604037178372128767"));
assertThat(zoneSystem.getZoneForLinkId(Id.createLinkId(59914)).orElseThrow().getId()).isEqualTo(createZoneId("604037178372128767"));

//check all links are mapped
for (Link link : network.getLinks().values()) {
assertNotNull(drtZonalSystem.getZoneForLinkId(link.getId()));
assertNotNull(zoneSystem.getZoneForLinkId(link.getId()));
}
}

Expand All @@ -117,18 +117,18 @@ void test_Holzkirchen_Resolution10() {
Network network = getNetwork();
String crs = TransformationFactory.DHDN_GK4;
int resolution = 10;
ZoneSystem drtZonalSystem = new H3ZoneSystem(crs, resolution, network, z -> true);
ZoneSystem zoneSystem = new H3ZoneSystem(crs, resolution, network, z -> true);

// center of Holzkirchen
assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).orElseThrow().getId()).isEqualTo(createZoneId("622051824027533311"));
assertThat(zoneSystem.getZoneForLinkId(Id.createLinkId(358598)).orElseThrow().getId()).isEqualTo(createZoneId("622051824027533311"));
// Thanning (Western border of network)
assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).orElseThrow().getId()).isEqualTo(createZoneId("622051500514213887"));
assertThat(zoneSystem.getZoneForLinkId(Id.createLinkId(78976)).orElseThrow().getId()).isEqualTo(createZoneId("622051500514213887"));
// between Gross- and Kleinpienzenau (Southeastern border of network)
assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).orElseThrow().getId()).isEqualTo(createZoneId("622051576862081023"));
assertThat(zoneSystem.getZoneForLinkId(Id.createLinkId(59914)).orElseThrow().getId()).isEqualTo(createZoneId("622051576862081023"));

//check all links are mapped
for (Link link : network.getLinks().values()) {
assertNotNull(drtZonalSystem.getZoneForLinkId(link.getId()));
assertNotNull(zoneSystem.getZoneForLinkId(link.getId()));
}
}

Expand All @@ -138,19 +138,19 @@ void test_Holzkirchen_Resolution12() {
String crs = TransformationFactory.DHDN_GK4;
int resolution = 12;

ZoneSystem drtZonalSystem = new H3ZoneSystem(crs, resolution, network, z -> true);
ZoneSystem zoneSystem = new H3ZoneSystem(crs, resolution, network, z -> true);


// center of Holzkirchen
assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(358598)).orElseThrow().getId()).isEqualTo(createZoneId("631059023282267135"));
assertThat(zoneSystem.getZoneForLinkId(Id.createLinkId(358598)).orElseThrow().getId()).isEqualTo(createZoneId("631059023282267135"));
// Thanning (Western border of network)
assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(78976)).orElseThrow().getId()).isEqualTo(createZoneId("631058699768943103"));
assertThat(zoneSystem.getZoneForLinkId(Id.createLinkId(78976)).orElseThrow().getId()).isEqualTo(createZoneId("631058699768943103"));
// between Gross- and Kleinpienzenau (Southeastern border of network)
assertThat(drtZonalSystem.getZoneForLinkId(Id.createLinkId(59914)).orElseThrow().getId()).isEqualTo(createZoneId("631058776116789759"));
assertThat(zoneSystem.getZoneForLinkId(Id.createLinkId(59914)).orElseThrow().getId()).isEqualTo(createZoneId("631058776116789759"));

//check all links are mapped
for (Link link : network.getLinks().values()) {
assertNotNull(drtZonalSystem.getZoneForLinkId(link.getId()));
assertNotNull(zoneSystem.getZoneForLinkId(link.getId()));
}
}

Expand Down

0 comments on commit 0730d0b

Please sign in to comment.