Skip to content

Commit

Permalink
Added grid bench generator
Browse files Browse the repository at this point in the history
  • Loading branch information
Aklakan committed Mar 8, 2024
1 parent 942324d commit 99ec212
Show file tree
Hide file tree
Showing 12 changed files with 1,129 additions and 0 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
package org.aksw.bench.geo.cmd;

import org.locationtech.jts.geom.Envelope;

public record Cell2D(Grid2D grid, int row, int col, Envelope envelope) {}
Original file line number Diff line number Diff line change
@@ -0,0 +1,182 @@
package org.aksw.bench.geo.cmd;

import java.io.OutputStream;
import java.util.concurrent.Callable;
import java.util.stream.IntStream;
import java.util.stream.Stream;

import org.aksw.commons.io.util.StdIo;
import org.aksw.commons.picocli.CmdCommonBase;
import org.apache.jena.geosparql.implementation.GeometryWrapper;
import org.apache.jena.geosparql.implementation.jts.CustomGeometryFactory;
import org.apache.jena.geosparql.implementation.vocabulary.Geo;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.NodeFactory;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.riot.RDFFormat;
import org.apache.jena.riot.out.NodeFmtLib;
import org.apache.jena.riot.system.StreamRDF;
import org.apache.jena.riot.system.StreamRDFWriter;
import org.apache.jena.sparql.core.Quad;
import org.locationtech.jts.geom.Envelope;
import org.locationtech.jts.geom.Geometry;
import org.locationtech.jts.geom.Point;
import org.locationtech.jts.geom.util.AffineTransformation;

import picocli.CommandLine.ArgGroup;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

