├── .gitignore ├── CONTRIBUTING.md ├── LICENSE ├── README.md ├── conf └── geoflink-conf.yml ├── dependency-reduced-pom.xml ├── pom.xml └── src └── main ├── java └── GeoFlink │ ├── StreamingJob.java │ ├── apps │ ├── CheckIn.java │ └── StayTime.java │ ├── spatialIndices │ ├── SpatialIndex.java │ └── UniformGrid.java │ ├── spatialObjects │ ├── GeometryCollection.java │ ├── LineString.java │ ├── MultiLineString.java │ ├── MultiPoint.java │ ├── MultiPolygon.java │ ├── Point.java │ ├── Polygon.java │ └── SpatialObject.java │ ├── spatialOperators │ ├── QueryConfiguration.java │ ├── QueryType.java │ ├── SpatialOperator.java │ ├── join │ │ ├── JoinQuery.java │ │ ├── LineStringLineStringJoinQuery.java │ │ ├── LineStringPointJoinQuery.java │ │ ├── LineStringPolygonJoinQuery.java │ │ ├── PointLineStringJoinQuery.java │ │ ├── PointPointJoinQuery.java │ │ ├── PointPolygonJoinQuery.java │ │ ├── PolygonLineStringJoinQuery.java │ │ ├── PolygonPointJoinQuery.java │ │ └── PolygonPolygonJoinQuery.java │ ├── knn │ │ ├── KNNQuery.java │ │ ├── LineStringLineStringKNNQuery.java │ │ ├── LineStringPointKNNQuery.java │ │ ├── LineStringPolygonKNNQuery.java │ │ ├── PointLineStringKNNQuery.java │ │ ├── PointPointKNNQuery.java │ │ ├── PointPolygonKNNQuery.java │ │ ├── PolygonLineStringKNNQuery.java │ │ ├── PolygonPointKNNQuery.java │ │ └── PolygonPolygonKNNQuery.java │ ├── range │ │ ├── LineStringLineStringRangeQuery.java │ │ ├── LineStringPointRangeQuery.java │ │ ├── LineStringPolygonRangeQuery.java │ │ ├── PointLineStringRangeQuery.java │ │ ├── PointPointRangeQuery.java │ │ ├── PointPolygonRangeQuery.java │ │ ├── PolygonLineStringRangeQuery.java │ │ ├── PolygonPointRangeQuery.java │ │ ├── PolygonPolygonRangeQuery.java │ │ └── RangeQuery.java │ ├── tAggregate │ │ ├── PointTAggregateQuery.java │ │ └── TAggregateQuery.java │ ├── tFilter │ │ ├── PointTFilterQuery.java │ │ └── TFilterQuery.java │ ├── tJoin │ │ ├── PointPointTJoinQuery.java │ │ └── TJoinQuery.java │ ├── tKnn │ │ ├── PointPointTKNNQuery.java │ │ └── TKNNQuery.java │ ├── tRange │ │ ├── PointPolygonTRangeQuery.java │ │ └── TRangeQuery.java │ └── tStats │ │ ├── PointTStatsQuery.java │ │ └── TStatsQuery.java │ ├── spatialStreams │ ├── Deserialization.java │ ├── Serialization.java │ └── ShapeFileInputFormat.java │ └── utils │ ├── Comparators.java │ ├── ConfigType.java │ ├── DistanceFunctions.java │ ├── HelperClass.java │ └── Params.java └── resources └── log4j.properties /.gitignore: -------------------------------------------------------------------------------- 1 | # Don't track content of these folders 2 | data/ 3 | bin/ 4 | scripts/ 5 | obj/ 6 | output/ 7 | .idea/ 8 | target/ 9 | 10 | 11 | # Don't track the following source file # 12 | ######################################## 13 | #src/main/java/GeoFlink/StreamingJob.java 14 | 15 | # Don't track the Compiled source # 16 | ################################## 17 | *.com 18 | *.class 19 | *.dll 20 | *.exe 21 | *.o 22 | *.so 23 | 24 | # Don't track following misc files 25 | ################################## 26 | *.csv 27 | *.cbp 28 | *.depend 29 | *.py 30 | #*.gitignore 31 | Makefile 32 | *.iml 33 | 34 | # Packages # 35 | ############ 36 | # it's better to unpack these files and commit the raw source 37 | # git has its own built in compression methods 38 | *.7z 39 | *.dmg 40 | *.gz 41 | *.iso 42 | *.jar 43 | *.rar 44 | *.tar 45 | *.zip 46 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contributing to GeoFlink 2 | 3 | The GeoFlink project welcomes contributions. You can contribute to GeoFlink code by making Pull Requests on [GeoFlink github repository](https://github.com/aistairc/GeoFlink) 4 | 5 | The following sections brief the workflow of how to complete a contribution. 6 | 7 | ## Develop a code contribution 8 | 9 | Code contributions should include the following: 10 | 11 | - Detailed documentations on classes and methods. 12 | - Updates on corresponding GeoFlink documentation if necessary. 13 | 14 | Code contributions must include a license header at the top of each file. A sample header for Scala/Java files is as follows: 15 | 16 | ``` 17 | /* 18 | Copyright 2020 Data Platform Research Team, AIRC, AIST, Japan 19 | 20 | Licensed under the Apache License, Version 2.0 (the "License"); 21 | you may not use this file except in compliance with the License. 22 | You may obtain a copy of the License at 23 | 24 | http://www.apache.org/licenses/LICENSE-2.0 25 | 26 | Unless required by applicable law or agreed to in writing, software 27 | distributed under the License is distributed on an "AS IS" BASIS, 28 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 29 | See the License for the specific language governing permissions and 30 | limitations under the License. 31 | */ 32 | ``` 33 | 34 | 35 | ## Make a Pull Request 36 | After developing a contribution, the easiest way to push a contribution is to submit a Pull Request to the [GeoFlink github repository](https://github.com/aistairc/GeoFlink) 37 | 38 | When preparing a pull request, please mentione what changes were proposed in this pull request. 39 | 40 | When a pull request is submitted, we will check the build correctness. Please check the pull request status, and fix any reported problems. 41 | -------------------------------------------------------------------------------- /conf/geoflink-conf.yml: -------------------------------------------------------------------------------- 1 | !!GeoFlink.utils.ConfigType 2 | # This is a GeoFlink Config File 3 | # --- 4 | # Cluster 5 | clusterMode: False 6 | #kafkaBootStrapServers: "172.16.0.64:9092, 172.16.0.81:9092" 7 | kafkaBootStrapServers: "150.82.97.204:9092" 8 | #kafkaBootStrapServers: "localhost:9092" 9 | 10 | # Input Stream1 11 | inputStream1: 12 | topicName: "randPointUniform" 13 | #topicName: "TaxiDrive17MillionGeoJSON" 14 | # format : GeoJSON or WKT or CSV or TSV 15 | format: "GeoJSON" 16 | #dateFormat: "null" if timestamp is already in epoch milliseconds 17 | dateFormat: "yyyy-MM-dd HH:mm:ss" 18 | #dateFormat: "null" 19 | geoJSONSchemaAttr: ["oID", "timestamp"] 20 | csvTsvSchemaAttr: [1, 4, 5, 6] 21 | # csvTsvSchemaAttr : object ID, timestamp, coordinate-x, coordinate-y (Point only) 22 | gridBBox: [115.5, 39.6, 117.6, 41.1] 23 | #gridBBox: [-41543.0, -27825.0, 48431.0, 24224.0] 24 | numGridCells: 100 25 | cellLength: 0 26 | # delimiter : CSV = ",", TSV separeted by TAB character = " " or "\t", TSV separeted by \t = "\\\\t" 27 | delimiter: " " 28 | charset: "UTF-8" 29 | 30 | # Input Stream2 31 | inputStream2: 32 | topicName: "TaxiDriveGeoJSON_Live" 33 | # format : GeoJSON or WKT or CSV or TSV 34 | format: "GeoJSON" 35 | dateFormat: "yyyy-MM-dd HH:mm:ss" 36 | geoJSONSchemaAttr: ["oID", "timestamp"] 37 | # csvTsvSchemaAttr : object ID, timestamp, coordinate-x, coordinate-y (Point only) 38 | csvTsvSchemaAttr: [1, 4, 5, 6] 39 | gridBBox: [115.5, 39.6, 117.6, 41.1] 40 | numGridCells: 100 41 | cellLength: 0 42 | # delimiter : CSV = ",", TSV separeted by TAB character = " " or "\t", TSV separeted by \t = "\\\\t" 43 | #delimiter: "\\\\t" 44 | delimiter: "," 45 | charset: "UTF-8" 46 | 47 | # Output Stream 48 | outputStream: 49 | topicName: "GeoJSONToCSV" 50 | delimiter: "," 51 | 52 | # Query parameters 53 | query: 54 | option: 2 #2011 or 211 55 | parallelism: 15 56 | approximate: False 57 | radius: 10.5 58 | aggregateFunction: "SUM" 59 | k: 100 60 | omegaDuration: 1 61 | trajIDs: [123, 231] 62 | 63 | queryPoints: 64 | - [116.14319, 40.07271] 65 | - [117.6, 40.5] 66 | 67 | queryPolygons: 68 | - [[116.5, 40.5], [117.6, 40.5], [117.6, 41.4], [116.5, 41.4], [116.5, 40.5]] 69 | - [[116.5, 40.5], [117.6, 40.5], [117.6, 41.4], [116.5, 41.4], [116.5, 40.5]] 70 | #- [[-41543.0, -8046.37999999997],[-41022.51, -8046.37999999997],[-41022.51, -7525.88999999997],[-41543.0, -7525.88999999997],[-41543.0, -8046.37999999997]] 71 | 72 | queryLineStrings: 73 | - [[116.5, 40.5], [117.6, 40.5], [117.6, 41.4], [116.5, 41.4]] 74 | - [[116.5, 40.5], [117.6, 40.5], [117.6, 41.4], [116.5, 41.4]] 75 | 76 | thresholds: 77 | trajDeletion: 1000 78 | outOfOrderTuples: 1 79 | 80 | # Window parameters 81 | window: 82 | type: "TIME" 83 | interval: 5 84 | step: 5 -------------------------------------------------------------------------------- /dependency-reduced-pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4.0.0 4 | GeoFlinkProject 5 | GeoFlinkProject 6 | 0.1 7 | 8 | 9 | 10 | 11 | org.eclipse.m2e 12 | lifecycle-mapping 13 | 1.0.0 14 | 15 | 16 | 17 | 18 | 19 | org.apache.maven.plugins 20 | maven-shade-plugin 21 | [3.0.0,) 22 | 23 | shade 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | org.apache.maven.plugins 33 | maven-compiler-plugin 34 | [3.1,) 35 | 36 | testCompile 37 | compile 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | maven-compiler-plugin 53 | 3.1 54 | 55 | ${java.version} 56 | ${java.version} 57 | 58 | 59 | 60 | maven-shade-plugin 61 | 3.0.0 62 | 63 | 64 | package 65 | 66 | shade 67 | 68 | 69 | 70 | 71 | org.apache.flink:force-shading 72 | com.google.code.findbugs:jsr305 73 | org.slf4j:* 74 | log4j:* 75 | 76 | 77 | 78 | 79 | *:* 80 | 81 | META-INF/*.SF 82 | META-INF/*.DSA 83 | META-INF/*.RSA 84 | 85 | 86 | 87 | 88 | 89 | GeoFlink.StreamingJob 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | add-dependencies-for-IDEA 101 | 102 | 103 | org.apache.flink 104 | flink-java 105 | ${flink.version} 106 | compile 107 | 108 | 109 | org.apache.flink 110 | flink-streaming-java_${scala.binary.version} 111 | ${flink.version} 112 | compile 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | false 121 | 122 | central.maven.org 123 | Central Maven repository 124 | http://central.maven.org/maven2 125 | 126 | 127 | 128 | 129 | org.slf4j 130 | slf4j-log4j12 131 | 1.7.7 132 | runtime 133 | 134 | 135 | 136 | 2.11 137 | ${java.version} 138 | 1.8 139 | ${java.version} 140 | UTF-8 141 | 1.9.1 142 | 143 | 144 | 145 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 19 | 21 | 4.0.0 22 | 23 | GeoFlinkProject 24 | GeoFlinkProject 25 | 0.1 26 | jar 27 | 28 | 29 | UTF-8 30 | 1.9.1 31 | 1.8 32 | 2.17.1 33 | 2.11 34 | ${java.version} 35 | ${java.version} 36 | 37 | 38 | 39 | 40 | 41 | 42 | central.maven.org 43 | Central Maven repository 44 | http://central.maven.org/maven2 45 | 46 | false 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | org.locationtech.jts 61 | jts-core 62 | 1.16.1 63 | 64 | 65 | 66 | 67 | org.apache.flink 68 | flink-runtime-web_2.11 69 | ${flink.version} 70 | 71 | 72 | 73 | org.apache.flink 74 | flink-streaming-java_${scala.binary.version} 75 | ${flink.version} 76 | compile 77 | 78 | 79 | 80 | org.apache.flink 81 | flink-connector-kafka_2.11 82 | 1.9.0 83 | 84 | 85 | 86 | org.json 87 | json 88 | 20200518 89 | 90 | 91 | 92 | 93 | org.apache.flink 94 | flink-metrics-dropwizard 95 | 1.9.0 96 | 97 | 98 | 99 | 100 | 101 | org.locationtech.jts.io 102 | jts-io-common 103 | 1.18.0 104 | 105 | 106 | 107 | javax.json 108 | javax.json-api 109 | 1.1.4 110 | 111 | 112 | org.glassfish 113 | javax.json 114 | 1.1 115 | 116 | 117 | 118 | 119 | 120 | 121 | org.apache.logging.log4j 122 | log4j-core 123 | ${log4j.version} 124 | 125 | 126 | 127 | org.apache.logging.log4j 128 | log4j-api 129 | ${log4j.version} 130 | 131 | 132 | 133 | org.apache.logging.log4j 134 | log4j-to-slf4j 135 | ${log4j.version} 136 | 137 | 138 | org.apache.logging.log4j 139 | log4j-1.2-api 140 | ${log4j.version} 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | org.apache.maven.plugins 151 | maven-compiler-plugin 152 | 3.1 153 | 154 | ${java.version} 155 | ${java.version} 156 | 157 | 158 | 159 | 160 | 161 | 162 | org.apache.maven.plugins 163 | maven-shade-plugin 164 | 3.0.0 165 | 166 | 167 | 168 | package 169 | 170 | shade 171 | 172 | 173 | 174 | 175 | org.apache.flink:force-shading 176 | com.google.code.findbugs:jsr305 177 | org.slf4j:* 178 | log4j:* 179 | 180 | 181 | 182 | 183 | 185 | *:* 186 | 187 | META-INF/*.SF 188 | META-INF/*.DSA 189 | META-INF/*.RSA 190 | 191 | 192 | 193 | 194 | 195 | GeoFlink.StreamingJob 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | org.eclipse.m2e 210 | lifecycle-mapping 211 | 1.0.0 212 | 213 | 214 | 215 | 216 | 217 | org.apache.maven.plugins 218 | maven-shade-plugin 219 | [3.0.0,) 220 | 221 | shade 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | org.apache.maven.plugins 231 | maven-compiler-plugin 232 | [3.1,) 233 | 234 | testCompile 235 | compile 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | add-dependencies-for-IDEA 256 | 257 | 258 | 259 | idea.version 260 | 261 | 262 | 263 | 264 | 265 | org.apache.flink 266 | flink-java 267 | ${flink.version} 268 | compile 269 | 270 | 271 | log4j 272 | log4j 273 | 274 | 275 | org.slf4j 276 | slf4j-log4j12 277 | 278 | 279 | 280 | 281 | org.apache.flink 282 | flink-streaming-java_${scala.binary.version} 283 | ${flink.version} 284 | compile 285 | 286 | 287 | 288 | 289 | 290 | 291 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialIndices/SpatialIndex.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialIndices; 2 | 3 | public interface SpatialIndex extends java.io.Serializable { 4 | } 5 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialObjects/GeometryCollection.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialObjects; 2 | 3 | import GeoFlink.utils.HelperClass; 4 | import org.apache.flink.api.java.tuple.Tuple2; 5 | import org.locationtech.jts.geom.Coordinate; 6 | import org.locationtech.jts.geom.Geometry; 7 | import org.locationtech.jts.geom.GeometryFactory; 8 | 9 | import java.io.Serializable; 10 | import java.util.ArrayList; 11 | import java.util.List; 12 | 13 | public class GeometryCollection extends SpatialObject implements Serializable { 14 | public org.locationtech.jts.geom.GeometryCollection geometryCollection; 15 | private List listSpatialObject = new ArrayList(); 16 | public Tuple2 boundingBox; 17 | 18 | public GeometryCollection() {}; // required for POJO 19 | 20 | public GeometryCollection(List listSpatialObject, String objID) { 21 | this.geometryCollection = parseSpatialObject(listSpatialObject); 22 | this.objID = objID; 23 | this.listSpatialObject = listSpatialObject; 24 | this.boundingBox = HelperClass.getBoundingBox(geometryCollection); 25 | } 26 | 27 | public GeometryCollection(List listSpatialObject, String objID, long timeStampMillisec) { 28 | this.geometryCollection = parseSpatialObject(listSpatialObject); 29 | this.objID = objID; 30 | this.timeStampMillisec = timeStampMillisec; 31 | this.listSpatialObject = listSpatialObject; 32 | this.boundingBox = HelperClass.getBoundingBox(geometryCollection); 33 | } 34 | 35 | public List getSpatialObjects() { 36 | return this.listSpatialObject; 37 | } 38 | 39 | private org.locationtech.jts.geom.GeometryCollection parseSpatialObject(List listSpatialObject) { 40 | List listGeometry = new ArrayList(); 41 | if (listSpatialObject.size() > 0) { 42 | for (SpatialObject obj : listSpatialObject) { 43 | if (obj instanceof Point) { 44 | listGeometry.add(((Point) obj).point); 45 | } 46 | else if (obj instanceof MultiPoint) { 47 | listGeometry.add(((MultiPoint) obj).multiPoint); 48 | } 49 | else if (obj instanceof MultiPolygon) { 50 | listGeometry.add(((MultiPolygon) obj).getMultiPolygon()); 51 | } 52 | else if (obj instanceof Polygon) { 53 | listGeometry.add(((Polygon) obj).polygon); 54 | } 55 | else if (obj instanceof MultiLineString) { 56 | listGeometry.add(((MultiLineString) obj).getMultiPolygon()); 57 | } 58 | else if (obj instanceof LineString) { 59 | listGeometry.add(((LineString) obj).lineString); 60 | } 61 | } 62 | } 63 | Geometry[] arrGeometry = listGeometry.toArray(new org.locationtech.jts.geom.Geometry[0]); 64 | GeometryFactory geofact = new GeometryFactory(); 65 | return geofact.createGeometryCollection(arrGeometry); 66 | } 67 | 68 | @Override 69 | public String toString() { 70 | try { 71 | String str = "{\"geometry\":"; 72 | str = str + "{\"type\": \"GeometryCollection\", "; 73 | str = str + "\"geometries\": ["; 74 | for (SpatialObject obj: listSpatialObject) { 75 | str = str + "{\"type\": \"" + obj.getClass().getSimpleName() + "\", "; 76 | str = str + "\"coordinates\": ["; 77 | if (obj instanceof Point) { 78 | Point point = (Point)obj; 79 | str = str + point.point.getX() + ", " + point.point.getY() + "]"; 80 | } 81 | else if (obj instanceof MultiPoint) { 82 | MultiPoint multiPoint = (MultiPoint)obj; 83 | Coordinate[] coordinates = multiPoint.multiPoint.getCoordinates(); 84 | for(Coordinate coordinate: coordinates) 85 | str = str + "[" + coordinate.getX() + ", " + coordinate.getY() + "],"; 86 | str = str.substring(0, str.length() - 1); 87 | str += "]"; 88 | } 89 | else if (obj instanceof MultiPolygon) { 90 | MultiPolygon multiPolygon = (MultiPolygon)obj; 91 | org.locationtech.jts.geom.Polygon[] arrPolygon = multiPolygon.arrPolygon; 92 | for (org.locationtech.jts.geom.Polygon p : arrPolygon) { 93 | List> listCoordinate = multiPolygon.getCoordinates(p); 94 | str = str + "["; 95 | for (List l : listCoordinate) { 96 | str = str + "["; 97 | for (Coordinate coordinate : l) 98 | str = str + "[" + coordinate.getX() + ", " + coordinate.getY() + "],"; 99 | if (str.charAt(str.length() - 1) == ',') { 100 | str = str.substring(0, str.length() - 1); 101 | } 102 | str += "],"; 103 | } 104 | str = str.substring(0, str.length() - 1); 105 | str += "],"; 106 | } 107 | str = str.substring(0, str.length() - 1); 108 | str += "]"; 109 | } 110 | else if (obj instanceof Polygon) { 111 | Polygon polygon = (Polygon)obj; 112 | List> listCoordinates = polygon.getCoordinates(); 113 | for (List coordinates : listCoordinates) { 114 | str = str + "["; 115 | for (Coordinate coordinate : coordinates) 116 | str = str + "[" + coordinate.getX() + ", " + coordinate.getY() + "],"; 117 | str = str.substring(0, str.length() - 1); 118 | str = str + "],"; 119 | } 120 | str = str.substring(0, str.length() - 1); 121 | str += "]"; 122 | } 123 | else if (obj instanceof MultiLineString) { 124 | MultiLineString multiLineString = (MultiLineString)obj; 125 | List> listCoordinate = multiLineString.getListCoordinate(); 126 | for (List l: listCoordinate) { 127 | str = str + "["; 128 | for(Coordinate coordinate : l) 129 | str = str + "[" + coordinate.getX() + ", " + coordinate.getY() + "],"; 130 | if (str.charAt(str.length() - 1) == ',') { 131 | str = str.substring(0, str.length() - 1); 132 | } 133 | str += "],"; 134 | } 135 | str = str.substring(0, str.length() - 1); 136 | str += "]"; 137 | } 138 | else if (obj instanceof LineString) { 139 | LineString lineString = (LineString)obj; 140 | Coordinate[] coordinates = lineString.lineString.getCoordinates(); 141 | for(Coordinate coordinate: coordinates) { 142 | str = str + "[" + coordinate.getX() + ", " + coordinate.getY() + "],"; 143 | } 144 | str = str.substring(0, str.length() - 1); 145 | str += "]"; 146 | } 147 | str = str + "}, "; 148 | } 149 | if (str.endsWith(", ")) { 150 | str = str.substring(0, str.length() - 2); 151 | } 152 | str = str + "]}}"; 153 | str = str + ", " + "ObjID: " + this.objID; 154 | str = str + ", " + "TimeStamp(ms): " + this.timeStampMillisec; 155 | // str = str + ", Bounding Box: " + this.boundingBox; 156 | return str; 157 | } 158 | catch(NullPointerException e) 159 | { 160 | e.printStackTrace(); 161 | } 162 | return ""; 163 | } 164 | } 165 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialObjects/LineString.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialObjects; 2 | 3 | import GeoFlink.spatialIndices.UniformGrid; 4 | import GeoFlink.utils.HelperClass; 5 | import org.apache.flink.api.java.tuple.Tuple2; 6 | import org.locationtech.jts.geom.Coordinate; 7 | import org.locationtech.jts.geom.GeometryFactory; 8 | 9 | import java.io.Serializable; 10 | import java.sql.Timestamp; 11 | import java.util.Arrays; 12 | import java.util.HashSet; 13 | import java.util.List; 14 | 15 | public class LineString extends SpatialObject implements Serializable { 16 | 17 | public HashSet gridIDsSet; 18 | public String gridID; 19 | public Tuple2 boundingBox; 20 | public org.locationtech.jts.geom.LineString lineString; 21 | 22 | public LineString() {}; // required for POJO 23 | 24 | public LineString(String objID, List coordinates, HashSet gridIDsSet, String gridID, Tuple2 boundingBox) { 25 | if (coordinates.size() > 1) { 26 | GeometryFactory geofact = new GeometryFactory(); 27 | //create geotools point object 28 | lineString = geofact.createLineString(coordinates.toArray(new Coordinate[0])); 29 | this.gridIDsSet = gridIDsSet; 30 | this.gridID = gridID; 31 | this.objID = objID; 32 | this.boundingBox = boundingBox; 33 | } 34 | } 35 | 36 | public LineString(String objID, List coordinates, HashSet gridIDsSet, String gridID, long timestamp, Tuple2 boundingBox) { 37 | if (coordinates.size() > 1) { 38 | GeometryFactory geofact = new GeometryFactory(); 39 | //create geotools point object 40 | lineString = geofact.createLineString(coordinates.toArray(new Coordinate[0])); 41 | this.gridIDsSet = gridIDsSet; 42 | this.gridID = gridID; 43 | this.objID = objID; 44 | this.boundingBox = boundingBox; 45 | this.timeStampMillisec = timestamp; 46 | } 47 | } 48 | 49 | public LineString(String objID, org.locationtech.jts.geom.LineString lineString, UniformGrid uGrid) { 50 | if (lineString.getNumPoints() > 1) { 51 | GeometryFactory geofact = new GeometryFactory(); 52 | //lineString = geofact.createLineString(coordinates.toArray(new Coordinate[0])); 53 | this.boundingBox = HelperClass.getBoundingBox(lineString); 54 | this.gridIDsSet = HelperClass.assignGridCellID(this.boundingBox, uGrid); 55 | this.gridID = ""; 56 | this.objID = objID; 57 | } 58 | } 59 | 60 | public LineString(String objID, List coordinates, UniformGrid uGrid) { 61 | if (coordinates.size() > 1) { // LineString can only be made with 2 or more points 62 | GeometryFactory geofact = new GeometryFactory(); 63 | lineString = geofact.createLineString(coordinates.toArray(new Coordinate[0])); 64 | this.boundingBox = HelperClass.getBoundingBox(lineString); 65 | this.gridIDsSet = HelperClass.assignGridCellID(this.boundingBox, uGrid); 66 | this.gridID = ""; 67 | this.objID = objID; 68 | } 69 | } 70 | 71 | public LineString(List coordinates, UniformGrid uGrid) { 72 | if (coordinates.size() > 1) { // LineString can only be made with 2 or more points 73 | GeometryFactory geofact = new GeometryFactory(); 74 | lineString = geofact.createLineString(coordinates.toArray(new Coordinate[0])); 75 | this.boundingBox = HelperClass.getBoundingBox(lineString); 76 | this.gridIDsSet = HelperClass.assignGridCellID(this.boundingBox, uGrid); 77 | this.gridID = ""; 78 | this.objID = ""; 79 | } 80 | } 81 | 82 | public LineString(String objID, List coordinates, HashSet gridIDsSet) { 83 | if (coordinates.size() > 1) { // LineString can only be made with 2 or more points 84 | GeometryFactory geofact = new GeometryFactory(); 85 | lineString = geofact.createLineString(coordinates.toArray(new Coordinate[0])); 86 | this.boundingBox = HelperClass.getBoundingBox(lineString); 87 | this.gridIDsSet = gridIDsSet; 88 | this.gridID = ""; 89 | this.objID = objID; 90 | } 91 | } 92 | 93 | public LineString(String objID, List coordinates) { 94 | if (coordinates.size() > 1) { // LineString can only be made with 2 or more points 95 | GeometryFactory geofact = new GeometryFactory(); 96 | lineString = geofact.createLineString(coordinates.toArray(new Coordinate[0])); 97 | this.boundingBox = HelperClass.getBoundingBox(lineString); 98 | this.gridIDsSet = null; 99 | this.gridID = ""; 100 | this.objID = objID; 101 | } 102 | } 103 | public LineString(String objID, List coordinates, long timeStampMillisec, UniformGrid uGrid) { 104 | if (coordinates.size() > 1) { // LineString can only be made with 2 or more points 105 | GeometryFactory geofact = new GeometryFactory(); 106 | lineString = geofact.createLineString(coordinates.toArray(new Coordinate[0])); 107 | this.boundingBox = HelperClass.getBoundingBox(lineString); 108 | this.gridIDsSet = HelperClass.assignGridCellID(this.boundingBox, uGrid); 109 | this.gridID = ""; 110 | this.objID = objID; 111 | this.timeStampMillisec = timeStampMillisec; 112 | } 113 | } 114 | 115 | //{"geometry": {"coordinates": [[[[-73.817854, 40.81909], [-73.817924, 40.819207], [-73.817791, 40.819253], [-73.817785, 40.819255], [-73.817596, 40.81932], [-73.81752, 40.819194], [-73.817521, 40.819193], [-73.817735, 40.819119], [-73.817755, 40.819113], [-73.817771, 40.819107], [-73.817798, 40.819098], [-73.817848, 40.81908], [-73.817852, 40.819087]]]], "type": "LineString"}, "type": "Feature"} 116 | 117 | // To print the point coordinates 118 | @Override 119 | public String toString() { 120 | try{ 121 | String str = "{\"geometry\":{\"coordinates\": ["; 122 | Coordinate[] coordinates = lineString.getCoordinates(); 123 | for(Coordinate coordinate: coordinates) 124 | str = str + "[" + coordinate.getX() + ", " + coordinate.getY() + "],"; 125 | str = str + "], \"type\": \"LineString\"}}"; 126 | str = str + ", " + "ObjID: " + this.objID; 127 | str = str + ", " + this.timeStampMillisec; 128 | //str = str + ", Bounding Box: " + this.boundingBox; 129 | //str = str + ", Grid ID: " + this.gridIDsSet; 130 | //str = str + ", Obj ID: " + this.objID; 131 | return str; 132 | } 133 | catch(NullPointerException e) 134 | { 135 | System.out.print("NullPointerException Caught"); 136 | } 137 | return "Invalid Tuple"; 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialObjects/MultiLineString.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialObjects; 2 | 3 | import GeoFlink.spatialIndices.UniformGrid; 4 | import GeoFlink.utils.HelperClass; 5 | import org.apache.flink.api.java.tuple.Tuple2; 6 | import org.locationtech.jts.geom.Coordinate; 7 | import org.locationtech.jts.geom.GeometryFactory; 8 | 9 | import java.io.Serializable; 10 | import java.util.ArrayList; 11 | import java.util.HashSet; 12 | import java.util.List; 13 | 14 | public class MultiLineString extends LineString implements Serializable { 15 | 16 | private List> listCoordinate = new ArrayList>(); 17 | public org.locationtech.jts.geom.LineString[] arrLineString; 18 | 19 | public MultiLineString() {}; // required for POJO 20 | 21 | 22 | public MultiLineString(String objID, List coordinates, HashSet gridIDsSet, String gridID, Tuple2 boundingBox) { 23 | super(objID, coordinates, gridIDsSet, gridID, boundingBox); 24 | } 25 | 26 | public MultiLineString(String objID, org.locationtech.jts.geom.LineString lineString, UniformGrid uGrid) { 27 | super(objID, lineString, uGrid); 28 | } 29 | 30 | public MultiLineString(String objID, List> listCoordinate, UniformGrid uGrid) { 31 | super(objID, listCoordinate.get(0), uGrid); 32 | this.listCoordinate = listCoordinate; 33 | List listLineString = new ArrayList(); 34 | for (List list : listCoordinate) { 35 | GeometryFactory geofact = new GeometryFactory(); 36 | listLineString.add(geofact.createLineString(list.toArray(new Coordinate[0]))); 37 | } 38 | this.arrLineString = listLineString.toArray(new org.locationtech.jts.geom.LineString[0]); 39 | } 40 | 41 | public MultiLineString(String objID, List> listCoordinate, long timeStampMillisec, UniformGrid uGrid) { 42 | super(objID, listCoordinate.get(0), timeStampMillisec, uGrid); 43 | this.listCoordinate = listCoordinate; 44 | List listLineString = new ArrayList(); 45 | for (List list : listCoordinate) { 46 | GeometryFactory geofact = new GeometryFactory(); 47 | listLineString.add(geofact.createLineString(list.toArray(new Coordinate[0]))); 48 | } 49 | this.arrLineString = listLineString.toArray(new org.locationtech.jts.geom.LineString[0]); 50 | } 51 | 52 | public org.locationtech.jts.geom.MultiLineString getMultiPolygon() { 53 | GeometryFactory geofact = new GeometryFactory(); 54 | return geofact.createMultiLineString(arrLineString); 55 | } 56 | 57 | // To print the point coordinates 58 | @Override 59 | public String toString() { 60 | try{ 61 | String str = "{\"geometry\":{\"coordinates\": ["; 62 | for (List l: listCoordinate) { 63 | str = str + "["; 64 | for(Coordinate coordinate : l) 65 | str = str + "[" + coordinate.getX() + ", " + coordinate.getY() + "],"; 66 | if (str.charAt(str.length() - 1) == ',') { 67 | str = str.substring(0, str.length() - 1); 68 | } 69 | str += "],"; 70 | } 71 | str = str.substring(0, str.length() - 1); 72 | str = str + "], \"type\": \"MultiLineString\"}}"; 73 | str = str + ", " + "ObjID: " + this.objID; 74 | str = str + ", " + this.timeStampMillisec; 75 | //str = str + ", Bounding Box: " + this.boundingBox; 76 | //str = str + ", Grid ID: " + this.gridIDsSet; 77 | //str = str + ", Obj ID: " + this.objID; 78 | return str; 79 | } 80 | catch(NullPointerException e) 81 | { 82 | System.out.print("NullPointerException Caught"); 83 | } 84 | return "Invalid Tuple"; 85 | } 86 | 87 | public List> getListCoordinate() { 88 | return listCoordinate; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialObjects/MultiPoint.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialObjects; 2 | 3 | import GeoFlink.spatialIndices.UniformGrid; 4 | import GeoFlink.utils.HelperClass; 5 | import org.apache.flink.api.java.tuple.Tuple2; 6 | import org.locationtech.jts.geom.Coordinate; 7 | import org.locationtech.jts.geom.GeometryFactory; 8 | 9 | import java.io.Serializable; 10 | import java.util.Date; 11 | import java.util.HashSet; 12 | import java.util.List; 13 | 14 | public class MultiPoint extends SpatialObject implements Serializable { 15 | 16 | public HashSet gridIDsSet; 17 | public String gridID; 18 | public Tuple2 boundingBox; 19 | public org.locationtech.jts.geom.MultiPoint multiPoint; 20 | 21 | public MultiPoint() { 22 | } 23 | 24 | ; // required for POJO 25 | 26 | public MultiPoint(String objID, List coordinates, HashSet gridIDsSet, String gridID, Tuple2 boundingBox) { 27 | GeometryFactory geofact = new GeometryFactory(); 28 | this.multiPoint = geofact.createMultiPointFromCoords(coordinates.toArray(new Coordinate[0])); 29 | this.gridIDsSet = gridIDsSet; 30 | this.gridID = gridID; 31 | this.objID = objID; 32 | this.boundingBox = boundingBox; 33 | this.timeStampMillisec = timeStampMillisec; 34 | } 35 | 36 | public MultiPoint(String objID, List coordinates, HashSet gridIDsSet, String gridID, long timestamp, Tuple2 boundingBox) { 37 | Date date = new Date(); 38 | GeometryFactory geofact = new GeometryFactory(); 39 | this.multiPoint = geofact.createMultiPointFromCoords(coordinates.toArray(new Coordinate[0])); 40 | this.gridIDsSet = gridIDsSet; 41 | this.gridID = gridID; 42 | this.objID = objID; 43 | this.boundingBox = boundingBox; 44 | this.timeStampMillisec = timestamp; 45 | } 46 | 47 | public MultiPoint(String objID, org.locationtech.jts.geom.MultiPoint multiPoint, UniformGrid uGrid) { 48 | this.multiPoint = multiPoint; 49 | this.boundingBox = HelperClass.getBoundingBox(multiPoint); 50 | this.gridIDsSet = HelperClass.assignGridCellID(this.boundingBox, uGrid); 51 | this.gridID = ""; 52 | this.objID = objID; 53 | } 54 | 55 | public MultiPoint(String objID, List coordinates, UniformGrid uGrid) { 56 | GeometryFactory geofact = new GeometryFactory(); 57 | this.multiPoint = geofact.createMultiPointFromCoords(coordinates.toArray(new Coordinate[0])); 58 | this.boundingBox = HelperClass.getBoundingBox(this.multiPoint); 59 | this.gridIDsSet = HelperClass.assignGridCellID(this.boundingBox, uGrid); 60 | this.gridID = ""; 61 | this.objID = objID; 62 | } 63 | 64 | public MultiPoint(List coordinates, UniformGrid uGrid) { 65 | GeometryFactory geofact = new GeometryFactory(); 66 | this.multiPoint = geofact.createMultiPointFromCoords(coordinates.toArray(new Coordinate[0])); 67 | this.boundingBox = HelperClass.getBoundingBox(this.multiPoint); 68 | this.gridIDsSet = HelperClass.assignGridCellID(this.boundingBox, uGrid); 69 | this.gridID = ""; 70 | this.objID = ""; 71 | } 72 | 73 | public MultiPoint(String objID, List coordinates, HashSet gridIDsSet) { 74 | GeometryFactory geofact = new GeometryFactory(); 75 | this.multiPoint = geofact.createMultiPointFromCoords(coordinates.toArray(new Coordinate[0])); 76 | this.boundingBox = HelperClass.getBoundingBox(this.multiPoint); 77 | this.gridIDsSet = gridIDsSet; 78 | this.gridID = ""; 79 | this.objID = objID; 80 | } 81 | 82 | public MultiPoint(String objID, List coordinates) { 83 | GeometryFactory geofact = new GeometryFactory(); 84 | this.multiPoint = geofact.createMultiPointFromCoords(coordinates.toArray(new Coordinate[0])); 85 | this.boundingBox = HelperClass.getBoundingBox(this.multiPoint); 86 | this.gridIDsSet = null; 87 | this.gridID = ""; 88 | this.objID = objID; 89 | } 90 | 91 | public MultiPoint(String objID, List coordinates, long timeStampMillisec, UniformGrid uGrid) { 92 | GeometryFactory geofact = new GeometryFactory(); 93 | this.multiPoint = geofact.createMultiPointFromCoords(coordinates.toArray(new Coordinate[0])); 94 | this.boundingBox = HelperClass.getBoundingBox(this.multiPoint); 95 | this.gridIDsSet = HelperClass.assignGridCellID(this.boundingBox, uGrid); 96 | this.gridID = ""; 97 | this.objID = objID; 98 | this.timeStampMillisec = timeStampMillisec; 99 | } 100 | 101 | @Override 102 | public String toString() { 103 | try{ 104 | String str = "{\"geometry\":{\"coordinates\": ["; 105 | Coordinate[] coordinates = multiPoint.getCoordinates(); 106 | for(Coordinate coordinate: coordinates) 107 | str = str + "[" + coordinate.getX() + ", " + coordinate.getY() + "],"; 108 | str = str.substring(0, str.length() - 1); 109 | str = str + "], \"type\": \"MultiPoint\"}}"; 110 | str = str + ", " + "ObjID: " + this.objID; 111 | str = str + ", " + this.timeStampMillisec; 112 | //str = str + ", Bounding Box: " + this.boundingBox; 113 | //str = str + ", Grid ID: " + this.gridIDsSet; 114 | return str; 115 | } 116 | catch(NullPointerException e) 117 | { 118 | System.out.print("NullPointerException Caught"); 119 | e.printStackTrace(); 120 | return ""; 121 | } 122 | } 123 | 124 | } -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialObjects/MultiPolygon.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialObjects; 2 | 3 | import GeoFlink.spatialIndices.UniformGrid; 4 | import org.apache.flink.api.java.tuple.Tuple2; 5 | import org.locationtech.jts.geom.Coordinate; 6 | import org.locationtech.jts.geom.GeometryFactory; 7 | 8 | import java.io.Serializable; 9 | import java.util.ArrayList; 10 | import java.util.HashSet; 11 | import java.util.List; 12 | 13 | public class MultiPolygon extends Polygon implements Serializable { 14 | 15 | public org.locationtech.jts.geom.Polygon[] arrPolygon; 16 | 17 | public MultiPolygon() {}; // required for POJO 18 | 19 | 20 | 21 | /* 22 | public MultiPolygon(List> coordinates, String objID, HashSet gridIDsSet, String gridID, long timeStampMillisec, Tuple2 boundingBox) { 23 | super(coordinates, objID, gridIDsSet, gridID, timeStampMillisec, boundingBox); 24 | this.listCoordinate = orderPolygonCoordinates(coordinates); 25 | 26 | */ 27 | public MultiPolygon(List>> coordinates, String objID, HashSet gridIDsSet, String gridID, Tuple2 boundingBox) { 28 | super(coordinates.get(0), objID, gridIDsSet, gridID, boundingBox); 29 | this.arrPolygon = createArrPolygon(coordinates); 30 | } 31 | 32 | public MultiPolygon(List>> coordinates, long timeStampMillisec, UniformGrid uGrid) { 33 | super(coordinates.get(0), timeStampMillisec, uGrid); 34 | this.arrPolygon = createArrPolygon(coordinates); 35 | } 36 | 37 | public MultiPolygon(List>> coordinates, UniformGrid uGrid) { 38 | super(coordinates.get(0), uGrid); 39 | this.arrPolygon = createArrPolygon(coordinates); 40 | } 41 | 42 | public MultiPolygon(List>> coordinates, String objID, long timeStampMillisec, UniformGrid uGrid) { 43 | super(objID, coordinates.get(0), timeStampMillisec, uGrid); 44 | this.arrPolygon = createArrPolygon(coordinates); 45 | } 46 | 47 | private org.locationtech.jts.geom.Polygon[] createArrPolygon(List>> coordinates) { 48 | List listPolygon = new ArrayList(); 49 | for (List> listCoordinates : coordinates) { 50 | listPolygon.add(createPolygon(listCoordinates)); 51 | } 52 | return listPolygon.toArray(new org.locationtech.jts.geom.Polygon[0]); 53 | } 54 | 55 | public org.locationtech.jts.geom.MultiPolygon getMultiPolygon() { 56 | GeometryFactory geofact = new GeometryFactory(); 57 | return geofact.createMultiPolygon(arrPolygon); 58 | } 59 | 60 | // To print the point coordinates 61 | @Override 62 | public String toString() { 63 | try { 64 | String str = "{\"geometry\":{\"coordinates\": ["; 65 | for (org.locationtech.jts.geom.Polygon p : arrPolygon) { 66 | List> listCoordinate = getCoordinates(p); 67 | str = str + "["; 68 | for (List l : listCoordinate) { 69 | str = str + "["; 70 | for (Coordinate coordinate : l) 71 | str = str + "[" + coordinate.getX() + ", " + coordinate.getY() + "],"; 72 | if (str.charAt(str.length() - 1) == ',') { 73 | str = str.substring(0, str.length() - 1); 74 | } 75 | str += "],"; 76 | } 77 | str = str.substring(0, str.length() - 1); 78 | str += "],"; 79 | } 80 | str = str.substring(0, str.length() - 1); 81 | str = str + "], \"type\": \"MultiPolygon\"}}"; 82 | str = str + ", " + "ObjID: " + this.objID; 83 | str = str + ", " + this.timeStampMillisec; 84 | //str = str + ", Bounding Box: " + this.boundingBox; 85 | //str = str + ", Grid ID: " + this.gridIDsSet; 86 | //str = str + ", Obj ID: " + this.objID; 87 | return str; 88 | } 89 | catch(NullPointerException e) 90 | { 91 | System.out.print("NullPointerException Caught"); 92 | } 93 | return "Invalid Tuple"; 94 | } 95 | 96 | public List>> getListCoordinate() { 97 | List>> list = new ArrayList>>(); 98 | for (org.locationtech.jts.geom.Polygon p : arrPolygon) { 99 | list.add(getCoordinates(p)); 100 | } 101 | return list; 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialObjects/Point.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 Data Platform Research Team, AIRC, AIST, Japan 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package GeoFlink.spatialObjects; 18 | 19 | import GeoFlink.spatialIndices.UniformGrid; 20 | import GeoFlink.utils.HelperClass; 21 | import org.apache.flink.api.common.functions.MapFunction; 22 | import org.apache.flink.api.common.functions.ReduceFunction; 23 | import org.apache.flink.api.common.functions.RichMapFunction; 24 | import org.apache.flink.api.java.functions.KeySelector; 25 | import org.apache.flink.api.java.tuple.Tuple2; 26 | import org.apache.flink.api.java.tuple.Tuple4; 27 | import org.apache.flink.configuration.Configuration; 28 | import org.apache.flink.dropwizard.metrics.DropwizardMeterWrapper; 29 | import org.apache.flink.metrics.Counter; 30 | import org.apache.flink.metrics.Meter; 31 | import org.apache.flink.shaded.jackson2.com.fasterxml.jackson.databind.node.ObjectNode; 32 | import org.locationtech.jts.geom.Coordinate; 33 | import org.locationtech.jts.geom.GeometryFactory; 34 | 35 | import java.io.Serializable; 36 | import java.util.Arrays; 37 | import java.util.Date; 38 | import java.util.List; 39 | 40 | public class Point extends SpatialObject implements Serializable { 41 | public String gridID; 42 | public org.locationtech.jts.geom.Point point; 43 | public long ingestionTime; 44 | public String eventID; 45 | public String deviceID; 46 | public String userID; 47 | Date date = new Date(); 48 | 49 | public Point() {}; // required for POJO 50 | 51 | public Point(double x, double y, String gridID) { 52 | Date date = new Date(); 53 | GeometryFactory geofact = new GeometryFactory(); 54 | //create geotools point object 55 | point = geofact.createPoint(new Coordinate(x, y)); 56 | this.gridID = gridID; 57 | this.ingestionTime = date.getTime(); 58 | } 59 | 60 | public Point(double x, double y, UniformGrid uGrid) { 61 | Date date = new Date(); 62 | GeometryFactory geofact = new GeometryFactory(); 63 | point = geofact.createPoint(new Coordinate(x, y)); 64 | //assignGridID(uGrid); 65 | this.gridID = HelperClass.assignGridCellID(point.getCoordinate(), uGrid); 66 | this.ingestionTime = date.getTime(); 67 | } 68 | 69 | public Point(double x, double y, long timeStampMillisec, UniformGrid uGrid) { 70 | Date date = new Date(); 71 | GeometryFactory geofact = new GeometryFactory(); 72 | //create geotools point object 73 | point = geofact.createPoint(new Coordinate(x, y)); 74 | this.timeStampMillisec = timeStampMillisec; 75 | //assignGridID(uGrid); 76 | this.gridID = HelperClass.assignGridCellID(point.getCoordinate(), uGrid); 77 | this.ingestionTime = date.getTime(); 78 | } 79 | 80 | public Point(String objID, double x, double y, long timeStampMillisec) { 81 | Date date = new Date(); 82 | GeometryFactory geofact = new GeometryFactory(); 83 | //create geotools point object 84 | point = geofact.createPoint(new Coordinate(x, y)); 85 | this.objID = objID; 86 | this.timeStampMillisec = timeStampMillisec; 87 | this.gridID = ""; 88 | this.ingestionTime = date.getTime(); 89 | } 90 | 91 | public Point(String objID, double x, double y, long timeStampMillisec, UniformGrid uGrid) { 92 | Date date = new Date(); 93 | GeometryFactory geofact = new GeometryFactory(); 94 | //create geotools point object 95 | point = geofact.createPoint(new Coordinate(x, y)); 96 | this.objID = objID; 97 | this.timeStampMillisec = timeStampMillisec; 98 | this.gridID = HelperClass.assignGridCellID(point.getCoordinate(), uGrid); 99 | this.ingestionTime = date.getTime(); 100 | } 101 | 102 | public Point(String objID, double x, double y, long timeStampMillisec, String gridID) { 103 | Date date = new Date(); 104 | GeometryFactory geofact = new GeometryFactory(); 105 | //create geotools point object 106 | point = geofact.createPoint(new Coordinate(x, y)); 107 | this.objID = objID; 108 | this.timeStampMillisec = timeStampMillisec; 109 | this.gridID = gridID; 110 | this.ingestionTime = date.getTime(); 111 | } 112 | 113 | // Point for DEIM App 114 | public Point(String eventID, String deviceID, String userID, long timeStampMillisec, double x, double y) { 115 | Date date = new Date(); 116 | GeometryFactory geofact = new GeometryFactory(); 117 | //create geotools point object 118 | point = geofact.createPoint(new Coordinate(x, y)); 119 | this.eventID = eventID; 120 | this.deviceID = deviceID; 121 | this.userID = userID; 122 | this.timeStampMillisec = timeStampMillisec; 123 | this.gridID = ""; 124 | this.ingestionTime = date.getTime();; 125 | } 126 | 127 | // To print the point coordinates 128 | @Override 129 | public String toString() { 130 | return "[ObjID: " + this.objID + ", " + point.getX() + ", " + point.getY() + ", " + this.gridID + ", " + this.timeStampMillisec + ", " + this.ingestionTime + "]"; 131 | // For DEIM App 132 | // return "[eventID " + this.eventID + ", deviceID: " + this.deviceID + ", userID " + this.userID + ", " + this.timeStampMillisec + "]"; 133 | } 134 | 135 | 136 | //getters 137 | public static class getX implements MapFunction { 138 | @Override 139 | public Double map(Point p) throws Exception { 140 | return p.point.getX(); 141 | } 142 | } 143 | 144 | public static class getY implements MapFunction { 145 | @Override 146 | public Double map(Point p) throws Exception { 147 | return p.point.getY(); 148 | } 149 | } 150 | 151 | 152 | public static class getGridID implements MapFunction { 153 | @Override 154 | public String map(Point p) throws Exception { 155 | return p.gridID; 156 | 157 | } 158 | } 159 | 160 | // rolling grid-wise sum of spatial objects 161 | public static class addSummer implements MapFunction> { 162 | @Override 163 | public Tuple2 map(Point p) throws Exception { 164 | return Tuple2.of(p.gridID, 1); 165 | } 166 | } 167 | 168 | // max-min functions for coordinates 169 | public static class maxY implements ReduceFunction { 170 | @Override 171 | public Point reduce(Point p, Point p1) { 172 | if (p.point.getY() > p1.point.getY()) { 173 | return p; 174 | } else 175 | return p1; 176 | } 177 | } 178 | 179 | public static class minY implements ReduceFunction { 180 | @Override 181 | public Point reduce(Point p, Point p1) { 182 | if (p.point.getY() < p1.point.getY()) { 183 | return p; 184 | } else 185 | return p1; 186 | } 187 | } 188 | 189 | public static class maxX implements ReduceFunction { 190 | @Override 191 | public Point reduce(Point p, Point p1) { 192 | if (p.point.getX() > p1.point.getX()) { 193 | return p; 194 | } else 195 | return p1; 196 | } 197 | } 198 | 199 | public static class minX implements ReduceFunction { 200 | @Override 201 | public Point reduce(Point p, Point p1) { 202 | if (p.point.getX() < p1.point.getX()) { 203 | return p; 204 | } else 205 | return p1; 206 | } 207 | } 208 | 209 | public static class gridIDKeySelector implements KeySelector { 210 | @Override 211 | public String getKey(Point p) throws Exception { 212 | return p.gridID; 213 | } 214 | } 215 | 216 | 217 | 218 | 219 | 220 | public static class distCompCounter extends RichMapFunction { 221 | private transient Counter counter; 222 | 223 | @Override 224 | public void open(Configuration config) { 225 | this.counter = getRuntimeContext() 226 | .getMetricGroup() 227 | .counter("Distance Computation Count"); 228 | } 229 | 230 | @Override 231 | public Point map(Point point) throws Exception { 232 | this.counter.inc(); 233 | return point; 234 | } 235 | } 236 | 237 | public static class throughputMeterPoint extends RichMapFunction { 238 | private transient Meter meter; 239 | 240 | @Override 241 | public void open(Configuration parameters) throws Exception { 242 | super.open(parameters); 243 | this.meter = getRuntimeContext() 244 | .getMetricGroup() 245 | .meter("Throughput-Meter", new DropwizardMeterWrapper(new com.codahale.metrics.Meter())); 246 | } 247 | 248 | @Override 249 | public Point map(Point point) throws Exception { 250 | this.meter.markEvent(); 251 | return point; 252 | } 253 | } 254 | 255 | static class throughputMeterJoin extends RichMapFunction, List>, Object> { 256 | private transient Meter meter; 257 | 258 | @Override 259 | public void open(Configuration parameters) throws Exception { 260 | super.open(parameters); 261 | this.meter = getRuntimeContext() 262 | .getMetricGroup() 263 | .meter("Throughput-Meter", new DropwizardMeterWrapper(new com.codahale.metrics.Meter())); 264 | } 265 | 266 | @Override 267 | public Object map(Tuple4, List> value) throws Exception { 268 | this.meter.markEvent(); 269 | return null; 270 | } 271 | } 272 | } -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialObjects/Polygon.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialObjects; 2 | 3 | import GeoFlink.spatialIndices.UniformGrid; 4 | import GeoFlink.utils.HelperClass; 5 | import org.apache.flink.api.java.tuple.Tuple2; 6 | import org.locationtech.jts.geom.Coordinate; 7 | import org.locationtech.jts.geom.GeometryFactory; 8 | import org.locationtech.jts.geom.LinearRing; 9 | 10 | import java.io.Serializable; 11 | import java.util.ArrayList; 12 | import java.util.Arrays; 13 | import java.util.HashSet; 14 | import java.util.List; 15 | 16 | public class Polygon extends SpatialObject implements Serializable { 17 | 18 | public HashSet gridIDsSet; 19 | public String gridID; 20 | //public long lObjID; 21 | public Tuple2 boundingBox; 22 | public org.locationtech.jts.geom.Polygon polygon; 23 | 24 | public Polygon() {}; // required for POJO 25 | 26 | public Polygon(List> coordinates, String objID, HashSet gridIDsSet, String gridID, Tuple2 boundingBox) { 27 | if (coordinates.size() >= 1 && coordinates.get(0).size() > 3) { 28 | //GeometryFactory geofact = new GeometryFactory(); 29 | //create geotools point object 30 | polygon = createPolygon(coordinates); 31 | this.gridIDsSet = gridIDsSet; 32 | this.gridID = gridID; 33 | this.objID = objID; 34 | this.boundingBox = boundingBox; 35 | this.timeStampMillisec = timeStampMillisec; 36 | } 37 | } 38 | 39 | public Polygon(List> coordinates, String objID, HashSet gridIDsSet, String gridID, long timeStampMillisec, Tuple2 boundingBox) { 40 | if (coordinates.size() >= 1 && coordinates.get(0).size() > 3) { 41 | //GeometryFactory geofact = new GeometryFactory(); 42 | //create geotools point object 43 | polygon = createPolygon(coordinates); 44 | this.gridIDsSet = gridIDsSet; 45 | this.gridID = gridID; 46 | this.objID = objID; 47 | this.boundingBox = boundingBox; 48 | this.timeStampMillisec = timeStampMillisec; 49 | } 50 | } 51 | 52 | public Polygon(List> coordinates, UniformGrid uGrid) { 53 | if (coordinates.size() >= 1 && coordinates.get(0).size() > 3) { 54 | /* 55 | //GeometryFactory geofact = new GeometryFactory(); 56 | polygon = createPolygonArray(coordinates); 57 | this.boundingBox = HelperClass.getBoundingBox(polygon.get(0)); 58 | */ 59 | GeometryFactory geofact = new GeometryFactory(); 60 | polygon = createPolygon(coordinates); 61 | this.boundingBox = HelperClass.getBoundingBox(polygon); 62 | this.gridIDsSet = HelperClass.assignGridCellID(this.boundingBox, uGrid); 63 | this.gridID = ""; 64 | this.objID = null; 65 | } 66 | } 67 | 68 | public Polygon(List> coordinates, long timeStampMillisec, UniformGrid uGrid) { 69 | if (coordinates.size() >= 1 && coordinates.get(0).size() > 3) { 70 | /* 71 | //GeometryFactory geofact = new GeometryFactory(); 72 | polygon = createPolygonArray(coordinates); 73 | this.boundingBox = HelperClass.getBoundingBox(polygon.get(0)); 74 | */ 75 | GeometryFactory geofact = new GeometryFactory(); 76 | polygon = createPolygon(coordinates); 77 | this.boundingBox = HelperClass.getBoundingBox(polygon); 78 | this.timeStampMillisec = timeStampMillisec; 79 | this.gridIDsSet = HelperClass.assignGridCellID(this.boundingBox, uGrid); 80 | this.gridID = ""; 81 | this.objID = null; 82 | } 83 | } 84 | 85 | public Polygon(String objID, List> coordinates, long timeStampMillisec, UniformGrid uGrid) { 86 | if (coordinates.size() >= 1 && coordinates.get(0).size() > 3) { 87 | /* 88 | //GeometryFactory geofact = new GeometryFactory(); 89 | polygon = createPolygonArray(coordinates); 90 | this.boundingBox = HelperClass.getBoundingBox(polygon.get(0)); 91 | */ 92 | GeometryFactory geofact = new GeometryFactory(); 93 | polygon = createPolygon(coordinates); 94 | this.boundingBox = HelperClass.getBoundingBox(polygon); 95 | this.timeStampMillisec = timeStampMillisec; 96 | this.gridIDsSet = HelperClass.assignGridCellID(this.boundingBox, uGrid); 97 | this.gridID = ""; 98 | this.objID = objID; 99 | } 100 | } 101 | 102 | protected List> getCoordinates(org.locationtech.jts.geom.Polygon polygon) { 103 | List> list = new ArrayList(); 104 | list.add(new ArrayList(Arrays.asList(polygon.getExteriorRing().getCoordinates()))); 105 | for (int i = 0; i < polygon.getNumInteriorRing(); i++) { 106 | list.add(new ArrayList(Arrays.asList(polygon.getInteriorRingN(i).getCoordinates()))); 107 | } 108 | return list; 109 | } 110 | 111 | public List> getCoordinates() { 112 | return getCoordinates(this.polygon); 113 | } 114 | 115 | private List createPolygonArray(List> coordinates) { 116 | List listPolygon = new ArrayList(); 117 | GeometryFactory geofact = new GeometryFactory(); 118 | for (List listCoordinate : coordinates) { 119 | if (listCoordinate.size() > 0 && listCoordinate.size() < 4) { 120 | System.out.println("listCoordinate " + listCoordinate); 121 | for (int i = 0; i < 4; i++) { 122 | listCoordinate.add(listCoordinate.get(0)); 123 | } 124 | } 125 | if (!listCoordinate.get(0).equals(listCoordinate.get(listCoordinate.size() - 1))) { 126 | listCoordinate.add(listCoordinate.get(0)); 127 | } 128 | org.locationtech.jts.geom.Polygon poly 129 | = geofact.createPolygon(listCoordinate.toArray(new Coordinate[0])); 130 | 131 | if (listPolygon.size() == 0) { 132 | listPolygon.add(poly); 133 | } else if (listPolygon.get(listPolygon.size() - 1).getArea() >= poly.getArea()) { 134 | listPolygon.add(poly); 135 | } else { 136 | for (int i = 0; i < listPolygon.size(); i++) { 137 | if (listPolygon.get(i).getArea() <= poly.getArea()) { 138 | listPolygon.add(i, poly); 139 | break; 140 | } 141 | } 142 | } 143 | } 144 | return listPolygon; 145 | } 146 | 147 | protected org.locationtech.jts.geom.Polygon createPolygon(List> coordinates) { 148 | GeometryFactory geofact = new GeometryFactory(); 149 | if (coordinates.size() == 1) { 150 | List listCoordinate = coordinates.get(0); 151 | if (!listCoordinate.get(0).equals(listCoordinate.get(listCoordinate.size() - 1))) { 152 | listCoordinate.add(listCoordinate.get(0)); 153 | } 154 | return geofact.createPolygon(listCoordinate.toArray(new Coordinate[0])); 155 | } 156 | else { 157 | List listPolygon = createPolygonArray(coordinates); 158 | LinearRing shell = geofact.createLinearRing(listPolygon.get(0).getCoordinates()); 159 | LinearRing[] holes = new LinearRing[listPolygon.size() - 1]; 160 | for (int i = 0; i < holes.length; i++) { 161 | holes[i] = geofact.createLinearRing(listPolygon.get(i + 1).getCoordinates()); 162 | } 163 | return geofact.createPolygon(shell, holes); 164 | } 165 | } 166 | 167 | 168 | //{"geometry": {"coordinates": [[[[-73.817854, 40.81909], [-73.817924, 40.819207], [-73.817791, 40.819253], [-73.817785, 40.819255], [-73.817596, 40.81932], [-73.81752, 40.819194], [-73.817521, 40.819193], [-73.817735, 40.819119], [-73.817755, 40.819113], [-73.817771, 40.819107], [-73.817798, 40.819098], [-73.817848, 40.81908], [-73.817852, 40.819087], [-73.817854, 40.81909]]]], "type": "MultiPolygon"}, "type": "Feature"} 169 | 170 | // To print the point coordinates 171 | @Override 172 | public String toString() { 173 | try{ 174 | String str = "{\"geometry\":{\"coordinates\": ["; 175 | List> listCoordinates = getCoordinates(); 176 | for (List coordinates : listCoordinates) { 177 | str = str + "["; 178 | for (Coordinate coordinate : coordinates) 179 | str = str + "[" + coordinate.getX() + ", " + coordinate.getY() + "],"; 180 | str = str.substring(0, str.length() - 1); 181 | str = str + "],"; 182 | } 183 | str = str.substring(0, str.length() - 1); 184 | str = str + "], \"type\": \"Polygon\"}}"; 185 | str = str + ", " + "ObjID: " + this.objID; 186 | str = str + ", " + "TimeStamp(ms): " + this.timeStampMillisec; 187 | //str = str + ", Bounding Box: " + this.boundingBox; 188 | //str = str + ", Grid ID: " + this.gridIDsSet; 189 | //str = str + ", Obj ID: " + this.objID; 190 | return str; 191 | } 192 | catch(NullPointerException e) 193 | { 194 | System.out.print("NullPointerException Caught"); 195 | } 196 | return "Invalid Tuple"; 197 | } 198 | 199 | } 200 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialObjects/SpatialObject.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 Data Platform Research Team, AIRC, AIST, Japan 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package GeoFlink.spatialObjects; 18 | 19 | import GeoFlink.utils.HelperClass; 20 | import org.apache.flink.api.common.functions.MapFunction; 21 | import org.apache.flink.api.java.tuple.Tuple2; 22 | import org.locationtech.jts.geom.Coordinate; 23 | import org.locationtech.jts.geom.Geometry; 24 | 25 | import java.io.Serializable; 26 | 27 | public abstract class SpatialObject extends Object implements Serializable { 28 | 29 | public String objID; 30 | //TODO: Assign timestamp 31 | public long timeStampMillisec; 32 | 33 | public SpatialObject() {} 34 | 35 | } 36 | 37 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/QueryConfiguration.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators; 2 | 3 | import java.io.Serializable; 4 | 5 | public class QueryConfiguration implements Serializable { 6 | private QueryType queryType; 7 | private int windowSize = 0; 8 | private int slideStep = 0; 9 | private int allowedLateness = 0; 10 | private boolean approximateQuery = false; 11 | 12 | public QueryConfiguration() {} 13 | 14 | public QueryConfiguration(QueryType queryType) { 15 | this.queryType = queryType; 16 | } 17 | 18 | public QueryType getQueryType() { 19 | return queryType; 20 | } 21 | 22 | public void setQueryType(QueryType queryType) { 23 | this.queryType = queryType; 24 | } 25 | 26 | public int getWindowSize() { 27 | return windowSize; 28 | } 29 | 30 | public void setWindowSize(int windowSize) { 31 | this.windowSize = windowSize; 32 | } 33 | 34 | public int getSlideStep() { 35 | return slideStep; 36 | } 37 | 38 | public void setSlideStep(int slideStep) { 39 | this.slideStep = slideStep; 40 | } 41 | 42 | public int getAllowedLateness() { 43 | return allowedLateness; 44 | } 45 | 46 | public void setAllowedLateness(int allowedLateness) { 47 | this.allowedLateness = allowedLateness; 48 | } 49 | 50 | public boolean isApproximateQuery() { 51 | return approximateQuery; 52 | } 53 | 54 | public void setApproximateQuery(boolean approximateQuery) { 55 | this.approximateQuery = approximateQuery; 56 | } 57 | } -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/QueryType.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators; 2 | 3 | public enum QueryType { 4 | RealTime, 5 | WindowBased, 6 | CountBased, 7 | RealTimeNaive, 8 | } -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/SpatialOperator.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators; 2 | 3 | public abstract class SpatialOperator { 4 | 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/join/JoinQuery.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 Data Platform Research Team, AIRC, AIST, Japan 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package GeoFlink.spatialOperators.join; 18 | 19 | import GeoFlink.spatialIndices.SpatialIndex; 20 | import GeoFlink.spatialIndices.UniformGrid; 21 | import GeoFlink.spatialObjects.LineString; 22 | import GeoFlink.spatialObjects.Point; 23 | import GeoFlink.spatialObjects.Polygon; 24 | import GeoFlink.spatialObjects.SpatialObject; 25 | import GeoFlink.spatialOperators.QueryConfiguration; 26 | import GeoFlink.spatialOperators.SpatialOperator; 27 | import org.apache.flink.api.common.functions.*; 28 | import org.apache.flink.api.java.tuple.Tuple2; 29 | import org.apache.flink.streaming.api.datastream.DataStream; 30 | import org.apache.flink.util.Collector; 31 | 32 | import java.io.Serializable; 33 | import java.util.*; 34 | 35 | public abstract class JoinQuery extends SpatialOperator implements Serializable { 36 | private QueryConfiguration queryConfiguration; 37 | private SpatialIndex spatialIndex1; 38 | private SpatialIndex spatialIndex2; 39 | 40 | public QueryConfiguration getQueryConfiguration() { 41 | return queryConfiguration; 42 | } 43 | 44 | public void setQueryConfiguration(QueryConfiguration queryConfiguration) { 45 | this.queryConfiguration = queryConfiguration; 46 | } 47 | 48 | public SpatialIndex getSpatialIndex1() { 49 | return spatialIndex1; 50 | } 51 | 52 | public void setSpatialIndex1(SpatialIndex spatialIndex) { 53 | this.spatialIndex1 = spatialIndex; 54 | } 55 | 56 | public SpatialIndex getSpatialIndex2() { 57 | return spatialIndex2; 58 | } 59 | 60 | public void setSpatialIndex2(SpatialIndex spatialIndex) { 61 | this.spatialIndex2 = spatialIndex; 62 | } 63 | 64 | public void initializeJoinQuery(QueryConfiguration conf, SpatialIndex index1, SpatialIndex index2) { 65 | this.setQueryConfiguration(conf); 66 | this.setSpatialIndex1(index1); 67 | this.setSpatialIndex2(index2); 68 | } 69 | 70 | public abstract DataStream> run(DataStream ordinaryStream, DataStream queryStream, double queryRadius); 71 | 72 | //Replicate Query Point Stream for each Neighbouring Grid ID 73 | public static DataStream getReplicatedPointQueryStream(DataStream queryPoints, double queryRadius, UniformGrid uGrid){ 74 | 75 | return queryPoints.flatMap(new FlatMapFunction() { 76 | @Override 77 | public void flatMap(Point queryPoint, Collector out) throws Exception { 78 | 79 | // Neighboring cells contain all the cells including Candidate cells, Guaranteed Cells and the query point cell itself 80 | HashSet neighboringCells = uGrid.getNeighboringCells(queryRadius, queryPoint); 81 | 82 | // Create duplicated query points 83 | for (String gridID: neighboringCells) { 84 | //Point p = new Point(queryPoint.point.getX(), queryPoint.point.getY(), gridID); 85 | Point p = new Point(queryPoint.objID, queryPoint.point.getX(), queryPoint.point.getY(), queryPoint.timeStampMillisec, gridID); 86 | out.collect(p); 87 | } 88 | } 89 | }); 90 | } 91 | 92 | //Replicate Query Polygon Stream for each Neighbouring Grid ID 93 | public static DataStream getReplicatedPolygonQueryStream(DataStream queryPolygons, double queryRadius, UniformGrid uGrid){ 94 | 95 | return queryPolygons.flatMap(new RichFlatMapFunction() { 96 | 97 | @Override 98 | public void flatMap(Polygon poly, Collector out) throws Exception { 99 | Set guaranteedNeighboringCells = uGrid.getGuaranteedNeighboringCells(queryRadius, poly); 100 | Set candidateNeighboringCells = uGrid.getCandidateNeighboringCells(queryRadius, poly, guaranteedNeighboringCells); 101 | 102 | // Create duplicated polygon stream for all neighbouring cells based on GridIDs 103 | for (String gridID: guaranteedNeighboringCells) { 104 | //Polygon p = new Polygon(poly.getCoordinates(), uniqueObjID, poly.gridIDsSet, gridID, poly.timeStampMillisec, poly.boundingBox); 105 | Polygon p = new Polygon(poly.getCoordinates(), poly.objID, poly.gridIDsSet, gridID, poly.timeStampMillisec, poly.boundingBox); 106 | out.collect(p); 107 | } 108 | for (String gridID: candidateNeighboringCells) { 109 | //Polygon p = new Polygon(poly.getCoordinates(), uniqueObjID, poly.gridIDsSet, gridID, poly.timeStampMillisec, poly.boundingBox); 110 | Polygon p = new Polygon(poly.getCoordinates(), poly.objID, poly.gridIDsSet, gridID, poly.timeStampMillisec, poly.boundingBox); 111 | out.collect(p); 112 | } 113 | } 114 | }); 115 | } 116 | 117 | public static DataStream getReplicatedLineStringQueryStream(DataStream queryLineString, double queryRadius, UniformGrid uGrid){ 118 | 119 | return queryLineString.flatMap(new RichFlatMapFunction() { 120 | 121 | @Override 122 | public void flatMap(LineString lineString, Collector out) throws Exception { 123 | Set guaranteedNeighboringCells = uGrid.getGuaranteedNeighboringCells(queryRadius, lineString); 124 | Set candidateNeighboringCells = uGrid.getCandidateNeighboringCells(queryRadius, lineString, guaranteedNeighboringCells); 125 | 126 | // Create duplicated polygon stream for all neighbouring cells based on GridIDs 127 | for (String gridID: guaranteedNeighboringCells) { 128 | LineString ls = new LineString(lineString.objID, Arrays.asList(lineString.lineString.getCoordinates().clone()), lineString.gridIDsSet, gridID, lineString.timeStampMillisec, lineString.boundingBox); 129 | out.collect(ls); 130 | } 131 | for (String gridID: candidateNeighboringCells) { 132 | LineString ls = new LineString(lineString.objID, Arrays.asList(lineString.lineString.getCoordinates().clone()), lineString.gridIDsSet, gridID, lineString.timeStampMillisec, lineString.boundingBox); 133 | out.collect(ls); 134 | } 135 | } 136 | }); 137 | } 138 | } -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/join/LineStringLineStringJoinQuery.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators.join; 2 | 3 | import GeoFlink.spatialIndices.SpatialIndex; 4 | import GeoFlink.spatialIndices.UniformGrid; 5 | import GeoFlink.spatialObjects.LineString; 6 | import GeoFlink.spatialOperators.QueryConfiguration; 7 | import GeoFlink.spatialOperators.QueryType; 8 | import GeoFlink.utils.DistanceFunctions; 9 | import GeoFlink.utils.HelperClass; 10 | import org.apache.flink.api.common.functions.FilterFunction; 11 | import org.apache.flink.api.common.functions.JoinFunction; 12 | import org.apache.flink.api.java.functions.KeySelector; 13 | import org.apache.flink.api.java.tuple.Tuple2; 14 | import org.apache.flink.streaming.api.datastream.DataStream; 15 | import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; 16 | import org.apache.flink.streaming.api.windowing.assigners.SlidingProcessingTimeWindows; 17 | import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows; 18 | import org.apache.flink.streaming.api.windowing.time.Time; 19 | 20 | public class LineStringLineStringJoinQuery extends JoinQuery { 21 | public LineStringLineStringJoinQuery(QueryConfiguration conf, SpatialIndex index1, SpatialIndex index2){ 22 | super.initializeJoinQuery(conf, index1, index2); 23 | } 24 | 25 | public DataStream> run(DataStream lineStringStream, DataStream queryStream, double queryRadius) { 26 | boolean approximateQuery = this.getQueryConfiguration().isApproximateQuery(); 27 | int allowedLateness = this.getQueryConfiguration().getAllowedLateness(); 28 | 29 | UniformGrid uGrid = (UniformGrid) this.getSpatialIndex1(); 30 | UniformGrid qGrid = (UniformGrid) this.getSpatialIndex2(); 31 | 32 | //--------------- Real-time - LINESTRING - LINESTRING -----------------// 33 | if(this.getQueryConfiguration().getQueryType() == QueryType.RealTime) { 34 | int omegaJoinDurationSeconds = this.getQueryConfiguration().getWindowSize(); 35 | //return realTime(lineStringStream, queryStream, queryRadius, uGrid, qGrid, omegaJoinDurationSeconds, allowedLateness, approximateQuery); 36 | return windowBased(lineStringStream, queryStream, queryRadius, uGrid, qGrid, omegaJoinDurationSeconds, omegaJoinDurationSeconds, allowedLateness, approximateQuery); 37 | } 38 | 39 | //--------------- Window-based - LINESTRING - LINESTRING -----------------// 40 | else if(this.getQueryConfiguration().getQueryType() == QueryType.WindowBased) { 41 | int windowSize = this.getQueryConfiguration().getWindowSize(); 42 | int slideStep = this.getQueryConfiguration().getSlideStep(); 43 | return windowBased(lineStringStream, queryStream, queryRadius, uGrid, qGrid, windowSize, slideStep, allowedLateness, approximateQuery); 44 | } 45 | 46 | else { 47 | throw new IllegalArgumentException("Not yet support"); 48 | } 49 | } 50 | 51 | // REAL-TIME 52 | /* 53 | private DataStream> realTime(DataStream lineStringStream, DataStream queryStream, double queryRadius, UniformGrid uGrid, UniformGrid qGrid, int omegaJoinDurationSeconds, int allowedLateness, boolean approximateQuery){ 54 | 55 | // Spatial stream with Timestamps and Watermarks 56 | // Max Allowed Lateness: allowedLateness 57 | DataStream queryStreamWithTsAndWm = 58 | queryStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 59 | @Override 60 | public long extractTimestamp(LineString p) { 61 | return p.timeStampMillisec; 62 | } 63 | }).startNewChain(); 64 | 65 | DataStream ordinaryStreamWithTsAndWm = 66 | lineStringStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 67 | @Override 68 | public long extractTimestamp(LineString p) { 69 | return p.timeStampMillisec; 70 | } 71 | }).startNewChain(); 72 | 73 | DataStream replicatedQueryStream = JoinQuery.getReplicatedLineStringQueryStream(queryStreamWithTsAndWm, queryRadius, qGrid); 74 | DataStream replicatedLineStringStream = ordinaryStreamWithTsAndWm.flatMap(new HelperClass.ReplicateLineStringStreamUsingObjID()); 75 | 76 | DataStream> joinOutput = replicatedLineStringStream.join(replicatedQueryStream) 77 | .where(new KeySelector() { 78 | @Override 79 | public String getKey(LineString ls) throws Exception { 80 | return ls.gridID; 81 | } 82 | }).equalTo(new KeySelector() { 83 | @Override 84 | public String getKey(LineString q) throws Exception { 85 | return q.gridID; 86 | } 87 | }).window(TumblingEventTimeWindows.of(Time.seconds(omegaJoinDurationSeconds))) 88 | .apply(new JoinFunction>() { 89 | @Override 90 | public Tuple2 join(LineString ls, LineString q) { 91 | 92 | double distance; 93 | if(approximateQuery) { 94 | distance = DistanceFunctions.getBBoxBBoxMinEuclideanDistance(q.boundingBox, ls.boundingBox); 95 | }else{ 96 | distance = DistanceFunctions.getDistance(q, ls); 97 | } 98 | 99 | if (distance <= queryRadius) { 100 | return Tuple2.of(ls, q); 101 | } else { 102 | return Tuple2.of(null, null); 103 | } 104 | } 105 | }); 106 | 107 | return joinOutput.filter(new FilterFunction>() { 108 | @Override 109 | public boolean filter(Tuple2 value) throws Exception { 110 | return value.f1 != null; 111 | } 112 | }); 113 | } 114 | */ 115 | 116 | // WINDOW BASED 117 | private DataStream> windowBased(DataStream lineStringStream, DataStream queryStream, double queryRadius, UniformGrid uGrid, UniformGrid qGrid, int windowSize, int slideStep, int allowedLateness, boolean approximateQuery){ 118 | 119 | // Spatial stream with Timestamps and Watermarks 120 | // Max Allowed Lateness: allowedLateness 121 | DataStream queryStreamWithTsAndWm = 122 | queryStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 123 | @Override 124 | public long extractTimestamp(LineString p) { 125 | return p.timeStampMillisec; 126 | } 127 | }).startNewChain(); 128 | 129 | DataStream ordinaryStreamWithTsAndWm = 130 | lineStringStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 131 | @Override 132 | public long extractTimestamp(LineString p) { 133 | return p.timeStampMillisec; 134 | } 135 | }).startNewChain(); 136 | 137 | DataStream replicatedQueryStream = JoinQuery.getReplicatedLineStringQueryStream(queryStreamWithTsAndWm, queryRadius, qGrid); 138 | DataStream replicatedLineStringStream = ordinaryStreamWithTsAndWm.flatMap(new HelperClass.ReplicateLineStringStreamUsingObjID()); 139 | 140 | DataStream> joinOutput = replicatedLineStringStream.join(replicatedQueryStream) 141 | .where(new KeySelector() { 142 | @Override 143 | public String getKey(LineString ls) throws Exception { 144 | return ls.gridID; 145 | } 146 | }).equalTo(new KeySelector() { 147 | @Override 148 | public String getKey(LineString q) throws Exception { 149 | return q.gridID; 150 | } 151 | }).window(SlidingProcessingTimeWindows.of(Time.seconds(windowSize), Time.seconds(slideStep))) 152 | .apply(new JoinFunction>() { 153 | @Override 154 | public Tuple2 join(LineString ls, LineString q) { 155 | 156 | double distance; 157 | if(approximateQuery) { 158 | distance = DistanceFunctions.getBBoxBBoxMinEuclideanDistance(q.boundingBox, ls.boundingBox); 159 | }else{ 160 | distance = DistanceFunctions.getDistance(q, ls); 161 | } 162 | 163 | if (distance <= queryRadius) { 164 | return Tuple2.of(ls, q); 165 | } else { 166 | return Tuple2.of(null, null); 167 | } 168 | } 169 | }); 170 | 171 | return joinOutput.filter(new FilterFunction>() { 172 | @Override 173 | public boolean filter(Tuple2 value) throws Exception { 174 | return value.f1 != null; 175 | } 176 | }); 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/join/LineStringPointJoinQuery.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators.join; 2 | 3 | import GeoFlink.spatialIndices.SpatialIndex; 4 | import GeoFlink.spatialIndices.UniformGrid; 5 | import GeoFlink.spatialObjects.LineString; 6 | import GeoFlink.spatialObjects.Point; 7 | import GeoFlink.spatialOperators.QueryConfiguration; 8 | import GeoFlink.spatialOperators.QueryType; 9 | import GeoFlink.utils.DistanceFunctions; 10 | import GeoFlink.utils.HelperClass; 11 | import org.apache.flink.api.common.functions.FilterFunction; 12 | import org.apache.flink.api.common.functions.JoinFunction; 13 | import org.apache.flink.api.java.functions.KeySelector; 14 | import org.apache.flink.api.java.tuple.Tuple2; 15 | import org.apache.flink.streaming.api.datastream.DataStream; 16 | import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; 17 | import org.apache.flink.streaming.api.windowing.assigners.SlidingProcessingTimeWindows; 18 | import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows; 19 | import org.apache.flink.streaming.api.windowing.time.Time; 20 | 21 | public class LineStringPointJoinQuery extends JoinQuery { 22 | public LineStringPointJoinQuery(QueryConfiguration conf, SpatialIndex index1, SpatialIndex index2){ 23 | super.initializeJoinQuery(conf, index1, index2); 24 | } 25 | 26 | public DataStream> run(DataStream lineStringStream, DataStream queryPointStream, double queryRadius) { 27 | boolean approximateQuery = this.getQueryConfiguration().isApproximateQuery(); 28 | int allowedLateness = this.getQueryConfiguration().getAllowedLateness(); 29 | 30 | UniformGrid uGrid = (UniformGrid) this.getSpatialIndex1(); 31 | UniformGrid qGrid = (UniformGrid) this.getSpatialIndex2(); 32 | 33 | //--------------- Real-time - LINESTRING - POINT -----------------// 34 | if(this.getQueryConfiguration().getQueryType() == QueryType.RealTime) { 35 | int omegaJoinDurationSeconds = this.getQueryConfiguration().getWindowSize(); 36 | //return realTime(lineStringStream, queryPointStream, queryRadius, omegaJoinDurationSeconds, uGrid, qGrid, allowedLateness, approximateQuery); 37 | return windowBased(lineStringStream, queryPointStream, queryRadius, omegaJoinDurationSeconds, omegaJoinDurationSeconds, uGrid, qGrid, allowedLateness, approximateQuery); 38 | } 39 | 40 | //--------------- Window-based - LINESTRING - POINT -----------------// 41 | else if(this.getQueryConfiguration().getQueryType() == QueryType.WindowBased) { 42 | int windowSize = this.getQueryConfiguration().getWindowSize(); 43 | int slideStep = this.getQueryConfiguration().getSlideStep(); 44 | return windowBased(lineStringStream, queryPointStream, queryRadius, windowSize, slideStep, uGrid, qGrid, allowedLateness, approximateQuery); 45 | } 46 | 47 | else { 48 | throw new IllegalArgumentException("Not yet support"); 49 | } 50 | } 51 | 52 | // REAL-TIME 53 | /* 54 | private DataStream> realTime(DataStream lineStringStream, DataStream queryPointStream, double queryRadius, int omegaJoinDurationSeconds, UniformGrid uGrid, UniformGrid qGrid, int allowedLateness, boolean approximateQuery){ 55 | 56 | // Spatial stream with Timestamps and Watermarks 57 | // Max Allowed Lateness: allowedLateness 58 | DataStream queryPointStreamWithTsAndWm = 59 | queryPointStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 60 | @Override 61 | public long extractTimestamp(Point p) { 62 | return p.timeStampMillisec; 63 | } 64 | }).startNewChain(); 65 | 66 | DataStream lineStringStreamWithTsAndWm = 67 | lineStringStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 68 | @Override 69 | public long extractTimestamp(LineString ls) { 70 | return ls.timeStampMillisec; 71 | } 72 | }).startNewChain(); 73 | 74 | DataStream replicatedQueryStream = JoinQuery.getReplicatedPointQueryStream(queryPointStreamWithTsAndWm, queryRadius, qGrid); 75 | DataStream replicatedLineStringStream = lineStringStreamWithTsAndWm.flatMap(new HelperClass.ReplicateLineStringStreamUsingObjID()); 76 | 77 | DataStream> joinOutput = replicatedLineStringStream.join(replicatedQueryStream) 78 | .where(new KeySelector() { 79 | @Override 80 | public String getKey(LineString ls) throws Exception { 81 | return ls.gridID; 82 | } 83 | }).equalTo(new KeySelector() { 84 | @Override 85 | public String getKey(Point q) throws Exception { 86 | return q.gridID; 87 | } 88 | }).window(TumblingEventTimeWindows.of(Time.seconds(omegaJoinDurationSeconds))) 89 | .apply(new JoinFunction>() { 90 | @Override 91 | public Tuple2 join(LineString ls, Point q) { 92 | 93 | double distance; 94 | if(approximateQuery) { 95 | distance = DistanceFunctions.getPointLineStringBBoxMinEuclideanDistance(q, ls); 96 | }else{ 97 | distance = DistanceFunctions.getDistance(q, ls); 98 | } 99 | 100 | if (distance <= queryRadius) { 101 | return Tuple2.of(ls, q); 102 | } else { 103 | return Tuple2.of(null, null); 104 | } 105 | } 106 | }); 107 | 108 | return joinOutput.filter(new FilterFunction>() { 109 | @Override 110 | public boolean filter(Tuple2 value) throws Exception { 111 | return value.f1 != null; 112 | } 113 | }); 114 | } 115 | */ 116 | 117 | // WINDOW BASED 118 | private DataStream> windowBased(DataStream lineStringStream, DataStream queryPointStream, double queryRadius, int windowSize, int slideStep, UniformGrid uGrid, UniformGrid qGrid, int allowedLateness, boolean approximateQuery){ 119 | 120 | // Spatial stream with Timestamps and Watermarks 121 | // Max Allowed Lateness: allowedLateness 122 | DataStream queryPointStreamWithTsAndWm = 123 | queryPointStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 124 | @Override 125 | public long extractTimestamp(Point p) { 126 | return p.timeStampMillisec; 127 | } 128 | }).startNewChain(); 129 | 130 | DataStream lineStringStreamWithTsAndWm = 131 | lineStringStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 132 | @Override 133 | public long extractTimestamp(LineString ls) { 134 | return ls.timeStampMillisec; 135 | } 136 | }).startNewChain(); 137 | 138 | DataStream replicatedQueryStream = JoinQuery.getReplicatedPointQueryStream(queryPointStreamWithTsAndWm, queryRadius, qGrid); 139 | DataStream replicatedLineStringStream = lineStringStreamWithTsAndWm.flatMap(new HelperClass.ReplicateLineStringStreamUsingObjID()); 140 | 141 | DataStream> joinOutput = replicatedLineStringStream.join(replicatedQueryStream) 142 | .where(new KeySelector() { 143 | @Override 144 | public String getKey(LineString ls) throws Exception { 145 | return ls.gridID; 146 | } 147 | }).equalTo(new KeySelector() { 148 | @Override 149 | public String getKey(Point q) throws Exception { 150 | return q.gridID; 151 | } 152 | }).window(SlidingProcessingTimeWindows.of(Time.seconds(windowSize), Time.seconds(slideStep))) 153 | .apply(new JoinFunction>() { 154 | @Override 155 | public Tuple2 join(LineString ls, Point q) { 156 | 157 | double distance; 158 | if(approximateQuery) { 159 | distance = DistanceFunctions.getPointLineStringBBoxMinEuclideanDistance(q, ls); 160 | }else{ 161 | distance = DistanceFunctions.getDistance(q, ls); 162 | } 163 | 164 | if (distance <= queryRadius) { 165 | return Tuple2.of(ls, q); 166 | } else { 167 | return Tuple2.of(null, null); 168 | } 169 | } 170 | }); 171 | 172 | return joinOutput.filter(new FilterFunction>() { 173 | @Override 174 | public boolean filter(Tuple2 value) throws Exception { 175 | return value.f1 != null; 176 | } 177 | }); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/join/LineStringPolygonJoinQuery.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators.join; 2 | 3 | import GeoFlink.spatialIndices.SpatialIndex; 4 | import GeoFlink.spatialIndices.UniformGrid; 5 | import GeoFlink.spatialObjects.LineString; 6 | import GeoFlink.spatialObjects.Polygon; 7 | import GeoFlink.spatialOperators.QueryConfiguration; 8 | import GeoFlink.spatialOperators.QueryType; 9 | import GeoFlink.utils.DistanceFunctions; 10 | import GeoFlink.utils.HelperClass; 11 | import org.apache.flink.api.common.functions.FilterFunction; 12 | import org.apache.flink.api.common.functions.JoinFunction; 13 | import org.apache.flink.api.java.functions.KeySelector; 14 | import org.apache.flink.api.java.tuple.Tuple2; 15 | import org.apache.flink.streaming.api.datastream.DataStream; 16 | import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; 17 | import org.apache.flink.streaming.api.windowing.assigners.SlidingProcessingTimeWindows; 18 | import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows; 19 | import org.apache.flink.streaming.api.windowing.time.Time; 20 | 21 | public class LineStringPolygonJoinQuery extends JoinQuery { 22 | public LineStringPolygonJoinQuery(QueryConfiguration conf, SpatialIndex index1, SpatialIndex index2){ 23 | super.initializeJoinQuery(conf, index1, index2); 24 | } 25 | 26 | public DataStream> run(DataStream lineStringStream, DataStream queryStream, double queryRadius) { 27 | boolean approximateQuery = this.getQueryConfiguration().isApproximateQuery(); 28 | int allowedLateness = this.getQueryConfiguration().getAllowedLateness(); 29 | 30 | UniformGrid uGrid = (UniformGrid) this.getSpatialIndex1(); 31 | UniformGrid qGrid = (UniformGrid) this.getSpatialIndex2(); 32 | 33 | //--------------- Real-time - LINESTRING - POLYGON -----------------// 34 | if(this.getQueryConfiguration().getQueryType() == QueryType.RealTime) { 35 | int omegaJoinDurationSeconds = this.getQueryConfiguration().getWindowSize(); 36 | //return realTime(lineStringStream, queryStream, uGrid, qGrid, queryRadius, omegaJoinDurationSeconds, allowedLateness, approximateQuery); 37 | return windowBased(lineStringStream, queryStream, uGrid, qGrid, queryRadius, omegaJoinDurationSeconds, omegaJoinDurationSeconds, allowedLateness, approximateQuery); 38 | } 39 | 40 | //--------------- Window-based - LINESTRING - POLYGON -----------------// 41 | else if(this.getQueryConfiguration().getQueryType() == QueryType.WindowBased) { 42 | int windowSize = this.getQueryConfiguration().getWindowSize(); 43 | int slideStep = this.getQueryConfiguration().getSlideStep(); 44 | return windowBased(lineStringStream, queryStream, uGrid, qGrid, queryRadius, windowSize, slideStep, allowedLateness, approximateQuery); 45 | } 46 | 47 | else { 48 | throw new IllegalArgumentException("Not yet support"); 49 | } 50 | } 51 | 52 | // REAL-TIME 53 | /* 54 | private DataStream> realTime(DataStream lineStringStream, DataStream queryStream, UniformGrid uGrid, UniformGrid qGrid, double queryRadius, int omegaJoinDurationSeconds, int allowedLateness, boolean approximateQuery){ 55 | 56 | // Spatial stream with Timestamps and Watermarks 57 | // Max Allowed Lateness: allowedLateness 58 | DataStream queryStreamWithTsAndWm = 59 | queryStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 60 | @Override 61 | public long extractTimestamp(Polygon p) { 62 | return p.timeStampMillisec; 63 | } 64 | }).startNewChain(); 65 | 66 | DataStream ordinaryStreamWithTsAndWm = 67 | lineStringStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 68 | @Override 69 | public long extractTimestamp(LineString p) { 70 | return p.timeStampMillisec; 71 | } 72 | }).startNewChain(); 73 | 74 | DataStream replicatedQueryStream = JoinQuery.getReplicatedPolygonQueryStream(queryStreamWithTsAndWm, queryRadius, qGrid); 75 | DataStream replicatedLineStringStream = ordinaryStreamWithTsAndWm.flatMap(new HelperClass.ReplicateLineStringStreamUsingObjID()); 76 | 77 | DataStream> joinOutput = replicatedLineStringStream.join(replicatedQueryStream) 78 | .where(new KeySelector() { 79 | @Override 80 | public String getKey(LineString ls) throws Exception { 81 | return ls.gridID; 82 | } 83 | }).equalTo(new KeySelector() { 84 | @Override 85 | public String getKey(Polygon q) throws Exception { 86 | return q.gridID; 87 | } 88 | }).window(TumblingEventTimeWindows.of(Time.seconds(omegaJoinDurationSeconds))) 89 | .apply(new JoinFunction>() { 90 | @Override 91 | public Tuple2 join(LineString ls, Polygon q) { 92 | 93 | double distance; 94 | if(approximateQuery) { 95 | distance = DistanceFunctions.getPolygonLineStringBBoxMinEuclideanDistance(q, ls); 96 | }else{ 97 | distance = DistanceFunctions.getDistance(q, ls); 98 | } 99 | 100 | if (distance <= queryRadius) { 101 | return Tuple2.of(ls, q); 102 | } else { 103 | return Tuple2.of(null, null); 104 | } 105 | } 106 | }); 107 | 108 | return joinOutput.filter(new FilterFunction>() { 109 | @Override 110 | public boolean filter(Tuple2 value) throws Exception { 111 | return value.f1 != null; 112 | } 113 | }); 114 | } 115 | */ 116 | 117 | // WINDOW BASED 118 | private DataStream> windowBased(DataStream lineStringStream, DataStream queryStream, UniformGrid uGrid, UniformGrid qGrid, double queryRadius, int windowSize, int slideStep, int allowedLateness, boolean approximateQuery){ 119 | 120 | // Spatial stream with Timestamps and Watermarks 121 | // Max Allowed Lateness: allowedLateness 122 | DataStream queryStreamWithTsAndWm = 123 | queryStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 124 | @Override 125 | public long extractTimestamp(Polygon p) { 126 | return p.timeStampMillisec; 127 | } 128 | }).startNewChain(); 129 | 130 | DataStream ordinaryStreamWithTsAndWm = 131 | lineStringStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 132 | @Override 133 | public long extractTimestamp(LineString p) { 134 | return p.timeStampMillisec; 135 | } 136 | }).startNewChain(); 137 | 138 | DataStream replicatedQueryStream = JoinQuery.getReplicatedPolygonQueryStream(queryStreamWithTsAndWm, queryRadius, qGrid); 139 | DataStream replicatedLineStringStream = ordinaryStreamWithTsAndWm.flatMap(new HelperClass.ReplicateLineStringStreamUsingObjID()); 140 | 141 | DataStream> joinOutput = replicatedLineStringStream.join(replicatedQueryStream) 142 | .where(new KeySelector() { 143 | @Override 144 | public String getKey(LineString ls) throws Exception { 145 | return ls.gridID; 146 | } 147 | }).equalTo(new KeySelector() { 148 | @Override 149 | public String getKey(Polygon q) throws Exception { 150 | return q.gridID; 151 | } 152 | }).window(SlidingProcessingTimeWindows.of(Time.seconds(windowSize), Time.seconds(slideStep))) 153 | .apply(new JoinFunction>() { 154 | @Override 155 | public Tuple2 join(LineString ls, Polygon q) { 156 | 157 | double distance; 158 | if(approximateQuery) { 159 | distance = DistanceFunctions.getPolygonLineStringBBoxMinEuclideanDistance(q, ls); 160 | }else{ 161 | distance = DistanceFunctions.getDistance(q, ls); 162 | } 163 | 164 | if (distance <= queryRadius) { 165 | return Tuple2.of(ls, q); 166 | } else { 167 | return Tuple2.of(null, null); 168 | } 169 | } 170 | }); 171 | 172 | return joinOutput.filter(new FilterFunction>() { 173 | @Override 174 | public boolean filter(Tuple2 value) throws Exception { 175 | return value.f1 != null; 176 | } 177 | }); 178 | } 179 | } 180 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/join/PointLineStringJoinQuery.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators.join; 2 | 3 | import GeoFlink.spatialIndices.SpatialIndex; 4 | import GeoFlink.spatialIndices.UniformGrid; 5 | import GeoFlink.spatialObjects.LineString; 6 | import GeoFlink.spatialObjects.Point; 7 | import GeoFlink.spatialOperators.QueryConfiguration; 8 | import GeoFlink.spatialOperators.QueryType; 9 | import GeoFlink.utils.DistanceFunctions; 10 | import org.apache.flink.api.common.functions.FilterFunction; 11 | import org.apache.flink.api.common.functions.JoinFunction; 12 | import org.apache.flink.api.java.functions.KeySelector; 13 | import org.apache.flink.api.java.tuple.Tuple2; 14 | import org.apache.flink.streaming.api.datastream.DataStream; 15 | import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; 16 | import org.apache.flink.streaming.api.windowing.assigners.SlidingProcessingTimeWindows; 17 | import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows; 18 | import org.apache.flink.streaming.api.windowing.time.Time; 19 | 20 | public class PointLineStringJoinQuery extends JoinQuery { 21 | public PointLineStringJoinQuery(QueryConfiguration conf, SpatialIndex index1, SpatialIndex index2){ 22 | super.initializeJoinQuery(conf, index1, index2); 23 | } 24 | 25 | public DataStream> run(DataStream ordinaryPointStream, DataStream queryStream, double queryRadius) { 26 | boolean approximateQuery = this.getQueryConfiguration().isApproximateQuery(); 27 | int allowedLateness = this.getQueryConfiguration().getAllowedLateness(); 28 | 29 | UniformGrid uGrid = (UniformGrid) this.getSpatialIndex1(); 30 | UniformGrid qGrid = (UniformGrid) this.getSpatialIndex2(); 31 | 32 | //--------------- Real-time - POINT - LINESTRING -----------------// 33 | if(this.getQueryConfiguration().getQueryType() == QueryType.RealTime) { 34 | int omegaJoinDurationSeconds = this.getQueryConfiguration().getWindowSize(); 35 | //return realTime(ordinaryPointStream, queryStream, queryRadius, uGrid, qGrid, omegaJoinDurationSeconds, allowedLateness, approximateQuery); 36 | return windowBased(ordinaryPointStream, queryStream, queryRadius, uGrid, qGrid, omegaJoinDurationSeconds, omegaJoinDurationSeconds, allowedLateness, approximateQuery); 37 | } 38 | 39 | //--------------- Window-based - POINT - LINESTRING -----------------// 40 | else if(this.getQueryConfiguration().getQueryType() == QueryType.WindowBased) { 41 | int windowSize = this.getQueryConfiguration().getWindowSize(); 42 | int slideStep = this.getQueryConfiguration().getSlideStep(); 43 | return windowBased(ordinaryPointStream, queryStream, queryRadius, uGrid, qGrid, windowSize, slideStep, allowedLateness, approximateQuery); 44 | } 45 | 46 | else { 47 | throw new IllegalArgumentException("Not yet support"); 48 | } 49 | } 50 | 51 | // REAL-TIME 52 | /* 53 | private DataStream> realTime(DataStream ordinaryPointStream, DataStream queryStream, double queryRadius, UniformGrid uGrid, UniformGrid qGrid, int omegaJoinDurationSeconds, int allowedLateness, boolean approximateQuery){ 54 | 55 | // Spatial stream with Timestamps and Watermarks 56 | // Max Allowed Lateness: allowedLateness 57 | DataStream pointStreamWithTsAndWm = 58 | ordinaryPointStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 59 | @Override 60 | public long extractTimestamp(Point p) { 61 | return p.timeStampMillisec; 62 | } 63 | }).startNewChain(); 64 | 65 | DataStream replicatedQueryStream = JoinQuery.getReplicatedLineStringQueryStream(queryStream, queryRadius, qGrid); 66 | 67 | // Spatial stream with Timestamps and Watermarks 68 | // Max Allowed Lateness: allowedLateness 69 | DataStream replicatedQueryStreamWithTsAndWm = 70 | replicatedQueryStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 71 | @Override 72 | public long extractTimestamp(LineString p) { 73 | return p.timeStampMillisec; 74 | } 75 | }).startNewChain(); 76 | 77 | DataStream> joinOutput = pointStreamWithTsAndWm.join(replicatedQueryStreamWithTsAndWm) 78 | .where(new KeySelector() { 79 | @Override 80 | public String getKey(Point p) throws Exception { 81 | return p.gridID; 82 | } 83 | }).equalTo(new KeySelector() { 84 | @Override 85 | public String getKey(LineString q) throws Exception { 86 | return q.gridID; 87 | } 88 | }).window(TumblingEventTimeWindows.of(Time.seconds(omegaJoinDurationSeconds))) 89 | .apply(new JoinFunction>() { 90 | @Override 91 | public Tuple2 join(Point p, LineString q) { 92 | 93 | if (approximateQuery) { // all the candidate neighbors are sent to output 94 | return Tuple2.of(p, q); 95 | } else { 96 | 97 | if (DistanceFunctions.getDistance(p, q) <= queryRadius) { 98 | return Tuple2.of(p, q); 99 | } else { 100 | return Tuple2.of(null, null); 101 | } 102 | 103 | } 104 | } 105 | }); 106 | 107 | return joinOutput.filter(new FilterFunction>() { 108 | @Override 109 | public boolean filter(Tuple2 value) throws Exception { 110 | return value.f1 != null; 111 | } 112 | }); 113 | } 114 | */ 115 | 116 | // WINDOW BASED 117 | private DataStream> windowBased(DataStream ordinaryPointStream, DataStream queryStream, double queryRadius, UniformGrid uGrid, UniformGrid qGrid, int windowSize, int slideStep, int allowedLateness, boolean approximateQuery){ 118 | 119 | // Spatial stream with Timestamps and Watermarks 120 | // Max Allowed Lateness: allowedLateness 121 | DataStream pointStreamWithTsAndWm = 122 | ordinaryPointStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 123 | @Override 124 | public long extractTimestamp(Point p) { 125 | return p.timeStampMillisec; 126 | } 127 | }).startNewChain(); 128 | 129 | DataStream replicatedQueryStream = JoinQuery.getReplicatedLineStringQueryStream(queryStream, queryRadius, qGrid); 130 | 131 | // Spatial stream with Timestamps and Watermarks 132 | // Max Allowed Lateness: allowedLateness 133 | DataStream replicatedQueryStreamWithTsAndWm = 134 | replicatedQueryStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 135 | @Override 136 | public long extractTimestamp(LineString p) { 137 | return p.timeStampMillisec; 138 | } 139 | }).startNewChain(); 140 | 141 | DataStream> joinOutput = pointStreamWithTsAndWm.join(replicatedQueryStreamWithTsAndWm) 142 | .where(new KeySelector() { 143 | @Override 144 | public String getKey(Point p) throws Exception { 145 | return p.gridID; 146 | } 147 | }).equalTo(new KeySelector() { 148 | @Override 149 | public String getKey(LineString q) throws Exception { 150 | return q.gridID; 151 | } 152 | }).window(SlidingProcessingTimeWindows.of(Time.seconds(windowSize), Time.seconds(slideStep))) 153 | .apply(new JoinFunction>() { 154 | @Override 155 | public Tuple2 join(Point p, LineString q) { 156 | 157 | if (approximateQuery) { // all the candidate neighbors are sent to output 158 | return Tuple2.of(p, q); 159 | } else { 160 | 161 | if (DistanceFunctions.getDistance(p, q) <= queryRadius) { 162 | return Tuple2.of(p, q); 163 | } else { 164 | return Tuple2.of(null, null); 165 | } 166 | 167 | } 168 | } 169 | }); 170 | 171 | return joinOutput.filter(new FilterFunction>() { 172 | @Override 173 | public boolean filter(Tuple2 value) throws Exception { 174 | return value.f1 != null; 175 | } 176 | }); 177 | } 178 | } 179 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/join/PolygonLineStringJoinQuery.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators.join; 2 | 3 | import GeoFlink.spatialIndices.SpatialIndex; 4 | import GeoFlink.spatialIndices.UniformGrid; 5 | import GeoFlink.spatialObjects.LineString; 6 | import GeoFlink.spatialObjects.Polygon; 7 | import GeoFlink.spatialOperators.QueryConfiguration; 8 | import GeoFlink.spatialOperators.QueryType; 9 | import GeoFlink.utils.DistanceFunctions; 10 | import GeoFlink.utils.HelperClass; 11 | import org.apache.flink.api.common.functions.FilterFunction; 12 | import org.apache.flink.api.common.functions.JoinFunction; 13 | import org.apache.flink.api.java.functions.KeySelector; 14 | import org.apache.flink.api.java.tuple.Tuple2; 15 | import org.apache.flink.streaming.api.datastream.DataStream; 16 | import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; 17 | import org.apache.flink.streaming.api.windowing.assigners.SlidingProcessingTimeWindows; 18 | import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows; 19 | import org.apache.flink.streaming.api.windowing.time.Time; 20 | 21 | public class PolygonLineStringJoinQuery extends JoinQuery { 22 | public PolygonLineStringJoinQuery(QueryConfiguration conf, SpatialIndex index1, SpatialIndex index2){ 23 | super.initializeJoinQuery(conf, index1, index2); 24 | } 25 | 26 | public DataStream> run(DataStream polygonStream, DataStream queryStream, double queryRadius) { 27 | boolean approximateQuery = this.getQueryConfiguration().isApproximateQuery(); 28 | int allowedLateness = this.getQueryConfiguration().getAllowedLateness(); 29 | 30 | UniformGrid uGrid = (UniformGrid) this.getSpatialIndex1(); 31 | UniformGrid qGrid = (UniformGrid) this.getSpatialIndex2(); 32 | 33 | //--------------- Real-time - POLYGON - LINESTRING -----------------// 34 | if(this.getQueryConfiguration().getQueryType() == QueryType.RealTime) { 35 | int omegaJoinDurationSeconds = this.getQueryConfiguration().getWindowSize(); 36 | //return realTime(polygonStream, queryStream, queryRadius, uGrid, qGrid, omegaJoinDurationSeconds, allowedLateness, approximateQuery); 37 | return windowBased(polygonStream, queryStream, queryRadius, uGrid, qGrid, omegaJoinDurationSeconds, omegaJoinDurationSeconds, allowedLateness, approximateQuery); 38 | } 39 | 40 | //--------------- Window-based - POLYGON - LINESTRING -----------------// 41 | else if(this.getQueryConfiguration().getQueryType() == QueryType.WindowBased) { 42 | int windowSize = this.getQueryConfiguration().getWindowSize(); 43 | int slideStep = this.getQueryConfiguration().getSlideStep(); 44 | return windowBased(polygonStream, queryStream, queryRadius, uGrid, qGrid, windowSize, slideStep, allowedLateness, approximateQuery); 45 | } 46 | 47 | else { 48 | throw new IllegalArgumentException("Not yet support"); 49 | } 50 | } 51 | 52 | // REAL-TIME 53 | /* 54 | private DataStream> realTime(DataStream polygonStream, DataStream queryStream, double queryRadius, UniformGrid uGrid, UniformGrid qGrid, int omegaJoinDurationSeconds, int allowedLateness, boolean approximateQuery){ 55 | 56 | // Spatial stream with Timestamps and Watermarks 57 | // Max Allowed Lateness: allowedLateness 58 | DataStream queryStreamWithTsAndWm = 59 | queryStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 60 | @Override 61 | public long extractTimestamp(LineString p) { 62 | return p.timeStampMillisec; 63 | } 64 | }).startNewChain(); 65 | 66 | DataStream ordinaryStreamWithTsAndWm = 67 | polygonStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 68 | @Override 69 | public long extractTimestamp(Polygon p) { 70 | return p.timeStampMillisec; 71 | } 72 | }).startNewChain(); 73 | 74 | DataStream replicatedQueryStream = JoinQuery.getReplicatedLineStringQueryStream(queryStreamWithTsAndWm, queryRadius, qGrid); 75 | DataStream replicatedOrdinaryStream = ordinaryStreamWithTsAndWm.flatMap(new HelperClass.ReplicatePolygonStreamUsingObjID()); 76 | 77 | DataStream> joinOutput = replicatedOrdinaryStream.join(replicatedQueryStream) 78 | .where(new KeySelector() { 79 | @Override 80 | public String getKey(Polygon poly) throws Exception { 81 | return poly.gridID; 82 | } 83 | }).equalTo(new KeySelector() { 84 | @Override 85 | public String getKey(LineString q) throws Exception { 86 | return q.gridID; 87 | } 88 | }).window(TumblingEventTimeWindows.of(Time.seconds(omegaJoinDurationSeconds))) 89 | .apply(new JoinFunction>() { 90 | @Override 91 | public Tuple2 join(Polygon poly, LineString q) { 92 | 93 | double distance; 94 | if(approximateQuery) { 95 | distance = DistanceFunctions.getPolygonLineStringBBoxMinEuclideanDistance(poly, q); 96 | }else{ 97 | distance = DistanceFunctions.getDistance(poly, q); 98 | } 99 | 100 | if (distance <= queryRadius) { 101 | return Tuple2.of(poly, q); 102 | } else { 103 | return Tuple2.of(null, null); 104 | } 105 | 106 | } 107 | }); 108 | 109 | return joinOutput.filter(new FilterFunction>() { 110 | @Override 111 | public boolean filter(Tuple2 value) throws Exception { 112 | return value.f1 != null; 113 | } 114 | }); 115 | } 116 | 117 | */ 118 | 119 | // WINDOW BASED 120 | private DataStream> windowBased(DataStream polygonStream, DataStream queryStream, double queryRadius, UniformGrid uGrid, UniformGrid qGrid, int windowSize, int slideStep, int allowedLateness, boolean approximateQuery){ 121 | 122 | // Spatial stream with Timestamps and Watermarks 123 | // Max Allowed Lateness: allowedLateness 124 | DataStream queryStreamWithTsAndWm = 125 | queryStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 126 | @Override 127 | public long extractTimestamp(LineString p) { 128 | return p.timeStampMillisec; 129 | } 130 | }).startNewChain(); 131 | 132 | DataStream ordinaryStreamWithTsAndWm = 133 | polygonStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 134 | @Override 135 | public long extractTimestamp(Polygon p) { 136 | return p.timeStampMillisec; 137 | } 138 | }).startNewChain(); 139 | 140 | DataStream replicatedQueryStream = JoinQuery.getReplicatedLineStringQueryStream(queryStreamWithTsAndWm, queryRadius, qGrid); 141 | DataStream replicatedOrdinaryStream = ordinaryStreamWithTsAndWm.flatMap(new HelperClass.ReplicatePolygonStreamUsingObjID()); 142 | 143 | DataStream> joinOutput = replicatedOrdinaryStream.join(replicatedQueryStream) 144 | .where(new KeySelector() { 145 | @Override 146 | public String getKey(Polygon poly) throws Exception { 147 | return poly.gridID; 148 | } 149 | }).equalTo(new KeySelector() { 150 | @Override 151 | public String getKey(LineString q) throws Exception { 152 | return q.gridID; 153 | } 154 | }).window(SlidingProcessingTimeWindows.of(Time.seconds(windowSize), Time.seconds(slideStep))) 155 | .apply(new JoinFunction>() { 156 | @Override 157 | public Tuple2 join(Polygon poly, LineString q) { 158 | 159 | double distance; 160 | if(approximateQuery) { 161 | distance = DistanceFunctions.getPolygonLineStringBBoxMinEuclideanDistance(poly, q); 162 | }else{ 163 | distance = DistanceFunctions.getDistance(poly, q); 164 | } 165 | 166 | if (distance <= queryRadius) { 167 | return Tuple2.of(poly, q); 168 | } else { 169 | return Tuple2.of(null, null); 170 | } 171 | } 172 | }); 173 | 174 | return joinOutput.filter(new FilterFunction>() { 175 | @Override 176 | public boolean filter(Tuple2 value) throws Exception { 177 | return value.f1 != null; 178 | } 179 | }); 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/join/PolygonPointJoinQuery.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators.join; 2 | 3 | import GeoFlink.spatialIndices.SpatialIndex; 4 | import GeoFlink.spatialIndices.UniformGrid; 5 | import GeoFlink.spatialObjects.Point; 6 | import GeoFlink.spatialObjects.Polygon; 7 | import GeoFlink.spatialOperators.QueryConfiguration; 8 | import GeoFlink.spatialOperators.QueryType; 9 | import GeoFlink.utils.DistanceFunctions; 10 | import GeoFlink.utils.HelperClass; 11 | import org.apache.flink.api.common.functions.FilterFunction; 12 | import org.apache.flink.api.common.functions.JoinFunction; 13 | import org.apache.flink.api.java.functions.KeySelector; 14 | import org.apache.flink.api.java.tuple.Tuple2; 15 | import org.apache.flink.streaming.api.datastream.DataStream; 16 | import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; 17 | import org.apache.flink.streaming.api.windowing.assigners.SlidingProcessingTimeWindows; 18 | import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows; 19 | import org.apache.flink.streaming.api.windowing.time.Time; 20 | 21 | public class PolygonPointJoinQuery extends JoinQuery { 22 | public PolygonPointJoinQuery(QueryConfiguration conf, SpatialIndex index1, SpatialIndex index2){ 23 | super.initializeJoinQuery(conf, index1, index2); 24 | } 25 | 26 | public DataStream> run(DataStream polygonStream, DataStream queryPointStream, double queryRadius) { 27 | boolean approximateQuery = this.getQueryConfiguration().isApproximateQuery(); 28 | int allowedLateness = this.getQueryConfiguration().getAllowedLateness(); 29 | 30 | UniformGrid uGrid = (UniformGrid) this.getSpatialIndex1(); 31 | UniformGrid qGrid = (UniformGrid) this.getSpatialIndex2(); 32 | 33 | //--------------- Real-time - POLYGON - POINT -----------------// 34 | if(this.getQueryConfiguration().getQueryType() == QueryType.RealTime) { 35 | int omegaJoinDurationSeconds = this.getQueryConfiguration().getWindowSize(); 36 | //return realTime(polygonStream, queryPointStream, queryRadius, omegaJoinDurationSeconds, uGrid, qGrid, allowedLateness, approximateQuery); 37 | return windowBased(polygonStream, queryPointStream, queryRadius, omegaJoinDurationSeconds, omegaJoinDurationSeconds, uGrid, qGrid, allowedLateness, approximateQuery); 38 | } 39 | 40 | //--------------- Window-based - POLYGON - POINT -----------------// 41 | else if(this.getQueryConfiguration().getQueryType() == QueryType.WindowBased) { 42 | int windowSize = this.getQueryConfiguration().getWindowSize(); 43 | int slideStep = this.getQueryConfiguration().getSlideStep(); 44 | return windowBased(polygonStream, queryPointStream, queryRadius, windowSize, slideStep, uGrid, qGrid, allowedLateness, approximateQuery); 45 | } 46 | 47 | else { 48 | throw new IllegalArgumentException("Not yet support"); 49 | } 50 | } 51 | 52 | // REAL-TIME 53 | /* 54 | private DataStream> realTime(DataStream polygonStream, DataStream queryPointStream, double queryRadius, int omegaJoinDurationSeconds, UniformGrid uGrid, UniformGrid qGrid, int allowedLateness, boolean approximateQuery){ 55 | 56 | // Spatial stream with Timestamps and Watermarks 57 | // Max Allowed Lateness: allowedLateness 58 | DataStream queryPointStreamWithTsAndWm = 59 | queryPointStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 60 | @Override 61 | public long extractTimestamp(Point p) { 62 | return p.timeStampMillisec; 63 | } 64 | }).startNewChain(); 65 | 66 | DataStream polygonStreamWithTsAndWm = 67 | polygonStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 68 | @Override 69 | public long extractTimestamp(Polygon p) { 70 | return p.timeStampMillisec; 71 | } 72 | }).startNewChain(); 73 | 74 | DataStream replicatedQueryStream = JoinQuery.getReplicatedPointQueryStream(queryPointStreamWithTsAndWm, queryRadius, qGrid); 75 | DataStream replicatedPolygonStream = polygonStreamWithTsAndWm.flatMap(new HelperClass.ReplicatePolygonStreamUsingObjID()); 76 | 77 | DataStream> joinOutput = replicatedPolygonStream.join(replicatedQueryStream) 78 | .where(new KeySelector() { 79 | @Override 80 | public String getKey(Polygon poly) throws Exception { 81 | return poly.gridID; 82 | } 83 | }).equalTo(new KeySelector() { 84 | @Override 85 | public String getKey(Point q) throws Exception { 86 | return q.gridID; 87 | } 88 | }).window(TumblingEventTimeWindows.of(Time.seconds(omegaJoinDurationSeconds))) 89 | .apply(new JoinFunction>() { 90 | @Override 91 | public Tuple2 join(Polygon poly, Point q) { 92 | 93 | double distance; 94 | if(approximateQuery) { 95 | distance = DistanceFunctions.getPointPolygonBBoxMinEuclideanDistance(q, poly); 96 | }else{ 97 | distance = DistanceFunctions.getDistance(q, poly); 98 | } 99 | 100 | if (distance <= queryRadius) { 101 | return Tuple2.of(poly, q); 102 | } else { 103 | return Tuple2.of(null, null); 104 | } 105 | 106 | } 107 | }); 108 | 109 | return joinOutput.filter(new FilterFunction>() { 110 | @Override 111 | public boolean filter(Tuple2 value) throws Exception { 112 | return value.f1 != null; 113 | } 114 | }); 115 | } 116 | */ 117 | 118 | // WINDOW BASED 119 | private DataStream> windowBased(DataStream polygonStream, DataStream queryPointStream, double queryRadius, int windowSize, int slideStep, UniformGrid uGrid, UniformGrid qGrid, int allowedLateness, boolean approximateQuery){ 120 | 121 | // Spatial stream with Timestamps and Watermarks 122 | // Max Allowed Lateness: allowedLateness 123 | DataStream queryPointStreamWithTsAndWm = 124 | queryPointStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 125 | @Override 126 | public long extractTimestamp(Point p) { 127 | return p.timeStampMillisec; 128 | } 129 | }).startNewChain(); 130 | 131 | DataStream polygonStreamWithTsAndWm = 132 | polygonStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 133 | @Override 134 | public long extractTimestamp(Polygon p) { 135 | return p.timeStampMillisec; 136 | } 137 | }).startNewChain(); 138 | 139 | DataStream replicatedQueryStream = JoinQuery.getReplicatedPointQueryStream(queryPointStreamWithTsAndWm, queryRadius, qGrid); 140 | DataStream replicatedPolygonStream = polygonStreamWithTsAndWm.flatMap(new HelperClass.ReplicatePolygonStreamUsingObjID()); 141 | 142 | DataStream> joinOutput = replicatedPolygonStream.join(replicatedQueryStream) 143 | .where(new KeySelector() { 144 | @Override 145 | public String getKey(Polygon poly) throws Exception { 146 | return poly.gridID; 147 | } 148 | }).equalTo(new KeySelector() { 149 | @Override 150 | public String getKey(Point q) throws Exception { 151 | return q.gridID; 152 | } 153 | }).window(SlidingProcessingTimeWindows.of(Time.seconds(windowSize), Time.seconds(slideStep))) 154 | .apply(new JoinFunction>() { 155 | @Override 156 | public Tuple2 join(Polygon poly, Point q) { 157 | 158 | double distance; 159 | if(approximateQuery) { 160 | distance = DistanceFunctions.getPointPolygonBBoxMinEuclideanDistance(q, poly); 161 | }else{ 162 | distance = DistanceFunctions.getDistance(q, poly); 163 | } 164 | 165 | if (distance <= queryRadius) { 166 | return Tuple2.of(poly, q); 167 | } else { 168 | return Tuple2.of(null, null); 169 | } 170 | 171 | } 172 | }); 173 | 174 | return joinOutput.filter(new FilterFunction>() { 175 | @Override 176 | public boolean filter(Tuple2 value) throws Exception { 177 | return value.f1 != null; 178 | } 179 | }); 180 | } 181 | } 182 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/join/PolygonPolygonJoinQuery.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators.join; 2 | 3 | import GeoFlink.spatialIndices.SpatialIndex; 4 | import GeoFlink.spatialIndices.UniformGrid; 5 | import GeoFlink.spatialObjects.Polygon; 6 | import GeoFlink.spatialOperators.QueryConfiguration; 7 | import GeoFlink.spatialOperators.QueryType; 8 | import GeoFlink.utils.DistanceFunctions; 9 | import GeoFlink.utils.HelperClass; 10 | import org.apache.flink.api.common.functions.FilterFunction; 11 | import org.apache.flink.api.common.functions.JoinFunction; 12 | import org.apache.flink.api.java.functions.KeySelector; 13 | import org.apache.flink.api.java.tuple.Tuple2; 14 | import org.apache.flink.streaming.api.datastream.DataStream; 15 | import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; 16 | import org.apache.flink.streaming.api.windowing.assigners.SlidingProcessingTimeWindows; 17 | import org.apache.flink.streaming.api.windowing.assigners.TumblingEventTimeWindows; 18 | import org.apache.flink.streaming.api.windowing.time.Time; 19 | 20 | public class PolygonPolygonJoinQuery extends JoinQuery { 21 | public PolygonPolygonJoinQuery(QueryConfiguration conf, SpatialIndex index1, SpatialIndex index2){ 22 | super.initializeJoinQuery(conf, index1, index2); 23 | } 24 | 25 | public DataStream> run(DataStream polygonStream, DataStream queryPolygonStream, double queryRadius) { 26 | boolean approximateQuery = this.getQueryConfiguration().isApproximateQuery(); 27 | int allowedLateness = this.getQueryConfiguration().getAllowedLateness(); 28 | 29 | UniformGrid uGrid = (UniformGrid) this.getSpatialIndex1(); 30 | UniformGrid qGrid = (UniformGrid) this.getSpatialIndex2(); 31 | 32 | //--------------- Real-time - POLYGON - POLYGON -----------------// 33 | if(this.getQueryConfiguration().getQueryType() == QueryType.RealTime) { 34 | int omegaJoinDurationSeconds = this.getQueryConfiguration().getWindowSize(); 35 | //return realTime(polygonStream, queryPolygonStream, uGrid, qGrid, queryRadius, omegaJoinDurationSeconds, allowedLateness, approximateQuery); 36 | return windowBased(polygonStream, queryPolygonStream, uGrid, qGrid, queryRadius, omegaJoinDurationSeconds, omegaJoinDurationSeconds, allowedLateness, approximateQuery); 37 | } 38 | 39 | //--------------- Window-based - POLYGON - POLYGON -----------------// 40 | else if(this.getQueryConfiguration().getQueryType() == QueryType.WindowBased) { 41 | int windowSize = this.getQueryConfiguration().getWindowSize(); 42 | int slideStep = this.getQueryConfiguration().getSlideStep(); 43 | return windowBased(polygonStream, queryPolygonStream, uGrid, qGrid, queryRadius, windowSize, slideStep, allowedLateness, approximateQuery); 44 | } 45 | 46 | else { 47 | throw new IllegalArgumentException("Not yet support"); 48 | } 49 | } 50 | 51 | // REAL-TIME 52 | /* 53 | private DataStream> realTime(DataStream polygonStream, DataStream queryPolygonStream, UniformGrid uGrid, UniformGrid qGrid, double queryRadius, int omegaJoinDurationSeconds, int allowedLateness, boolean approximateQuery){ 54 | 55 | // Spatial stream with Timestamps and Watermarks 56 | // Max Allowed Lateness: allowedLateness 57 | DataStream queryStreamWithTsAndWm = 58 | queryPolygonStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 59 | @Override 60 | public long extractTimestamp(Polygon p) { 61 | return p.timeStampMillisec; 62 | } 63 | }).startNewChain(); 64 | 65 | DataStream ordinaryStreamWithTsAndWm = 66 | polygonStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 67 | @Override 68 | public long extractTimestamp(Polygon p) { 69 | return p.timeStampMillisec; 70 | } 71 | }).startNewChain(); 72 | 73 | DataStream replicatedQueryStream = JoinQuery.getReplicatedPolygonQueryStream(queryStreamWithTsAndWm, queryRadius, qGrid); 74 | DataStream replicatedOrdinaryStream = ordinaryStreamWithTsAndWm.flatMap(new HelperClass.ReplicatePolygonStreamUsingObjID()); 75 | 76 | DataStream> joinOutput = replicatedOrdinaryStream.join(replicatedQueryStream) 77 | .where(new KeySelector() { 78 | @Override 79 | public String getKey(Polygon poly) throws Exception { 80 | return poly.gridID; 81 | } 82 | }).equalTo(new KeySelector() { 83 | @Override 84 | public String getKey(Polygon q) throws Exception { 85 | return q.gridID; 86 | } 87 | }).window(TumblingEventTimeWindows.of(Time.seconds(omegaJoinDurationSeconds))) 88 | .apply(new JoinFunction>() { 89 | @Override 90 | public Tuple2 join(Polygon poly, Polygon q) { 91 | 92 | double distance; 93 | if(approximateQuery) { 94 | distance = DistanceFunctions.getPolygonPolygonBBoxMinEuclideanDistance(q, poly); 95 | }else{ 96 | distance = DistanceFunctions.getDistance(q, poly); 97 | } 98 | 99 | if (distance <= queryRadius) { 100 | return Tuple2.of(poly, q); 101 | } else { 102 | return Tuple2.of(null, null); 103 | } 104 | 105 | } 106 | }); 107 | 108 | return joinOutput.filter(new FilterFunction>() { 109 | @Override 110 | public boolean filter(Tuple2 value) throws Exception { 111 | return value.f1 != null; 112 | } 113 | }); 114 | } 115 | */ 116 | 117 | // WINDOW BASED 118 | private DataStream> windowBased(DataStream polygonStream, DataStream queryPolygonStream, UniformGrid uGrid, UniformGrid qGrid, double queryRadius, int windowSize, int slideStep, int allowedLateness, boolean approximateQuery){ 119 | 120 | // Spatial stream with Timestamps and Watermarks 121 | // Max Allowed Lateness: allowedLateness 122 | DataStream queryStreamWithTsAndWm = 123 | queryPolygonStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 124 | @Override 125 | public long extractTimestamp(Polygon p) { 126 | return p.timeStampMillisec; 127 | } 128 | }).startNewChain(); 129 | 130 | DataStream ordinaryStreamWithTsAndWm = 131 | polygonStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 132 | @Override 133 | public long extractTimestamp(Polygon p) { 134 | return p.timeStampMillisec; 135 | } 136 | }).startNewChain(); 137 | 138 | DataStream replicatedQueryStream = JoinQuery.getReplicatedPolygonQueryStream(queryStreamWithTsAndWm, queryRadius, qGrid); 139 | DataStream replicatedOrdinaryStream = ordinaryStreamWithTsAndWm.flatMap(new HelperClass.ReplicatePolygonStreamUsingObjID()); 140 | 141 | DataStream> joinOutput = replicatedOrdinaryStream.join(replicatedQueryStream) 142 | .where(new KeySelector() { 143 | @Override 144 | public String getKey(Polygon poly) throws Exception { 145 | return poly.gridID; 146 | } 147 | }).equalTo(new KeySelector() { 148 | @Override 149 | public String getKey(Polygon q) throws Exception { 150 | return q.gridID; 151 | } 152 | }).window(SlidingProcessingTimeWindows.of(Time.seconds(windowSize), Time.seconds(slideStep))) 153 | .apply(new JoinFunction>() { 154 | @Override 155 | public Tuple2 join(Polygon poly, Polygon q) { 156 | 157 | double distance; 158 | if(approximateQuery) { 159 | distance = DistanceFunctions.getPolygonPolygonBBoxMinEuclideanDistance(q, poly); 160 | }else{ 161 | distance = DistanceFunctions.getDistance(q, poly); 162 | } 163 | 164 | if (distance <= queryRadius) { 165 | return Tuple2.of(poly, q); 166 | } else { 167 | return Tuple2.of(null, null); 168 | } 169 | 170 | } 171 | }); 172 | 173 | return joinOutput.filter(new FilterFunction>() { 174 | @Override 175 | public boolean filter(Tuple2 value) throws Exception { 176 | return value.f1 != null; 177 | } 178 | }); 179 | } 180 | } 181 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/range/PointLineStringRangeQuery.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators.range; 2 | 3 | import GeoFlink.spatialIndices.SpatialIndex; 4 | import GeoFlink.spatialIndices.UniformGrid; 5 | import GeoFlink.spatialObjects.LineString; 6 | import GeoFlink.spatialObjects.Point; 7 | import GeoFlink.spatialOperators.QueryConfiguration; 8 | import GeoFlink.spatialOperators.QueryType; 9 | import GeoFlink.utils.DistanceFunctions; 10 | import org.apache.flink.api.common.functions.FilterFunction; 11 | import org.apache.flink.api.common.functions.FlatMapFunction; 12 | import org.apache.flink.api.java.functions.KeySelector; 13 | import org.apache.flink.streaming.api.datastream.DataStream; 14 | import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; 15 | import org.apache.flink.streaming.api.functions.windowing.WindowFunction; 16 | import org.apache.flink.streaming.api.windowing.assigners.SlidingProcessingTimeWindows; 17 | import org.apache.flink.streaming.api.windowing.time.Time; 18 | import org.apache.flink.streaming.api.windowing.windows.TimeWindow; 19 | import org.apache.flink.util.Collector; 20 | 21 | import java.util.HashSet; 22 | import java.util.Set; 23 | 24 | public class PointLineStringRangeQuery extends RangeQuery { 25 | public PointLineStringRangeQuery(QueryConfiguration conf, SpatialIndex index) { 26 | super.initializeRangeQuery(conf, index); 27 | } 28 | 29 | public DataStream run(DataStream pointStream, Set queryLineStringSet, double queryRadius) { 30 | boolean approximateQuery = this.getQueryConfiguration().isApproximateQuery(); 31 | int allowedLateness = this.getQueryConfiguration().getAllowedLateness(); 32 | 33 | UniformGrid uGrid = (UniformGrid) this.getSpatialIndex(); 34 | //--------------- Real-time - LINESTRING - POINT -----------------// 35 | if (this.getQueryConfiguration().getQueryType() == QueryType.RealTime) { 36 | //Set guaranteedNeighboringCells = uGrid.getGuaranteedNeighboringCells(queryRadius, ((LineString[])queryLineStringSet.toArray())[0]); 37 | //Set candidateNeighboringCells = uGrid.getCandidateNeighboringCells(queryRadius, ((LineString[])queryLineStringSet.toArray())[0], guaranteedNeighboringCells); 38 | 39 | HashSet candidateNeighboringCells = new HashSet<>(); 40 | HashSet guaranteedNeighboringCells = new HashSet<>(); 41 | 42 | for(LineString lineString:queryLineStringSet) { 43 | //Set guaranteedNeighboringCells = uGrid.getGuaranteedNeighboringCells(queryRadius, ((Polygon[]) queryPolygonSet.toArray())[0]); 44 | //Set candidateNeighboringCells = uGrid.getCandidateNeighboringCells(queryRadius, ((Polygon[]) queryPolygonSet.toArray())[0], guaranteedNeighboringCells); 45 | guaranteedNeighboringCells.addAll(uGrid.getGuaranteedNeighboringCells(queryRadius, lineString)); 46 | candidateNeighboringCells.addAll(uGrid.getCandidateNeighboringCells(queryRadius, lineString, guaranteedNeighboringCells)); 47 | //candidateNeighboringCells.addAll(guaranteedNeighboringCells); 48 | } 49 | 50 | DataStream filteredPoints = pointStream.filter(new FilterFunction() { 51 | @Override 52 | public boolean filter(Point point) throws Exception { 53 | return ((candidateNeighboringCells.contains(point.gridID)) || (guaranteedNeighboringCells.contains(point.gridID))); 54 | } 55 | }).startNewChain(); 56 | 57 | return filteredPoints.keyBy(new KeySelector() { 58 | @Override 59 | public String getKey(Point p) throws Exception { 60 | return p.gridID; 61 | } 62 | }).flatMap(new FlatMapFunction() { 63 | @Override 64 | public void flatMap(Point point, Collector collector) throws Exception { 65 | 66 | if (guaranteedNeighboringCells.contains(point.gridID)) 67 | collector.collect(point); 68 | else { 69 | 70 | double distance; 71 | for(LineString ls:queryLineStringSet) { 72 | 73 | if (approximateQuery) { 74 | distance = DistanceFunctions.getPointLineStringBBoxMinEuclideanDistance(point, ls); 75 | } else { 76 | distance = DistanceFunctions.getDistance(point, ls); 77 | } 78 | 79 | if (distance <= queryRadius) { 80 | collector.collect(point); 81 | break; 82 | } 83 | 84 | /* 85 | if (approximateQuery) { 86 | distance = DistanceFunctions.getBBoxBBoxMinEuclideanDistance(((LineString[]) queryLineStringSet.toArray())[0].boundingBox, lineString.boundingBox); 87 | } else { 88 | distance = DistanceFunctions.getDistance(((LineString[]) queryLineStringSet.toArray())[0], lineString); 89 | } 90 | 91 | if (distance <= queryRadius) { 92 | collector.collect(lineString); 93 | }*/ 94 | } 95 | } 96 | } 97 | }).name("Real-time - LINESTRING - POINT"); 98 | } 99 | //--------------- Window-based - LINESTRING - POINT -----------------// 100 | else if (this.getQueryConfiguration().getQueryType() == QueryType.WindowBased) { 101 | int windowSize = this.getQueryConfiguration().getWindowSize(); 102 | int slideStep = this.getQueryConfiguration().getSlideStep(); 103 | 104 | HashSet candidateNeighboringCells = new HashSet<>(); 105 | HashSet guaranteedNeighboringCells = new HashSet<>(); 106 | 107 | for(LineString lineString:queryLineStringSet) { 108 | //Set guaranteedNeighboringCells = uGrid.getGuaranteedNeighboringCells(queryRadius, ((Polygon[]) queryPolygonSet.toArray())[0]); 109 | //Set candidateNeighboringCells = uGrid.getCandidateNeighboringCells(queryRadius, ((Polygon[]) queryPolygonSet.toArray())[0], guaranteedNeighboringCells); 110 | guaranteedNeighboringCells.addAll(uGrid.getGuaranteedNeighboringCells(queryRadius, lineString)); 111 | candidateNeighboringCells.addAll(uGrid.getCandidateNeighboringCells(queryRadius, lineString, guaranteedNeighboringCells)); 112 | //candidateNeighboringCells.addAll(guaranteedNeighboringCells); 113 | } 114 | 115 | DataStream pointStreamWithTsAndWm = 116 | pointStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 117 | @Override 118 | public long extractTimestamp(Point p) { 119 | return p.timeStampMillisec; 120 | } 121 | }).startNewChain(); 122 | 123 | DataStream filteredPoints = pointStreamWithTsAndWm.filter(new FilterFunction() { 124 | @Override 125 | public boolean filter(Point point) throws Exception { 126 | return ((candidateNeighboringCells.contains(point.gridID)) || (guaranteedNeighboringCells.contains(point.gridID))); 127 | } 128 | }); 129 | 130 | return filteredPoints.keyBy(new KeySelector() { 131 | @Override 132 | public String getKey(Point p) throws Exception { 133 | return p.gridID; 134 | } 135 | }).window(SlidingProcessingTimeWindows.of(Time.seconds(windowSize), Time.seconds(slideStep))) 136 | .apply(new WindowFunction() { 137 | @Override 138 | public void apply(String gridID, TimeWindow timeWindow, Iterable pointIterator, Collector neighbors) throws Exception { 139 | for (Point point : pointIterator) { 140 | if (guaranteedNeighboringCells.contains(point.gridID)) 141 | neighbors.collect(point); 142 | else { 143 | 144 | double distance; 145 | for(LineString ls:queryLineStringSet) { 146 | 147 | if (approximateQuery) { 148 | distance = DistanceFunctions.getPointLineStringBBoxMinEuclideanDistance(point, ls); 149 | } else { 150 | distance = DistanceFunctions.getDistance(point, ls); 151 | } 152 | 153 | if (distance <= queryRadius) { 154 | neighbors.collect(point); 155 | break; 156 | } 157 | 158 | /* 159 | if (approximateQuery) { 160 | distance = DistanceFunctions.getBBoxBBoxMinEuclideanDistance(((LineString[]) queryLineStringSet.toArray())[0].boundingBox, lineString.boundingBox); 161 | } else { 162 | distance = DistanceFunctions.getDistance(((LineString[]) queryLineStringSet.toArray())[0], lineString); 163 | } 164 | 165 | if (distance <= queryRadius) { 166 | collector.collect(lineString); 167 | }*/ 168 | } 169 | } 170 | } 171 | } 172 | }).name("Window-based - LINESTRING - POINT"); 173 | } else { 174 | throw new IllegalArgumentException("Not yet support"); 175 | } 176 | } 177 | } 178 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/range/RangeQuery.java: -------------------------------------------------------------------------------- 1 | /* 2 | Copyright 2020 Data Platform Research Team, AIRC, AIST, Japan 3 | 4 | Licensed under the Apache License, Version 2.0 (the "License"); 5 | you may not use this file except in compliance with the License. 6 | You may obtain a copy of the License at 7 | 8 | http://www.apache.org/licenses/LICENSE-2.0 9 | 10 | Unless required by applicable law or agreed to in writing, software 11 | distributed under the License is distributed on an "AS IS" BASIS, 12 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | See the License for the specific language governing permissions and 14 | limitations under the License. 15 | */ 16 | 17 | package GeoFlink.spatialOperators.range; 18 | 19 | import GeoFlink.spatialIndices.SpatialIndex; 20 | import GeoFlink.spatialObjects.LineString; 21 | import GeoFlink.spatialObjects.Polygon; 22 | import GeoFlink.spatialObjects.SpatialObject; 23 | import GeoFlink.spatialOperators.QueryConfiguration; 24 | import GeoFlink.spatialOperators.SpatialOperator; 25 | import org.apache.flink.api.common.functions.*; 26 | import org.apache.flink.api.common.state.*; 27 | import org.apache.flink.api.java.tuple.Tuple2; 28 | import org.apache.flink.streaming.api.datastream.DataStream; 29 | import org.apache.flink.streaming.api.windowing.triggers.Trigger; 30 | import org.apache.flink.streaming.api.windowing.triggers.TriggerResult; 31 | import org.apache.flink.streaming.api.windowing.windows.TimeWindow; 32 | import org.apache.flink.util.Collector; 33 | 34 | import java.io.Serializable; 35 | import java.util.*; 36 | 37 | public abstract class RangeQuery extends SpatialOperator implements Serializable { 38 | private QueryConfiguration queryConfiguration; 39 | private SpatialIndex spatialIndex; 40 | 41 | public QueryConfiguration getQueryConfiguration() { 42 | return queryConfiguration; 43 | } 44 | 45 | public void setQueryConfiguration(QueryConfiguration queryConfiguration) { 46 | this.queryConfiguration = queryConfiguration; 47 | } 48 | 49 | public SpatialIndex getSpatialIndex() { 50 | return spatialIndex; 51 | } 52 | 53 | public void setSpatialIndex(SpatialIndex spatialIndex) { 54 | this.spatialIndex = spatialIndex; 55 | } 56 | 57 | public void initializeRangeQuery(QueryConfiguration conf, SpatialIndex index){ 58 | this.setQueryConfiguration(conf); 59 | this.setSpatialIndex(index); 60 | } 61 | 62 | public abstract DataStream run(DataStream stream, Set obj, double queryRadius); 63 | 64 | protected class PolygonTrigger extends Trigger { 65 | 66 | private int slideStep; 67 | ValueStateDescriptor firstWindowDesc = new ValueStateDescriptor("isFirstWindow", Boolean.class); 68 | 69 | //ctor 70 | public PolygonTrigger(){} 71 | public PolygonTrigger(int slideStep){ 72 | this.slideStep = slideStep; 73 | } 74 | 75 | @Override 76 | public TriggerResult onElement(Polygon polygon, long l, TimeWindow timeWindow, TriggerContext triggerContext) throws Exception { 77 | 78 | ValueState firstWindow = triggerContext.getPartitionedState(firstWindowDesc); 79 | //Using states manage the first window, so that all the tuples can be processed 80 | if(firstWindow.value() == null){ 81 | firstWindow.update(false); 82 | return TriggerResult.CONTINUE; 83 | } 84 | else { 85 | if (polygon.timeStampMillisec >= (timeWindow.getEnd() - (slideStep * 1000L))) 86 | return TriggerResult.CONTINUE; // Do nothing 87 | else 88 | return TriggerResult.PURGE; // Delete 89 | } 90 | } 91 | @Override 92 | public TriggerResult onProcessingTime(long l, TimeWindow timeWindow, TriggerContext triggerContext) throws Exception { 93 | return TriggerResult.FIRE; 94 | } 95 | @Override 96 | public TriggerResult onEventTime(long l, TimeWindow timeWindow, TriggerContext triggerContext) throws Exception { 97 | return TriggerResult.FIRE; 98 | } 99 | @Override 100 | public void clear(TimeWindow timeWindow, TriggerContext triggerContext) throws Exception { 101 | } 102 | } 103 | 104 | // Misc Classes 105 | protected class GetCellsFilteredByLayer extends RichFilterFunction> 106 | { 107 | private final HashSet CellIDs; // CellIDs are input parameters 108 | 109 | //ctor 110 | public GetCellsFilteredByLayer(HashSet CellIDs) 111 | { 112 | this.CellIDs = CellIDs; 113 | } 114 | 115 | @Override 116 | public boolean filter(Tuple2 cellIDCount) throws Exception 117 | { 118 | return CellIDs.contains(cellIDCount.f0); 119 | } 120 | } 121 | 122 | protected class CellBasedLineStringFlatMap implements FlatMapFunction{ 123 | 124 | Set neighboringCells = new HashSet(); 125 | 126 | //ctor 127 | public CellBasedLineStringFlatMap() {} 128 | public CellBasedLineStringFlatMap(Set neighboringCells) { 129 | this.neighboringCells = neighboringCells; 130 | } 131 | 132 | @Override 133 | public void flatMap(LineString lineString, Collector output) throws Exception { 134 | 135 | // If a polygon is either a CN or GN 136 | LineString outputLineString; 137 | for(String gridID: lineString.gridIDsSet) { 138 | if (neighboringCells.contains(gridID)) { 139 | outputLineString = new LineString(lineString.objID, Arrays.asList(lineString.lineString.getCoordinates()), lineString.gridIDsSet, gridID, lineString.boundingBox); 140 | output.collect(outputLineString); 141 | return; 142 | } 143 | } 144 | } 145 | } 146 | } -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/tAggregate/PointTAggregateQuery.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators.tAggregate; 2 | 3 | import GeoFlink.spatialObjects.Point; 4 | import GeoFlink.spatialOperators.QueryConfiguration; 5 | import GeoFlink.spatialOperators.QueryType; 6 | 7 | import org.apache.flink.api.common.functions.FilterFunction; 8 | import org.apache.flink.api.java.tuple.Tuple4; 9 | import org.apache.flink.api.java.tuple.Tuple5; 10 | import org.apache.flink.streaming.api.datastream.DataStream; 11 | import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; 12 | import org.apache.flink.streaming.api.windowing.assigners.SlidingEventTimeWindows; 13 | import org.apache.flink.streaming.api.windowing.time.Time; 14 | 15 | import java.util.HashMap; 16 | 17 | 18 | public class PointTAggregateQuery extends TAggregateQuery { 19 | public PointTAggregateQuery(QueryConfiguration conf) { 20 | super.initializeKNNQuery(conf); 21 | } 22 | 23 | public DataStream run(DataStream pointStream, String aggregateFunction, String windowType, Long inactiveTrajDeletionThreshold) { 24 | boolean approximateQuery = this.getQueryConfiguration().isApproximateQuery(); 25 | int allowedLateness = this.getQueryConfiguration().getAllowedLateness(); 26 | 27 | //--------------- Real-time - POINT -----------------// 28 | if (this.getQueryConfiguration().getQueryType() == QueryType.RealTime) { 29 | return realTime(pointStream, aggregateFunction, inactiveTrajDeletionThreshold); 30 | } 31 | 32 | //--------------- Window-based - POINT -----------------// 33 | else if (this.getQueryConfiguration().getQueryType() == QueryType.WindowBased) { 34 | int windowSize = this.getQueryConfiguration().getWindowSize(); 35 | int windowSlideStep = this.getQueryConfiguration().getSlideStep(); 36 | return windowBased(pointStream, aggregateFunction, windowType, windowSize, windowSlideStep); 37 | } 38 | 39 | else { 40 | throw new IllegalArgumentException("Not yet support"); 41 | } 42 | } 43 | 44 | // REAL-TIME 45 | private DataStream, Long>> realTime(DataStream pointStream, String aggregateFunction, Long inactiveTrajDeletionThreshold) { 46 | 47 | // Filtering out the cells which do not fall into the grid cells 48 | DataStream spatialStreamWithoutNullCellID = pointStream.filter(new FilterFunction() { 49 | @Override 50 | public boolean filter(GeoFlink.spatialObjects.Point p) throws Exception { 51 | return (p.gridID != null); 52 | } 53 | }); 54 | 55 | //DataStream>> cWindowedCellBasedStayTime = spatialStreamWithoutNullCellID 56 | 57 | return spatialStreamWithoutNullCellID 58 | .keyBy(new gridCellKeySelector()) 59 | .map(new THeatmapAggregateQueryMapFunction(aggregateFunction, inactiveTrajDeletionThreshold)); 60 | } 61 | 62 | // WINDOW BASED 63 | private DataStream>> windowBased(DataStream pointStream, String aggregateFunction, String windowType, long windowSize, long windowSlideStep) { 64 | 65 | // Filtering out the cells which do not fall into the grid cells 66 | DataStream spatialStreamWithoutNullCellID = pointStream.filter(new FilterFunction() { 67 | @Override 68 | public boolean filter(Point p) throws Exception { 69 | return (p.gridID != null); 70 | } 71 | }); 72 | 73 | // Spatial stream with Timestamps and Watermarks 74 | // Max Allowed Lateness: windowSize 75 | DataStream spatialStreamWithTsAndWm = 76 | spatialStreamWithoutNullCellID.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(windowSize)) { 77 | @Override 78 | public long extractTimestamp(Point p) { 79 | return p.timeStampMillisec; 80 | } 81 | }); 82 | 83 | if(windowType.equalsIgnoreCase("COUNT")){ 84 | 85 | return spatialStreamWithTsAndWm 86 | .keyBy(new gridCellKeySelector()) 87 | .countWindow(windowSize, windowSlideStep) 88 | .process(new CountWindowProcessFunction(aggregateFunction)).name("Count Window"); 89 | 90 | } 91 | else { // Default TIME Window 92 | 93 | return spatialStreamWithTsAndWm 94 | .keyBy(new gridCellKeySelector()) 95 | //.window(SlidingProcessingTimeWindows.of(Time.seconds(windowSize), Time.seconds(windowSlideStep))) 96 | .window(SlidingEventTimeWindows.of(Time.seconds(windowSize), Time.seconds(windowSlideStep))) 97 | .process(new TimeWindowProcessFunction(aggregateFunction)).name("Time Window"); 98 | } 99 | } 100 | } 101 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/tFilter/PointTFilterQuery.java: -------------------------------------------------------------------------------- 1 | //package GeoFlink.SpatialOperator; 2 | 3 | package GeoFlink.spatialOperators.tFilter; 4 | 5 | import GeoFlink.spatialObjects.SpatialObject; 6 | import GeoFlink.spatialObjects.LineString; 7 | import GeoFlink.spatialObjects.Point; 8 | import GeoFlink.spatialOperators.QueryConfiguration; 9 | import GeoFlink.spatialOperators.QueryType; 10 | import org.apache.flink.api.common.functions.FilterFunction; 11 | import org.apache.flink.api.java.functions.KeySelector; 12 | import org.apache.flink.streaming.api.datastream.DataStream; 13 | import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; 14 | import org.apache.flink.streaming.api.functions.windowing.WindowFunction; 15 | import org.apache.flink.streaming.api.windowing.assigners.SlidingProcessingTimeWindows; 16 | import org.apache.flink.streaming.api.windowing.time.Time; 17 | import org.apache.flink.streaming.api.windowing.windows.TimeWindow; 18 | import org.apache.flink.util.Collector; 19 | import org.locationtech.jts.geom.Coordinate; 20 | 21 | import java.util.LinkedList; 22 | import java.util.List; 23 | import java.util.Set; 24 | 25 | public class PointTFilterQuery extends TFilterQuery { 26 | public PointTFilterQuery(QueryConfiguration conf) { 27 | super.initializeKNNQuery(conf); 28 | } 29 | 30 | public DataStream run(DataStream pointStream, Set trajIDSet) { 31 | 32 | //--------------- Real-time - POINT -----------------// 33 | if (this.getQueryConfiguration().getQueryType() == QueryType.RealTime) { 34 | return realTime(pointStream, trajIDSet); 35 | } 36 | 37 | //--------------- Window-based - POINT -----------------// 38 | else if (this.getQueryConfiguration().getQueryType() == QueryType.WindowBased) { 39 | int windowSize = this.getQueryConfiguration().getWindowSize(); 40 | int windowSlideStep = this.getQueryConfiguration().getSlideStep(); 41 | return windowBased(pointStream, trajIDSet, windowSize, windowSlideStep); 42 | } 43 | 44 | else { 45 | throw new IllegalArgumentException("Not yet support"); 46 | } 47 | } 48 | 49 | // REAL-TIME 50 | private DataStream realTime(DataStream pointStream, Set trajIDSet){ 51 | 52 | // Spatial stream with Timestamps and Watermarks 53 | // Max Allowed Lateness: windowSize 54 | DataStream pointStreamWithTsAndWm = 55 | pointStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(0)) { 56 | @Override 57 | public long extractTimestamp(Point p) { 58 | return p.timeStampMillisec; 59 | } 60 | }); 61 | 62 | return pointStreamWithTsAndWm.filter(new FilterFunction() { 63 | @Override 64 | public boolean filter(Point point) throws Exception { 65 | 66 | //Date date = new Date(); 67 | //System.out.println(date.getTime() - point.ingestionTime); 68 | if (trajIDSet.size() > 0) 69 | return ((trajIDSet.contains(point.objID))); 70 | else 71 | return true; 72 | } 73 | }).name("TrajIDFilterQuery"); 74 | } 75 | 76 | // WINDOW BASED 77 | private DataStream windowBased(DataStream pointStream, Set trajIDSet, int windowSize, int windowSlideStep){ 78 | 79 | // Spatial stream with Timestamps and Watermarks 80 | // Max Allowed Lateness: windowSize 81 | DataStream pointStreamWithTsAndWm = 82 | pointStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(0)) { 83 | @Override 84 | public long extractTimestamp(Point p) { 85 | return p.timeStampMillisec; 86 | } 87 | }); 88 | 89 | DataStream filteredStream = pointStreamWithTsAndWm.filter(new FilterFunction() { 90 | @Override 91 | public boolean filter(Point point) throws Exception { 92 | if (trajIDSet.size() > 0) 93 | return ((trajIDSet.contains(point.objID))); 94 | else 95 | return true; 96 | } 97 | }).name("TrajIDFilterQueryWindowed"); 98 | 99 | //filteredStream.print(); 100 | DataStream windowedTrajectories = filteredStream.keyBy(new KeySelector() { 101 | 102 | @Override 103 | public String getKey(Point p) throws Exception { 104 | return p.objID; 105 | } 106 | }).window(SlidingProcessingTimeWindows.of(Time.seconds(windowSize), Time.seconds(windowSlideStep))) 107 | .apply(new WindowFunction() { 108 | List coordinateList = new LinkedList<>(); 109 | @Override 110 | public void apply(String objID, TimeWindow timeWindow, Iterable pointIterator, Collector trajectory) throws Exception { 111 | 112 | coordinateList.clear(); 113 | for (Point p : pointIterator) { 114 | coordinateList.add(new Coordinate(p.point.getX(), p.point.getY())); 115 | } 116 | LineString ls = new LineString(objID, coordinateList); 117 | trajectory.collect(ls); 118 | } 119 | }).name("TrajIDFilterWindowedQuery"); 120 | 121 | return windowedTrajectories; 122 | } 123 | } 124 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/tFilter/TFilterQuery.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators.tFilter; 2 | 3 | import GeoFlink.spatialObjects.SpatialObject; 4 | import GeoFlink.spatialOperators.QueryConfiguration; 5 | import GeoFlink.spatialOperators.SpatialOperator; 6 | import org.apache.flink.streaming.api.datastream.DataStream; 7 | 8 | import java.io.Serializable; 9 | import java.util.Set; 10 | 11 | public abstract class TFilterQuery extends SpatialOperator implements Serializable { 12 | private QueryConfiguration queryConfiguration; 13 | 14 | public QueryConfiguration getQueryConfiguration() { 15 | return queryConfiguration; 16 | } 17 | 18 | public void setQueryConfiguration(QueryConfiguration queryConfiguration) { 19 | this.queryConfiguration = queryConfiguration; 20 | } 21 | 22 | public void initializeKNNQuery(QueryConfiguration conf){ 23 | this.setQueryConfiguration(conf); 24 | } 25 | 26 | public abstract DataStream run(DataStream stream, Set trajIDSet); 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/tKnn/TKNNQuery.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators.tKnn; 2 | 3 | import GeoFlink.spatialIndices.SpatialIndex; 4 | 5 | import GeoFlink.spatialObjects.Point; 6 | import GeoFlink.spatialObjects.SpatialObject; 7 | import GeoFlink.spatialOperators.QueryConfiguration; 8 | import GeoFlink.spatialOperators.SpatialOperator; 9 | import GeoFlink.utils.DistanceFunctions; 10 | import org.apache.flink.api.java.tuple.Tuple2; 11 | import org.apache.flink.streaming.api.datastream.DataStream; 12 | import org.apache.flink.streaming.api.functions.windowing.WindowFunction; 13 | import org.apache.flink.streaming.api.windowing.triggers.Trigger; 14 | import org.apache.flink.streaming.api.windowing.triggers.TriggerResult; 15 | import org.apache.flink.streaming.api.windowing.windows.TimeWindow; 16 | import org.apache.flink.util.Collector; 17 | 18 | import java.io.Serializable; 19 | import java.util.*; 20 | 21 | public abstract class TKNNQuery extends SpatialOperator implements Serializable { 22 | private QueryConfiguration queryConfiguration; 23 | private SpatialIndex spatialIndex; 24 | static long dCounter = 0; 25 | 26 | public QueryConfiguration getQueryConfiguration() { 27 | return queryConfiguration; 28 | } 29 | 30 | public void setQueryConfiguration(QueryConfiguration queryConfiguration) { 31 | this.queryConfiguration = queryConfiguration; 32 | } 33 | 34 | public SpatialIndex getSpatialIndex() { 35 | return spatialIndex; 36 | } 37 | 38 | public void setSpatialIndex(SpatialIndex spatialIndex) { 39 | this.spatialIndex = spatialIndex; 40 | } 41 | 42 | public void initializeTKNNQuery(QueryConfiguration conf, SpatialIndex index){ 43 | this.setQueryConfiguration(conf); 44 | this.setSpatialIndex(index); 45 | } 46 | 47 | public abstract DataStream run(DataStream ordinaryStream, K obj, double queryRadius, Integer k); 48 | 49 | // Returns Tuple2 50 | protected class kNNEvaluationWindowed implements WindowFunction, String, TimeWindow> { 51 | 52 | //ctor 53 | public kNNEvaluationWindowed(){} 54 | 55 | public kNNEvaluationWindowed(Point qPoint, Integer k){ 56 | this.queryPoint = qPoint; 57 | this.k = k; 58 | } 59 | 60 | Point queryPoint; 61 | Integer k; 62 | Map objMap = new HashMap(); 63 | HashMap sortedObjMap = new LinkedHashMap<>(); 64 | 65 | @Override 66 | public void apply(String gridID, TimeWindow timeWindow, Iterable inputTuples, Collector> outputStream) throws Exception { 67 | 68 | objMap.clear(); 69 | sortedObjMap.clear(); 70 | 71 | // compute the distance of all trajectory points w.r.t. query point and return the kNN (trajectory ID, distance) pairs 72 | for (Point p : inputTuples) { 73 | 74 | Double newDistance = DistanceFunctions.getPointPointEuclideanDistance(p.point.getX(), p.point.getY(), queryPoint.point.getX(), queryPoint.point.getY()); 75 | Double existingDistance = objMap.get(p.objID); 76 | 77 | if (existingDistance == null) { // if object with the given ObjID does not already exist 78 | objMap.put(p.objID, newDistance); 79 | } else { // object already exist 80 | if (newDistance < existingDistance) 81 | objMap.replace(p.objID, newDistance); 82 | } 83 | } 84 | 85 | // Sorting the map by value 86 | List> list = new LinkedList<>(objMap.entrySet()); 87 | Collections.sort(list, Comparator.comparing(o -> o.getValue())); 88 | 89 | for (Map.Entry map : list) { 90 | sortedObjMap.put(map.getKey(), map.getValue()); 91 | } 92 | 93 | // Logic to return the kNN (trajectory ID, distance) pairs 94 | int counter = 0; 95 | for (Map.Entry entry : sortedObjMap.entrySet()) { 96 | if (counter == k) break; 97 | outputStream.collect(Tuple2.of(entry.getKey(), entry.getValue())); 98 | counter++; 99 | } 100 | } 101 | } 102 | 103 | // Returns Tuple2 104 | protected class kNNEvaluationRealtime implements WindowFunction, String, TimeWindow> { 105 | 106 | //ctor 107 | public kNNEvaluationRealtime(){} 108 | 109 | public kNNEvaluationRealtime(Point qPoint, Integer k){ 110 | this.queryPoint = qPoint; 111 | this.k = k; 112 | } 113 | 114 | Point queryPoint; 115 | Integer k; 116 | Map objIDDistMap = new HashMap(); 117 | Map objIDPointMap = new HashMap(); 118 | HashMap sortedObjMap = new LinkedHashMap<>(); 119 | 120 | @Override 121 | public void apply(String gridID, TimeWindow timeWindow, Iterable inputTuples, Collector> outputStream) throws Exception { 122 | 123 | objIDDistMap.clear(); 124 | objIDPointMap.clear(); 125 | sortedObjMap.clear(); 126 | 127 | // compute the distance of all trajectory points w.r.t. query point and return the kNN (trajectory ID, distance) pairs 128 | for (Point p : inputTuples) { 129 | 130 | //dCounter += 1; 131 | //System.out.println("counter " + dCounter); 132 | 133 | Double newDistance = DistanceFunctions.getPointPointEuclideanDistance(p.point.getX(), p.point.getY(), queryPoint.point.getX(), queryPoint.point.getY()); 134 | Double existingDistance = objIDDistMap.get(p.objID); 135 | 136 | if (existingDistance == null) { // if object with the given ObjID does not already exist 137 | objIDDistMap.put(p.objID, newDistance); 138 | objIDPointMap.put(p.objID, p); 139 | } else { // object already exist 140 | if (newDistance < existingDistance) { 141 | objIDDistMap.replace(p.objID, newDistance); 142 | objIDPointMap.replace(p.objID, p); 143 | } 144 | } 145 | } 146 | 147 | // Sorting the map by value 148 | List> list = new LinkedList<>(objIDDistMap.entrySet()); 149 | Collections.sort(list, Comparator.comparing(o -> o.getValue())); 150 | 151 | for (Map.Entry map : list) { 152 | sortedObjMap.put(map.getKey(), map.getValue()); 153 | } 154 | 155 | // Logic to return the kNN (trajectory ID, distance) pairs 156 | int counter = 0; 157 | for (Map.Entry entry : sortedObjMap.entrySet()) { 158 | if (counter == k) break; 159 | outputStream.collect(Tuple2.of(objIDPointMap.get(entry.getKey()), entry.getValue())); 160 | counter++; 161 | } 162 | } 163 | } 164 | 165 | // TimeWindow Trigger 166 | protected class realTimeWindowTrigger extends Trigger { 167 | 168 | @Override 169 | public TriggerResult onElement(Point point, long l, TimeWindow timeWindow, TriggerContext triggerContext) throws Exception { 170 | return TriggerResult.FIRE; 171 | //return TriggerResult.CONTINUE; 172 | } 173 | 174 | @Override 175 | public TriggerResult onProcessingTime(long l, TimeWindow timeWindow, TriggerContext triggerContext) throws Exception { 176 | return TriggerResult.FIRE; 177 | } 178 | 179 | @Override 180 | public TriggerResult onEventTime(long l, TimeWindow timeWindow, TriggerContext triggerContext) throws Exception { 181 | return TriggerResult.FIRE; 182 | } 183 | 184 | @Override 185 | public void clear(TimeWindow timeWindow, TriggerContext triggerContext) throws Exception { 186 | 187 | } 188 | } 189 | 190 | // TimeWindowAll Trigger 191 | protected class realTimeWindowAllTrigger extends Trigger, TimeWindow> { 192 | 193 | @Override 194 | public TriggerResult onElement(Tuple2 pointDoubleTuple2, long l, TimeWindow timeWindow, TriggerContext triggerContext) throws Exception { 195 | return TriggerResult.FIRE; 196 | //return TriggerResult.CONTINUE; 197 | } 198 | 199 | @Override 200 | public TriggerResult onProcessingTime(long l, TimeWindow timeWindow, TriggerContext triggerContext) throws Exception { 201 | return TriggerResult.FIRE; 202 | } 203 | 204 | @Override 205 | public TriggerResult onEventTime(long l, TimeWindow timeWindow, TriggerContext triggerContext) throws Exception { 206 | return TriggerResult.FIRE; 207 | } 208 | 209 | @Override 210 | public void clear(TimeWindow timeWindow, TriggerContext triggerContext) throws Exception { 211 | 212 | } 213 | } 214 | 215 | } 216 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/tRange/PointPolygonTRangeQuery.java: -------------------------------------------------------------------------------- 1 | 2 | package GeoFlink.spatialOperators.tRange; 3 | 4 | import GeoFlink.spatialObjects.LineString; 5 | import GeoFlink.spatialObjects.Point; 6 | import GeoFlink.spatialObjects.Polygon; 7 | import GeoFlink.spatialObjects.SpatialObject; 8 | import GeoFlink.spatialOperators.QueryConfiguration; 9 | import GeoFlink.spatialOperators.QueryType; 10 | import org.apache.flink.api.common.functions.FilterFunction; 11 | import org.apache.flink.api.common.functions.JoinFunction; 12 | import org.apache.flink.api.java.functions.KeySelector; 13 | import org.apache.flink.streaming.api.datastream.DataStream; 14 | import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; 15 | import org.apache.flink.streaming.api.functions.windowing.WindowFunction; 16 | import org.apache.flink.streaming.api.windowing.assigners.SlidingProcessingTimeWindows; 17 | import org.apache.flink.streaming.api.windowing.time.Time; 18 | import org.apache.flink.streaming.api.windowing.windows.TimeWindow; 19 | import org.apache.flink.util.Collector; 20 | import org.locationtech.jts.geom.Coordinate; 21 | 22 | import java.util.HashSet; 23 | import java.util.LinkedList; 24 | import java.util.List; 25 | import java.util.Set; 26 | 27 | public class PointPolygonTRangeQuery extends TRangeQuery { 28 | public PointPolygonTRangeQuery(QueryConfiguration conf) { 29 | super.initializeTRangeQuery(conf); 30 | } 31 | 32 | public DataStream run(DataStream pointStream, Set polygonSet) { 33 | int allowedLateness = this.getQueryConfiguration().getAllowedLateness(); 34 | 35 | //--------------- Real-time - POINT - POLYGON -----------------// 36 | if (this.getQueryConfiguration().getQueryType() == QueryType.RealTime) { 37 | return realTime(pointStream, polygonSet); 38 | } 39 | 40 | //--------------- Window-based - POINT - POLYGON -----------------// 41 | else if(this.getQueryConfiguration().getQueryType() == QueryType.WindowBased) { 42 | int windowSize = this.getQueryConfiguration().getWindowSize(); 43 | int windowSlideStep = this.getQueryConfiguration().getSlideStep(); 44 | return windowBased(pointStream, polygonSet, windowSize, windowSlideStep, allowedLateness); 45 | } 46 | 47 | else { 48 | throw new IllegalArgumentException("Not yet support"); 49 | } 50 | } 51 | 52 | // REAL-TIME 53 | private DataStream realTime(DataStream pointStream, Set polygonSet) { 54 | 55 | HashSet polygonsGridCellIDs = new HashSet<>(); 56 | // Making an integrated set of all the polygon's grid cell IDs 57 | for (Polygon poly : polygonSet) { 58 | polygonsGridCellIDs.addAll(poly.gridIDsSet); 59 | } 60 | 61 | // Filtering based on grid-cell ID 62 | DataStream filteredStream = pointStream.filter(new FilterFunction() { 63 | @Override 64 | public boolean filter(Point p) throws Exception { 65 | return ((polygonsGridCellIDs.contains(p.gridID))); 66 | } 67 | }); 68 | 69 | // Perform keyBy to logically distribute streams by trajectoryID and then check if a point lies within a polygon or nor 70 | return filteredStream.keyBy(new KeySelector() { 71 | @Override 72 | public String getKey(Point p) throws Exception { 73 | return p.objID; 74 | } 75 | }).filter(new FilterFunction() { 76 | @Override 77 | public boolean filter(Point p) throws Exception { 78 | for (Polygon poly : polygonSet) { 79 | //counter += 1; 80 | //System.out.println("counter " + counter); 81 | if (poly.polygon.contains(p.point.getEnvelope())) // Polygon contains the point 82 | return true; 83 | } 84 | return false; // Polygon does not contain the point 85 | } 86 | }); 87 | } 88 | 89 | // WINDOW BASED 90 | private DataStream windowBased(DataStream pointStream, Set polygonSet, int windowSize, int windowSlideStep, int allowedLateness){ 91 | 92 | HashSet polygonsGridCellIDs = new HashSet<>(); 93 | 94 | // Making an integrated set of all the polygon's grid cell IDs 95 | for (Polygon poly: polygonSet) { 96 | polygonsGridCellIDs.addAll(poly.gridIDsSet); 97 | } 98 | 99 | // Spatial stream with Timestamps and Watermarks 100 | // Max Allowed Lateness: allowedLateness 101 | DataStream pointStreamWithTsAndWm = 102 | pointStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(allowedLateness)) { 103 | @Override 104 | public long extractTimestamp(Point p) { 105 | return p.timeStampMillisec; 106 | } 107 | }); 108 | 109 | // Filtering based on grid-cell ID 110 | DataStream filteredStream = pointStreamWithTsAndWm.filter(new FilterFunction() { 111 | @Override 112 | public boolean filter(Point p) throws Exception { 113 | return ((polygonsGridCellIDs.contains(p.gridID))); 114 | } 115 | }); 116 | 117 | // Identifying trajectories' point which fulfill range query criteria 118 | DataStream trajIDStream = filteredStream.keyBy(new KeySelector() { 119 | @Override 120 | public String getKey(Point p) throws Exception { 121 | return p.objID; 122 | } 123 | }).window(SlidingProcessingTimeWindows.of(Time.seconds(windowSize), Time.seconds(windowSlideStep))).apply(new WindowFunction() { 124 | List coordinateList = new LinkedList<>(); 125 | @Override 126 | public void apply(String objID, TimeWindow timeWindow, Iterable pointIterator, Collector output) throws Exception { 127 | // all the points in the pointIterator belong to one trajectory, so even if a single point fulfills range query criteria, the whole trajectory does 128 | for (Point p:pointIterator) { 129 | for (Polygon poly : polygonSet) { 130 | if (poly.polygon.contains(p.point.getEnvelope())) { // Polygon contains the point 131 | output.collect(objID); 132 | return; 133 | } 134 | } 135 | } 136 | } 137 | }); 138 | 139 | // Joining the original stream with the trajID stream - output contains only trajectories within given range 140 | DataStream joinedStream = pointStreamWithTsAndWm.join(trajIDStream).where(new KeySelector() { 141 | @Override 142 | public String getKey(Point p) throws Exception { 143 | return p.objID; 144 | } 145 | }).equalTo(new KeySelector() { 146 | @Override 147 | public String getKey(String trajID) throws Exception { 148 | return trajID; 149 | } 150 | }).window(SlidingProcessingTimeWindows.of(Time.seconds(windowSize), Time.seconds(windowSlideStep))) 151 | .apply(new JoinFunction() { 152 | @Override 153 | public Point join(Point p, String trajID) { 154 | return p; 155 | } 156 | }); 157 | 158 | // Construct window based sub-trajectories 159 | return joinedStream.keyBy(new KeySelector() { 160 | @Override 161 | public String getKey(Point p) throws Exception { 162 | return p.objID; 163 | } 164 | }).window(SlidingProcessingTimeWindows.of(Time.seconds(windowSize), Time.seconds(windowSlideStep))) 165 | .apply(new WindowFunction() { 166 | List coordinateList = new LinkedList<>(); 167 | @Override 168 | public void apply(String objID, TimeWindow timeWindow, Iterable pointIterator, Collector trajectory) throws Exception { 169 | coordinateList.clear(); 170 | for (Point p : pointIterator) { 171 | coordinateList.add(new Coordinate(p.point.getX(), p.point.getY())); 172 | } 173 | LineString ls = new LineString(objID, coordinateList); 174 | trajectory.collect(ls); 175 | } 176 | }); 177 | } 178 | } -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/tRange/TRangeQuery.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators.tRange; 2 | 3 | import GeoFlink.spatialObjects.Point; 4 | import GeoFlink.spatialObjects.Polygon; 5 | import GeoFlink.spatialObjects.SpatialObject; 6 | import GeoFlink.spatialOperators.QueryConfiguration; 7 | import GeoFlink.spatialOperators.SpatialOperator; 8 | import org.apache.flink.api.common.functions.FilterFunction; 9 | import org.apache.flink.api.java.functions.KeySelector; 10 | import org.apache.flink.streaming.api.datastream.DataStream; 11 | 12 | import java.io.Serializable; 13 | import java.util.HashSet; 14 | import java.util.Set; 15 | 16 | public abstract class TRangeQuery extends SpatialOperator implements Serializable { 17 | private QueryConfiguration queryConfiguration; 18 | public QueryConfiguration getQueryConfiguration() { 19 | return queryConfiguration; 20 | } 21 | //static long counter = 0; 22 | 23 | public void setQueryConfiguration(QueryConfiguration queryConfiguration) { 24 | this.queryConfiguration = queryConfiguration; 25 | } 26 | 27 | public void initializeTRangeQuery(QueryConfiguration conf){ 28 | this.setQueryConfiguration(conf); 29 | } 30 | 31 | public abstract DataStream run(DataStream ordinaryStream, Set objSet); 32 | 33 | public static DataStream realTimeNaive(Set polygonSet, DataStream pointStream){ 34 | 35 | HashSet polygonsGridCellIDs = new HashSet<>(); 36 | // Making an integrated set of all the polygon's grid cell IDs 37 | for (Polygon poly: polygonSet) { 38 | polygonsGridCellIDs.addAll(poly.gridIDsSet); 39 | } 40 | 41 | // Perform keyBy to logically distribute streams by trajectoryID and then check if a point lies within a polygon or nor 42 | DataStream keyedStream = pointStream.keyBy(new KeySelector() { 43 | @Override 44 | public String getKey(Point p) throws Exception { 45 | return p.objID; 46 | } 47 | }).filter(new FilterFunction() { 48 | @Override 49 | public boolean filter(Point p) throws Exception { 50 | 51 | for (Polygon poly: polygonSet) { 52 | //counter += 1; 53 | //System.out.println("counter " + counter); 54 | if (poly.polygon.contains(p.point.getEnvelope())) { // Polygon contains the point 55 | return true; 56 | } 57 | } 58 | return false; // Polygon does not contain the point 59 | } 60 | }); 61 | 62 | return keyedStream; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/tStats/PointTStatsQuery.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators.tStats; 2 | 3 | import GeoFlink.spatialObjects.Point; 4 | import GeoFlink.spatialOperators.QueryConfiguration; 5 | import GeoFlink.spatialOperators.QueryType; 6 | import org.apache.flink.api.common.functions.FilterFunction; 7 | import org.apache.flink.api.java.functions.KeySelector; 8 | import org.apache.flink.api.java.tuple.Tuple4; 9 | import org.apache.flink.api.java.tuple.Tuple5; 10 | import org.apache.flink.streaming.api.datastream.DataStream; 11 | import org.apache.flink.streaming.api.functions.timestamps.BoundedOutOfOrdernessTimestampExtractor; 12 | import org.apache.flink.streaming.api.windowing.assigners.SlidingEventTimeWindows; 13 | import org.apache.flink.streaming.api.windowing.time.Time; 14 | 15 | import java.util.Set; 16 | 17 | public class PointTStatsQuery extends TStatsQuery { 18 | public PointTStatsQuery(QueryConfiguration conf) { 19 | super.initializeKNNQuery(conf); 20 | } 21 | 22 | public DataStream run(DataStream pointStream, Set trajIDSet) { 23 | 24 | //--------------- Real-time - POINT -----------------// 25 | if (this.getQueryConfiguration().getQueryType() == QueryType.RealTime) { 26 | return realTime(pointStream, trajIDSet); 27 | } 28 | 29 | //--------------- Window-based - POINT -----------------// 30 | else if (this.getQueryConfiguration().getQueryType() == QueryType.WindowBased) { 31 | int windowSize = this.getQueryConfiguration().getWindowSize(); 32 | int windowSlideStep = this.getQueryConfiguration().getSlideStep(); 33 | return windowBased(pointStream, trajIDSet, windowSize, windowSlideStep); 34 | } 35 | 36 | else { 37 | throw new IllegalArgumentException("Not yet support"); 38 | } 39 | } 40 | 41 | // REAL-TIME 42 | private DataStream> realTime(DataStream pointStream, Set trajIDSet){ 43 | 44 | DataStream filteredStream = pointStream.filter(new FilterFunction() { 45 | @Override 46 | public boolean filter(Point point) throws Exception { 47 | 48 | if (trajIDSet.size() > 0) 49 | return ((trajIDSet.contains(point.objID))); 50 | else 51 | return true; 52 | } 53 | }); 54 | 55 | return filteredStream.keyBy(new KeySelector() { 56 | @Override 57 | public String getKey(Point p) throws Exception { 58 | return p.objID; 59 | } 60 | }).flatMap(new TStatsQueryFlatmapFunction()); 61 | } 62 | 63 | // WINDOW BASED 64 | private DataStream> windowBased(DataStream pointStream, Set trajIDSet, int windowSize, int windowSlideStep){ 65 | 66 | // Spatial stream with Timestamps and Watermarks 67 | // Max Allowed Lateness: windowSize 68 | DataStream pointStreamWithTsAndWm = 69 | pointStream.assignTimestampsAndWatermarks(new BoundedOutOfOrdernessTimestampExtractor(Time.seconds(windowSize)) { 70 | @Override 71 | public long extractTimestamp(Point p) { 72 | return p.timeStampMillisec; 73 | } 74 | }); 75 | 76 | DataStream filteredStream = pointStreamWithTsAndWm.filter(new FilterFunction() { 77 | @Override 78 | public boolean filter(Point point) throws Exception { 79 | if (trajIDSet.size() > 0) 80 | return ((trajIDSet.contains(point.objID))); 81 | else 82 | return true; 83 | } 84 | }); 85 | 86 | return filteredStream.keyBy(new KeySelector() { 87 | @Override 88 | public String getKey(Point p) throws Exception { 89 | return p.objID; 90 | } 91 | }).window(SlidingEventTimeWindows.of(Time.seconds(windowSize), Time.seconds(windowSlideStep))) 92 | .apply(new TStatsQueryWFunction()); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/spatialOperators/tStats/TStatsQuery.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.spatialOperators.tStats; 2 | 3 | import GeoFlink.spatialObjects.Point; 4 | import GeoFlink.spatialObjects.SpatialObject; 5 | import GeoFlink.spatialOperators.QueryConfiguration; 6 | import GeoFlink.spatialOperators.SpatialOperator; 7 | import GeoFlink.utils.DistanceFunctions; 8 | import org.apache.flink.api.common.functions.RichFlatMapFunction; 9 | import org.apache.flink.api.common.state.ValueState; 10 | import org.apache.flink.api.common.state.ValueStateDescriptor; 11 | import org.apache.flink.api.common.typeinfo.BasicTypeInfo; 12 | import org.apache.flink.api.java.tuple.Tuple4; 13 | import org.apache.flink.api.java.tuple.Tuple5; 14 | import org.apache.flink.configuration.Configuration; 15 | import org.apache.flink.streaming.api.datastream.DataStream; 16 | import org.apache.flink.streaming.api.functions.windowing.RichWindowFunction; 17 | import org.apache.flink.streaming.api.windowing.windows.TimeWindow; 18 | import org.apache.flink.util.Collector; 19 | 20 | import java.io.Serializable; 21 | import java.util.Date; 22 | import java.util.Set; 23 | 24 | public abstract class TStatsQuery extends SpatialOperator implements Serializable { 25 | private QueryConfiguration queryConfiguration; 26 | 27 | public QueryConfiguration getQueryConfiguration() { 28 | return queryConfiguration; 29 | } 30 | 31 | public void setQueryConfiguration(QueryConfiguration queryConfiguration) { 32 | this.queryConfiguration = queryConfiguration; 33 | } 34 | 35 | public void initializeKNNQuery(QueryConfiguration conf){ 36 | this.setQueryConfiguration(conf); 37 | } 38 | 39 | public abstract DataStream run(DataStream stream, Set trajIDSet); 40 | 41 | // User Defined Classes 42 | // Update/Output is generated only when the current tuple timestamp is different from previous tuple 43 | //public static class TStatsQueryFlatmapFunction extends RichFlatMapFunction> { 44 | protected class TStatsQueryFlatmapFunction extends RichFlatMapFunction> { 45 | 46 | private ValueState temporalLengthVState; 47 | private ValueState lastTimestampVState; 48 | private ValueState spatialLengthVState; 49 | private ValueState lastPointCoordinateXVState; 50 | private ValueState lastPointCoordinateYVState; 51 | 52 | //ctor 53 | public TStatsQueryFlatmapFunction() {} 54 | 55 | @Override 56 | public void open(Configuration config) { 57 | 58 | ValueStateDescriptor temporalLengthDescriptor = new ValueStateDescriptor( 59 | "temporalLengthDescriptor", // state name 60 | BasicTypeInfo.LONG_TYPE_INFO); 61 | 62 | ValueStateDescriptor lastTimestampDescriptor = new ValueStateDescriptor( 63 | "lastTimestampDescriptor", // state name 64 | BasicTypeInfo.LONG_TYPE_INFO); 65 | 66 | ValueStateDescriptor spatialLengthDescriptor = new ValueStateDescriptor( 67 | "spatialLengthDescriptor", // state name 68 | BasicTypeInfo.DOUBLE_TYPE_INFO); 69 | 70 | ValueStateDescriptor lastPointCoordinateXDescriptor = new ValueStateDescriptor( 71 | "lastPointCoordinateXDescriptor", // state name 72 | BasicTypeInfo.DOUBLE_TYPE_INFO); 73 | 74 | ValueStateDescriptor lastPointCoordinateYDescriptor = new ValueStateDescriptor( 75 | "lastPointCoordinateYDescriptor", // state name 76 | BasicTypeInfo.DOUBLE_TYPE_INFO); 77 | 78 | this.temporalLengthVState = getRuntimeContext().getState(temporalLengthDescriptor); 79 | this.lastTimestampVState = getRuntimeContext().getState(lastTimestampDescriptor); 80 | this.spatialLengthVState = getRuntimeContext().getState(spatialLengthDescriptor); 81 | this.lastPointCoordinateXVState = getRuntimeContext().getState(lastPointCoordinateXDescriptor); 82 | this.lastPointCoordinateYVState = getRuntimeContext().getState(lastPointCoordinateYDescriptor); 83 | } 84 | 85 | //Tuple4.of(p.objID, temporalLength, spatialLength, spatialLength/temporalLength); 86 | @Override 87 | //public void flatMap(Point p, Collector> out) throws Exception { 88 | public void flatMap(Point p, Collector> out) throws Exception { 89 | Double spatialLength; 90 | Long temporalLength; 91 | Long lastTimestamp; 92 | Double lastPointCoordinateX; 93 | Double lastPointCoordinateY; 94 | 95 | // Fetching the value of state variables 96 | spatialLength = spatialLengthVState.value(); 97 | temporalLength = temporalLengthVState.value(); 98 | lastTimestamp = lastTimestampVState.value(); 99 | lastPointCoordinateX = lastPointCoordinateXVState.value(); 100 | lastPointCoordinateY = lastPointCoordinateYVState.value(); 101 | 102 | // If this is the first point, i.e., no past value is available 103 | if (lastTimestamp == null){ 104 | lastTimestamp = p.timeStampMillisec; 105 | lastPointCoordinateX = p.point.getX(); 106 | lastPointCoordinateY = p.point.getY(); 107 | temporalLength = 0L; 108 | spatialLength = 0.0; 109 | 110 | // Updating the state variables 111 | temporalLengthVState.update(temporalLength); 112 | lastTimestampVState.update(lastTimestamp); 113 | spatialLengthVState.update(spatialLength); 114 | lastPointCoordinateXVState.update(lastPointCoordinateX); 115 | lastPointCoordinateYVState.update(lastPointCoordinateY); 116 | 117 | }else { 118 | if (p.timeStampMillisec > lastTimestamp) // Avoiding out-of-order arrival of tuples 119 | { 120 | Date date = new Date(); 121 | //Double currSpatialDist = HelperClass.computeHaverSine(lastPointCoordinateX, lastPointCoordinateY, p.point.getX(), p.point.getY()); 122 | Double currSpatialDist = DistanceFunctions.getPointPointEuclideanDistance(lastPointCoordinateX, lastPointCoordinateY, p.point.getX(), p.point.getY()); 123 | Long currTemporalDist = p.timeStampMillisec - lastTimestamp; 124 | 125 | spatialLength += currSpatialDist; 126 | temporalLength += currTemporalDist; 127 | 128 | lastTimestamp = p.timeStampMillisec; 129 | lastPointCoordinateX = p.point.getX(); 130 | lastPointCoordinateY = p.point.getY(); 131 | 132 | // Updating the state variables 133 | temporalLengthVState.update(temporalLength); 134 | lastTimestampVState.update(lastTimestamp); 135 | spatialLengthVState.update(spatialLength); 136 | lastPointCoordinateXVState.update(lastPointCoordinateX); 137 | lastPointCoordinateYVState.update(lastPointCoordinateY); 138 | 139 | //out.collect(Tuple4.of(p.objID, spatialLength, temporalLength, spatialLength/temporalLength)); 140 | //System.out.println(date.getTime() - p.ingestionTime); 141 | out.collect(Tuple5.of(p.objID, spatialLength, temporalLength, spatialLength/temporalLength, (date.getTime() - p.ingestionTime))); 142 | } 143 | } 144 | } 145 | } 146 | 147 | //RichWindowFunction 148 | protected class TStatsQueryWFunction extends RichWindowFunction, String, TimeWindow> { 149 | 150 | //ctor 151 | public TStatsQueryWFunction() {}; 152 | 153 | @Override 154 | public void apply(String key, TimeWindow window, Iterable input, Collector> output) throws Exception { 155 | 156 | Long temporalLength = 0L; 157 | Long lastTimestamp = 0L; 158 | Double spatialLength = 0.0; 159 | Double lastPointCoordinateX = 0.0; 160 | Double lastPointCoordinateY = 0.0; 161 | 162 | 163 | // Check all points in the window 164 | for (Point p : input) { 165 | if (lastTimestamp.equals(0L)){ // case of first point p in the loop 166 | lastTimestamp = p.timeStampMillisec; 167 | lastPointCoordinateX = p.point.getX(); 168 | lastPointCoordinateY = p.point.getY(); 169 | spatialLength = 0.0; 170 | temporalLength = 0L; 171 | }else { 172 | if (p.timeStampMillisec > lastTimestamp) // Avoiding out-of-order arrival of tuples 173 | { 174 | //Double currSpatialDist = HelperClass.computeHaverSine(lastPointCoordinateX, lastPointCoordinateY, p.point.getX(), p.point.getY()); 175 | Double currSpatialDist = DistanceFunctions.getPointPointEuclideanDistance(lastPointCoordinateX, lastPointCoordinateY, p.point.getX(), p.point.getY()); 176 | Long currTemporalDist = p.timeStampMillisec - lastTimestamp; 177 | 178 | spatialLength += currSpatialDist; 179 | temporalLength += currTemporalDist; 180 | 181 | lastTimestamp = p.timeStampMillisec; 182 | lastPointCoordinateX = p.point.getX(); 183 | lastPointCoordinateY = p.point.getY(); 184 | } 185 | } 186 | } 187 | output.collect(Tuple4.of(key, spatialLength, temporalLength, spatialLength/temporalLength)); 188 | } 189 | } 190 | } 191 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/utils/Comparators.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.utils; 2 | 3 | import GeoFlink.spatialObjects.LineString; 4 | import GeoFlink.spatialObjects.Point; 5 | import GeoFlink.spatialObjects.Polygon; 6 | import org.apache.flink.api.java.tuple.Tuple2; 7 | 8 | import java.io.Serializable; 9 | import java.util.Comparator; 10 | import java.util.Map; 11 | 12 | public class Comparators { 13 | 14 | public static class inTuplePointDistanceComparator implements Comparator>, Serializable { 15 | 16 | public inTuplePointDistanceComparator() {} 17 | 18 | public int compare(Tuple2 t1, Tuple2 t2) { 19 | //double distance1 = HelperClass.getPointPointEuclideanDistance(t1.f0.point.getX(), t1.f0.point.getY(), queryPoint.point.getX(), queryPoint.point.getY()); 20 | //double distance2 = HelperClass.getPointPointEuclideanDistance(t2.f0.point.getX(), t2.f0.point.getY(), queryPoint.point.getX(), queryPoint.point.getY()); 21 | double distance1 = t1.f1; 22 | double distance2 = t2.f1; 23 | 24 | // Maintains a PQ in descending order with the object with the largest distance from query point at the top 25 | if (distance1 > distance2) { 26 | return -1; 27 | } else if (distance1 == distance2) { 28 | return 0; 29 | } 30 | return 1; 31 | } 32 | } 33 | 34 | /* TODO remove this block 35 | public static class inTupleDoubleDistanceComparator implements Comparator>, Serializable { 36 | 37 | public inTupleDoubleDistanceComparator() {} 38 | 39 | public int compare(Tuple2 t1, Tuple2 t2) { 40 | 41 | double distance1 = t1.f1; 42 | double distance2 = t2.f1; 43 | 44 | // Maintains a PQ in descending order with the object with the largest distance from query point at the top 45 | if (distance1 > distance2) { 46 | return -1; 47 | } else if (distance1 == distance2) { 48 | return 0; 49 | } 50 | return 1; 51 | } 52 | } 53 | */ 54 | 55 | public static class inTupleLineStringDistanceComparator implements Comparator>, Serializable { 56 | 57 | public inTupleLineStringDistanceComparator() {} 58 | 59 | @Override 60 | public int compare(Tuple2 t1, Tuple2 t2) { 61 | 62 | double distance1 = t1.f1; 63 | double distance2 = t2.f1; 64 | 65 | // Maintains a PQ in descending order with the object with the largest distance from query point at the top 66 | if (distance1 > distance2) { 67 | return -1; 68 | } else if (distance1 == distance2) { 69 | return 0; 70 | } 71 | return 1; 72 | } 73 | } 74 | 75 | public static class inTuplePolygonDistanceComparator implements Comparator>, Serializable { 76 | 77 | public inTuplePolygonDistanceComparator() {} 78 | 79 | public int compare(Tuple2 t1, Tuple2 t2) { 80 | 81 | double distance1 = t1.f1; 82 | double distance2 = t2.f1; 83 | 84 | // Maintains a PQ in descending order with the object with the largest distance from query point at the top 85 | if (distance1 > distance2) { 86 | return -1; 87 | } else if (distance1 == distance2) { 88 | return 0; 89 | } 90 | return 1; 91 | } 92 | } 93 | 94 | public class SpatialDistanceComparator implements Comparator>, Serializable { 95 | 96 | Point queryPoint; 97 | 98 | public SpatialDistanceComparator() { 99 | } 100 | 101 | public SpatialDistanceComparator(Point queryPoint) { 102 | this.queryPoint = queryPoint; 103 | } 104 | 105 | public int compare(Tuple2 t1, Tuple2 t2) { 106 | // computeSpatialDistance(Double lon, Double lat, Double lon1, Double lat1) 107 | double distance1 = DistanceFunctions.getPointPointEuclideanDistance(t1.f0.point.getX(), t1.f0.point.getY(), queryPoint.point.getX(), queryPoint.point.getY()); 108 | double distance2 = DistanceFunctions.getPointPointEuclideanDistance(t2.f0.point.getX(), t2.f0.point.getY(), queryPoint.point.getX(), queryPoint.point.getY()); 109 | 110 | if (distance1 > distance2) { 111 | return -1; 112 | } else if (distance1 == distance2) { 113 | return 0; 114 | } 115 | return 1; 116 | } 117 | } 118 | } 119 | -------------------------------------------------------------------------------- /src/main/java/GeoFlink/utils/ConfigType.java: -------------------------------------------------------------------------------- 1 | package GeoFlink.utils; 2 | 3 | import java.util.Map; 4 | 5 | public class ConfigType { 6 | private boolean clusterMode; 7 | private int parallelism; 8 | private String kafkaBootStrapServers; 9 | private Map inputStream1; 10 | private Map inputStream2; 11 | private Map outputStream; 12 | private Map query; 13 | private Map window; 14 | 15 | public boolean isClusterMode() { 16 | return clusterMode; 17 | } 18 | 19 | public void setClusterMode(boolean clusterMode) { 20 | this.clusterMode = clusterMode; 21 | } 22 | 23 | public int getParallelism() { 24 | return parallelism; 25 | } 26 | 27 | public void setParallelism(int parallelism) { 28 | this.parallelism = parallelism; 29 | } 30 | 31 | public String getKafkaBootStrapServers() { 32 | return kafkaBootStrapServers; 33 | } 34 | 35 | public void setKafkaBootStrapServers(String kafkaBootStrapServers) { 36 | this.kafkaBootStrapServers = kafkaBootStrapServers; 37 | } 38 | 39 | public Map getInputStream1() { 40 | return inputStream1; 41 | } 42 | 43 | public void setInputStream1(Map inputStream1) { 44 | this.inputStream1 = inputStream1; 45 | } 46 | 47 | public Map getInputStream2() { 48 | return inputStream2; 49 | } 50 | 51 | public void setInputStream2(Map inputStream2) { 52 | this.inputStream2 = inputStream2; 53 | } 54 | 55 | public Map getOutputStream() { 56 | return outputStream; 57 | } 58 | 59 | public void setOutputStream(Map outputStream) { 60 | this.outputStream = outputStream; 61 | } 62 | 63 | public Map getQuery() { 64 | return query; 65 | } 66 | 67 | public void setQuery(Map query) { 68 | this.query = query; 69 | } 70 | 71 | public Map getWindow() { 72 | return window; 73 | } 74 | 75 | public void setWindow(Map window) { 76 | this.window = window; 77 | } 78 | 79 | @Override 80 | public String toString() { 81 | return "clusterMode=" + clusterMode + ", kafkaBootStrapServers=" + kafkaBootStrapServers + ", inputStream1=" + inputStream1 + 82 | ", inputStream2=" + inputStream2 + ", outputStream=" + outputStream + 83 | ", query=" + query + ", window=" + window; 84 | } 85 | } 86 | -------------------------------------------------------------------------------- /src/main/resources/log4j.properties: -------------------------------------------------------------------------------- 1 | ################################################################################ 2 | # Licensed to the Apache Software Foundation (ASF) under one 3 | # or more contributor license agreements. See the NOTICE file 4 | # distributed with this work for additional information 5 | # regarding copyright ownership. The ASF licenses this file 6 | # to you under the Apache License, Version 2.0 (the 7 | # "License"); you may not use this file except in compliance 8 | # with the License. You may obtain a copy of the License at 9 | # 10 | # http://www.apache.org/licenses/LICENSE-2.0 11 | # 12 | # Unless required by applicable law or agreed to in writing, software 13 | # distributed under the License is distributed on an "AS IS" BASIS, 14 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | # See the License for the specific language governing permissions and 16 | # limitations under the License. 17 | ################################################################################ 18 | 19 | log4j.rootLogger=INFO, console 20 | 21 | log4j.appender.console=org.apache.log4j.ConsoleAppender 22 | log4j.appender.console.layout=org.apache.log4j.PatternLayout 23 | log4j.appender.console.layout.ConversionPattern=%d{HH:mm:ss,SSS} %-5p %-60c %x - %m%n 24 | --------------------------------------------------------------------------------