├── .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