@Command(name = "data")
// versionProvider = VersionProviderRdfProcessingToolkit.class,
// description = "Run sequences of SPARQL queries and stream triples, quads and bindings")
public class CmdBenchGenGridDataGen
extends CmdCommonBase
implements Callable<Integer>
{
@ArgGroup(exclusive = false)
protected GridOffsets gridOffsets = new GridOffsets();

static class GridOffsets {
@Option(names = "--minX", required = true, defaultValue = "-180")
protected double minX;

@Option(names = "--maxX", required = true, defaultValue = "180")
protected double maxX;

@Option(names = "--minY", required = true, defaultValue = "-90")
protected double minY;

@Option(names = "--maxY", required = true, defaultValue = "90")
protected double maxY;
}

@Option(names = "--rows", required = true, defaultValue = "2")
protected int rows;

@Option(names = "--cols", required = true, defaultValue = "2")
protected int cols;

@Option(names = "--graphs", required = true, defaultValue = "2")
protected int graphs;

@Option(names = "--scale", required = true, defaultValue = "false", fallbackValue = "true", description = "Make polygons smaller the higher the graph id.")
protected boolean scale;


public static Query genQuery(Cell2D cell) {
// ?adm spatial:intersectBoxGeom(?river_geom) .
// filter(geof:sfIntersects(?river_geom, ?adm_geom_))

String queryStr = """
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
PREFIX spatial-f: <http://jena.apache.org/function/spatial#>
SELECT (COUNT(*) AS ?c) {
GRAPH ?g {
BIND($CELLGEOM$ AS ?queryGeom)
?feature spatial-f:intersectsBoxGeom ?queryGeom .
?feature geo:hasGeometry ?featureGeom .
?feature geo:asWKTLiteral ?featureGeomWkt .
FILTER(geof:sfIntersects(?featureGeomWkt, ?queryGeom))
}
}
""".replace("$CELLGEOM$", NodeFmtLib.strNT(toNode(toGeometry(cell.envelope()))))
;

System.out.println(queryStr);
Query result = QueryFactory.create(queryStr);
return result;

// Node intersectsBoxGeom = NodeFactory.createURI(SpatialExtension.INTERSECT_BOX_GEOM_PROP);
// Node sfIntersects = NodeFactory.createURI(Geof.SF_INTERSECTS);

// Var feature = Var.alloc("feature");
// Var geometry = Var.alloc("geometry");
//
// Query query = new Query();
// query.setQuerySelectType();
// query.setQueryPattern(ElementUtils.unionIfNeeded(
// new ElementNamedGraph(Vars.g,
// ElementUtils.createElementTriple(
// Triple.create(
// )
// )
// );
//
//

}

public static Geometry toGeometry(Envelope envelope) {
return CustomGeometryFactory.theInstance().toGeometry(envelope);
}

public static Node toNode(Geometry geom) {
return new GeometryWrapper(geom, Geo.WKT).asNode();
}

// public static Stream<Geometry> envelopeToGeometry(Stream<Envelope> in) {
// return in.map(env -> CustomGeometryFactory.theInstance().toGeometry(env));
// }
//
// public static Stream<Node> jtsToJena(Stream<Geometry> in) {
// return in.map(geom -> new GeometryWrapper(geom, Geo.WKT).asNode());
// }

public static String genGraphName(int id) {
return "https://www.example.org/graph/" + id;
}

@Override
public Integer call() throws Exception {
Grid2D grid = Grid2D.newBuilder()
.setMinX(gridOffsets.minX)
.setMaxX(gridOffsets.maxX)
.setMinX(gridOffsets.minY)
.setMaxX(gridOffsets.maxY)
.setRowCount(rows)
.setColCount(cols)
.build();

Stream<Quad> quads =
IntStream.range(0, graphs).boxed().flatMap(g -> {
double ratio = scale ? 1 - g / (double)graphs : 1.0;
Node graph = NodeFactory.createURI(genGraphName(g));
return grid.stream().flatMap(cell -> {
Node feature = NodeFactory.createURI("https://www.example.org/feature/" + g + "/" + cell.row() + "/" + cell.col());
Node geom = NodeFactory.createURI("https://www.example.org/geometry/" + g + "/" + cell.row() + "/" + cell.col());

Geometry cellGeom = toGeometry(cell.envelope());
Geometry scaledCellGeom = ratio != 1.0
? scaleGeometry(cellGeom, ratio, ratio)
: cellGeom;
Node wkt = toNode(scaledCellGeom);

// System.out.println(genQuery(cell));

return Stream.of(
Quad.create(graph, feature, Geo.HAS_GEOMETRY_NODE, geom),
Quad.create(graph, geom, Geo.AS_WKT_NODE, wkt)
);
});
});

try (OutputStream out = StdIo.openStdOutWithCloseShield()) {
StreamRDF writer = StreamRDFWriter.getWriterStream(out, RDFFormat.NQUADS);
writer.start();
quads.forEach(writer::quad);
writer.finish();
out.flush();
}
return 0;
}


public static Geometry scaleGeometry(Geometry geometry, double scaleFactorX, double scaleFactorY) {
Point centroid = geometry.getCentroid();
AffineTransformation scaleTrans = AffineTransformation.scaleInstance(scaleFactorX, scaleFactorY, centroid.getX(), centroid.getY());
return scaleTrans.transform(geometry);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.aksw.bench.geo.cmd;

import picocli.CommandLine.Command;

@Command(name="grid", description = "Grid-based spatial benchmark generator", subcommands = {
CmdBenchGenGridDataGen.class,
CmdBenchGenGridQueryGen.class
})
public class CmdBenchGenGridParent {
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
package org.aksw.bench.geo.cmd;

import java.io.PrintWriter;
import java.util.concurrent.Callable;
import java.util.stream.Stream;

import org.aksw.commons.io.util.StdIo;
import org.aksw.commons.picocli.CmdCommonBase;
import org.apache.jena.geosparql.implementation.GeometryWrapper;
import org.apache.jena.geosparql.implementation.jts.CustomGeometryFactory;
import org.apache.jena.geosparql.implementation.vocabulary.Geo;
import org.apache.jena.graph.Node;
import org.apache.jena.graph.NodeFactory;
import org.apache.jena.query.Query;
import org.apache.jena.query.QueryFactory;
import org.apache.jena.riot.out.NodeFmtLib;
import org.locationtech.jts.geom.Envelope;

import picocli.CommandLine.ArgGroup;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;

@Command(name = "query")
public class CmdBenchGenGridQueryGen
extends CmdCommonBase
implements Callable<Integer>
{
@ArgGroup(exclusive = false)
protected GridOffsets gridOffsets = new GridOffsets();

static class GridOffsets {
@Option(names = "--minX", required = true, defaultValue = "-180")
protected double minX;

@Option(names = "--maxX", required = true, defaultValue = "180")
protected double maxX;

@Option(names = "--minY", required = true, defaultValue = "-90")
protected double minY;

@Option(names = "--maxY", required = true, defaultValue = "90")
protected double maxY;
}

@Option(names = "--rows", required = true, defaultValue = "2")
protected int rows;

@Option(names = "--cols", required = true, defaultValue = "2")
protected int cols;

@Option(names = "--allGraphs", required = true, defaultValue = "false")
protected boolean allGraphs;


public static Query genQuery(Cell2D cell, String fixedGraph) {

String g = fixedGraph == null ? "?g" : NodeFmtLib.strNT(NodeFactory.createURI(fixedGraph));

String queryStr = """
PREFIX geo: <http://www.opengis.net/ont/geosparql#>
PREFIX geof: <http://www.opengis.net/def/function/geosparql/>
PREFIX spatial: <http://jena.apache.org/spatial#>
SELECT (COUNT(*) AS ?c) {
GRAPH $GRAPH$ {
BIND($CELLGEOM$ AS ?queryGeom)
?feature spatial:intersectBoxGeom (?queryGeom) .
?feature geo:hasGeometry ?featureGeom .
?featureGeom geo:asWKT ?featureGeomWkt .
FILTER(geof:sfIntersects(?featureGeomWkt, ?queryGeom))
}
}
"""
.replace("$CELLGEOM$", NodeFmtLib.strNT(toNode(cell.envelope())))
.replace("$GRAPH$", g)
;

System.out.println(queryStr);
Query result = QueryFactory.create(queryStr);
return result;
}

public static Node toNode(Envelope envelope) {
return new GeometryWrapper(CustomGeometryFactory.theInstance().toGeometry(envelope), Geo.WKT).asNode();
}

@Override
public Integer call() throws Exception {
Grid2D grid = Grid2D.newBuilder()
.setMinX(gridOffsets.minX)
.setMaxX(gridOffsets.maxX)
.setMinX(gridOffsets.minY)
.setMaxX(gridOffsets.maxY)
.setRowCount(rows)
.setColCount(cols)
.build();

String fixedGraph = allGraphs ? null : CmdBenchGenGridDataGen.genGraphName(0);

Stream<Query> queries = grid.stream().map(cell -> genQuery(cell, fixedGraph));

try (PrintWriter writer = new PrintWriter(StdIo.openStdOutWithCloseShield())) {
queries.forEach(query -> writer.println(query));
writer.flush();
}
return 0;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.aksw.bench.geo.cmd;

import picocli.CommandLine.Command;

@Command(name="gen", description = "Benchmark generation tools", subcommands = {
CmdBenchGenGridParent.class,
})
public class CmdBenchGenParent {

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package org.aksw.bench.geo.cmd;

import picocli.CommandLine.Command;

@Command(name="bench", description = "Quick Benchmark Toolkit", subcommands = {
CmdBenchGenParent.class,
})
public class CmdBenchParent {

}

0 comments on commit 99ec212

Please sign in to comment.