/src/geos/include/geos/operation/relateng/RelatePredicate.h
Line | Count | Source |
1 | | /********************************************************************** |
2 | | * |
3 | | * GEOS - Geometry Engine Open Source |
4 | | * http://geos.osgeo.org |
5 | | * |
6 | | * Copyright (c) 2024 Martin Davis |
7 | | * Copyright (C) 2024 Paul Ramsey <pramsey@cleverelephant.ca> |
8 | | * |
9 | | * This is free software; you can redistribute and/or modify it under |
10 | | * the terms of the GNU Lesser General Public Licence as published |
11 | | * by the Free Software Foundation. |
12 | | * See the COPYING file for more information. |
13 | | * |
14 | | **********************************************************************/ |
15 | | |
16 | | #pragma once |
17 | | |
18 | | #include <geos/geom/Location.h> |
19 | | #include <geos/operation/relateng/BasicPredicate.h> |
20 | | #include <geos/operation/relateng/IMPatternMatcher.h> |
21 | | #include <geos/operation/relateng/IMPredicate.h> |
22 | | #include <geos/operation/relateng/RelateGeometry.h> |
23 | | #include <geos/geom/Envelope.h> |
24 | | #include <geos/export.h> |
25 | | |
26 | | namespace geos { // geos. |
27 | | namespace operation { // geos.operation. |
28 | | namespace relateng { // geos.operation.relateng |
29 | | |
30 | | |
31 | | class GEOS_DLL RelatePredicate { |
32 | | using Envelope = geos::geom::Envelope; |
33 | | using Location = geos::geom::Location; |
34 | | |
35 | | public: |
36 | | |
37 | | /************************************************************************ |
38 | | * |
39 | | * Creates a predicate to determine whether two geometries intersect. |
40 | | * |
41 | | * The intersects predicate has the following equivalent definitions: |
42 | | * |
43 | | * * The two geometries have at least one point in common |
44 | | * * The DE-9IM Intersection Matrix for the two geometries matches |
45 | | * at least one of the patterns |
46 | | * |
47 | | * [T********] |
48 | | * [*T*******] |
49 | | * [***T*****] |
50 | | * [****T****] |
51 | | * |
52 | | * disjoint() = false |
53 | | * (intersects is the inverse of disjoint) |
54 | | * |
55 | | * @return the predicate instance |
56 | | * |
57 | | * @see disjoint() |
58 | | */ |
59 | | class IntersectsPredicate : public BasicPredicate { |
60 | | |
61 | | public: |
62 | | |
63 | 0 | std::string name() const override { |
64 | 0 | return std::string("intersects"); |
65 | 0 | } |
66 | | |
67 | 0 | bool requireSelfNoding() const override { |
68 | | //-- self-noding is not required to check for a simple interaction |
69 | 0 | return false; |
70 | 0 | } |
71 | | |
72 | 0 | bool requireExteriorCheck(bool isSourceA) const override { |
73 | 0 | (void)isSourceA; |
74 | | //-- intersects only requires testing interaction |
75 | 0 | return false; |
76 | 0 | } |
77 | | |
78 | 0 | void init(const Envelope& envA, const Envelope& envB) override { |
79 | 0 | require(envA.intersects(envB)); |
80 | 0 | } |
81 | | |
82 | 0 | void updateDimension(Location locA, Location locB, int dimension) override { |
83 | 0 | (void)dimension; |
84 | 0 | setValueIf(true, isIntersection(locA, locB)); |
85 | 0 | } |
86 | | |
87 | 0 | void finish() override { |
88 | | //-- if no intersecting locations were found |
89 | 0 | setValue(false); |
90 | 0 | } |
91 | | |
92 | | }; |
93 | | |
94 | | static std::unique_ptr<BasicPredicate> intersects(); |
95 | | |
96 | | /************************************************************************ |
97 | | * |
98 | | * Creates a predicate to determine whether two geometries are disjoint. |
99 | | * |
100 | | * The disjoint predicate has the following equivalent definitions: |
101 | | * |
102 | | * * The two geometries have no point in common |
103 | | * * The DE-9IM Intersection Matrix for the two geometries matches |
104 | | * [FF*FF****] |
105 | | * * intersects() = false |
106 | | * (disjoint is the inverse of intersects) |
107 | | * |
108 | | * @return the predicate instance |
109 | | * |
110 | | * @see intersects() |
111 | | */ |
112 | | class DisjointPredicate : public BasicPredicate { |
113 | | |
114 | 0 | std::string name() const override { |
115 | 0 | return std::string("disjoint"); |
116 | 0 | } |
117 | | |
118 | 0 | bool requireSelfNoding() const override { |
119 | | //-- self-noding is not required to check for a simple interaction |
120 | 0 | return false; |
121 | 0 | } |
122 | | |
123 | 0 | bool requireInteraction() const override { |
124 | | //-- ensure entire matrix is computed |
125 | 0 | return false; |
126 | 0 | } |
127 | | |
128 | 0 | bool requireExteriorCheck(bool isSourceA) const override { |
129 | 0 | (void)isSourceA; |
130 | | //-- intersects only requires testing interaction |
131 | 0 | return false; |
132 | 0 | } |
133 | | |
134 | 0 | void init(const Envelope& envA, const Envelope& envB) override { |
135 | 0 | setValueIf(true, envA.disjoint(envB)); |
136 | 0 | } |
137 | | |
138 | 0 | void updateDimension(Location locA, Location locB, int dimension) override { |
139 | 0 | (void)dimension; |
140 | 0 | setValueIf(false, isIntersection(locA, locB)); |
141 | 0 | } |
142 | | |
143 | 0 | void finish() override { |
144 | | //-- if no intersecting locations were found |
145 | 0 | setValue(true); |
146 | 0 | } |
147 | | }; |
148 | | |
149 | | static std::unique_ptr<BasicPredicate> disjoint(); |
150 | | |
151 | | /************************************************************************ |
152 | | * Creates a predicate to determine whether a geometry contains another geometry. |
153 | | * |
154 | | * The contains predicate has the following equivalent definitions: |
155 | | * |
156 | | * * Every point of the other geometry is a point of this geometry, |
157 | | * and the interiors of the two geometries have at least one point in common. |
158 | | * * The DE-9IM Intersection Matrix for the two geometries matches |
159 | | * the pattern |
160 | | * [T*****FF*] |
161 | | * * within(B, A) = true |
162 | | * (contains is the converse of within) |
163 | | * |
164 | | * An implication of the definition is that "Geometries do not |
165 | | * contain their boundary". In other words, if a geometry A is a subset of |
166 | | * the points in the boundary of a geometry B, B.contains(A) = false. |
167 | | * (As a concrete example, take A to be a LineString which lies in the boundary of a Polygon B.) |
168 | | * For a predicate with similar behavior but avoiding |
169 | | * this subtle limitation, see covers(). |
170 | | * |
171 | | * @return the predicate instance |
172 | | * |
173 | | * @see within() |
174 | | */ |
175 | | class ContainsPredicate : public IMPredicate { |
176 | | |
177 | 0 | std::string name() const override { |
178 | 0 | return std::string("contains"); |
179 | 0 | } |
180 | | |
181 | 0 | bool requireCovers(bool isSourceA) override { |
182 | 0 | return isSourceA == RelateGeometry::GEOM_A; |
183 | 0 | } |
184 | | |
185 | 0 | bool requireExteriorCheck(bool isSourceA) const override { |
186 | | //-- only need to check B against Exterior of A |
187 | 0 | return isSourceA == RelateGeometry::GEOM_B; |
188 | 0 | } |
189 | | |
190 | 0 | void init(int _dimA, int _dimB) override { |
191 | 0 | IMPredicate::init(_dimA, _dimB); |
192 | 0 | require(isDimsCompatibleWithCovers(dimA, dimB)); |
193 | 0 | } |
194 | | |
195 | 0 | void init(const Envelope& envA, const Envelope& envB) override { |
196 | 0 | BasicPredicate::requireCovers(envA, envB); |
197 | 0 | } |
198 | | |
199 | 0 | bool isDetermined() const override { |
200 | 0 | return intersectsExteriorOf(RelateGeometry::GEOM_A); |
201 | 0 | } |
202 | | |
203 | 0 | bool valueIM() override { |
204 | 0 | return intMatrix.isContains(); |
205 | 0 | } |
206 | | }; |
207 | | |
208 | | static std::unique_ptr<IMPredicate> contains(); |
209 | | |
210 | | |
211 | | |
212 | | /************************************************************************ |
213 | | * Creates a predicate to determine whether a geometry is within another geometry. |
214 | | * |
215 | | * The within predicate has the following equivalent definitions: |
216 | | * |
217 | | * * Every point of this geometry is a point of the other geometry, |
218 | | * and the interiors of the two geometries have at least one point in common. |
219 | | * * The DE-9IM Intersection Matrix for the two geometries matches |
220 | | * [T*F**F***] |
221 | | * * contains(B, A) = true |
222 | | * (within is the converse of contains()) |
223 | | * |
224 | | * An implication of the definition is that |
225 | | * "The boundary of a Geometry is not within the Geometry". |
226 | | * In other words, if a geometry A is a subset of |
227 | | * the points in the boundary of a geometry B, within(B, A) = false |
228 | | * (As a concrete example, take A to be a LineString which lies in the boundary of a Polygon B.) |
229 | | * For a predicate with similar behavior but avoiding |
230 | | * this subtle limitation, see coveredimBy(). |
231 | | * |
232 | | * @return the predicate instance |
233 | | * |
234 | | * @see #contains() |
235 | | */ |
236 | | class WithinPredicate : public IMPredicate { |
237 | | |
238 | 0 | std::string name() const override { |
239 | 0 | return std::string("within"); |
240 | 0 | } |
241 | | |
242 | 0 | bool requireCovers(bool isSourceA) override { |
243 | 0 | return isSourceA == RelateGeometry::GEOM_B; |
244 | 0 | } |
245 | | |
246 | 0 | bool requireExteriorCheck(bool isSourceA) const override { |
247 | | //-- only need to check B against Exterior of A |
248 | 0 | return isSourceA == RelateGeometry::GEOM_A; |
249 | 0 | } |
250 | | |
251 | 0 | void init(int _dimA, int _dimB) override { |
252 | 0 | IMPredicate::init(_dimA, _dimB); |
253 | 0 | require(isDimsCompatibleWithCovers(dimB, dimA)); |
254 | 0 | } |
255 | | |
256 | 0 | void init(const Envelope& envA, const Envelope& envB) override { |
257 | 0 | BasicPredicate::requireCovers(envB, envA); |
258 | 0 | } |
259 | | |
260 | 0 | bool isDetermined() const override { |
261 | 0 | return intersectsExteriorOf(RelateGeometry::GEOM_B); |
262 | 0 | } |
263 | | |
264 | 0 | bool valueIM() override { |
265 | 0 | return intMatrix.isWithin(); |
266 | 0 | } |
267 | | }; |
268 | | |
269 | | static std::unique_ptr<IMPredicate> within(); |
270 | | |
271 | | |
272 | | |
273 | | /************************************************************************ |
274 | | * Creates a predicate to determine whether a geometry covers another geometry. |
275 | | * |
276 | | * The covers predicate has the following equivalent definitions: |
277 | | * |
278 | | * Every point of the other geometry is a point of this geometry. |
279 | | * The DE-9IM Intersection Matrix for the two geometries matches |
280 | | * at least one of the following patterns: |
281 | | * |
282 | | * * [T*****FF*] |
283 | | * * [*T****FF*] |
284 | | * * [***T**FF*] |
285 | | * * [****T*FF*] |
286 | | * |
287 | | * coveredimBy(b, a) = true |
288 | | * (covers is the converse of coveredimBy()) |
289 | | * |
290 | | * If either geometry is empty, the value of this predicate is false. |
291 | | * |
292 | | * This predicate is similar to contains(), |
293 | | * but is more inclusive (i.e. returns true for more cases). |
294 | | * In particular, unlike contains it does not distinguish between |
295 | | * points in the boundary and in the interior of geometries. |
296 | | * For most cases, covers should be used in preference to contains. |
297 | | * As an added benefit, covers is more amenable to optimization, |
298 | | * and hence should be more performant. |
299 | | * |
300 | | * @return the predicate instance |
301 | | * |
302 | | * @see #coveredimBy() |
303 | | */ |
304 | | class CoversPredicate : public IMPredicate { |
305 | | |
306 | 0 | std::string name() const override { |
307 | 0 | return std::string("covers"); |
308 | 0 | } |
309 | | |
310 | 0 | bool requireCovers(bool isSourceA) override { |
311 | 0 | return isSourceA == RelateGeometry::GEOM_A; |
312 | 0 | } |
313 | | |
314 | 0 | bool requireExteriorCheck(bool isSourceA) const override { |
315 | | //-- only need to check B against Exterior of A |
316 | 0 | return isSourceA == RelateGeometry::GEOM_B; |
317 | 0 | } |
318 | | |
319 | 0 | void init(int _dimA, int _dimB) override { |
320 | 0 | IMPredicate::init(_dimA, _dimB); |
321 | 0 | require(isDimsCompatibleWithCovers(dimA, dimB)); |
322 | 0 | } |
323 | | |
324 | 0 | void init(const Envelope& envA, const Envelope& envB) override { |
325 | 0 | BasicPredicate::requireCovers(envA, envB); |
326 | |
|
327 | 0 | } |
328 | | |
329 | 0 | bool isDetermined() const override { |
330 | 0 | return intersectsExteriorOf(RelateGeometry::GEOM_A); |
331 | 0 | } |
332 | | |
333 | 0 | bool valueIM() override { |
334 | 0 | return intMatrix.isCovers(); |
335 | 0 | } |
336 | | }; |
337 | | |
338 | | static std::unique_ptr<IMPredicate> covers(); |
339 | | |
340 | | |
341 | | /************************************************************************ |
342 | | * Creates a predicate to determine whether a geometry is covered |
343 | | * by another geometry. |
344 | | * |
345 | | * The coveredimBy predicate has the following equivalent definitions: |
346 | | * |
347 | | * Every point of this geometry is a point of the other geometry. |
348 | | * The DE-9IM Intersection Matrix for the two geometries matches |
349 | | * at least one of the following patterns: |
350 | | * |
351 | | * [T*F**F***] |
352 | | * [*TF**F***] |
353 | | * [**FT*F***] |
354 | | * [**F*TF***] |
355 | | * |
356 | | * covers(B, A) = true |
357 | | * (coveredimBy is the converse of covers()) |
358 | | * |
359 | | * If either geometry is empty, the value of this predicate is false. |
360 | | * |
361 | | * This predicate is similar to within(), |
362 | | * but is more inclusive (i.e. returns true for more cases). |
363 | | * |
364 | | * @return the predicate instance |
365 | | * |
366 | | * @see #covers() |
367 | | */ |
368 | | class CoveredByPredicate : public IMPredicate { |
369 | | |
370 | 0 | std::string name() const override { |
371 | 0 | return std::string("coveredBy"); |
372 | 0 | } |
373 | | |
374 | 0 | bool requireCovers(bool isSourceA) override { |
375 | 0 | return isSourceA == RelateGeometry::GEOM_B; |
376 | 0 | } |
377 | | |
378 | 0 | bool requireExteriorCheck(bool isSourceA) const override { |
379 | | //-- only need to check B against Exterior of A |
380 | 0 | return isSourceA == RelateGeometry::GEOM_A; |
381 | 0 | } |
382 | | |
383 | 0 | void init(int _dimA, int _dimB) override { |
384 | 0 | IMPredicate::init(_dimA, _dimB); |
385 | 0 | require(isDimsCompatibleWithCovers(dimB, dimA)); |
386 | 0 | } |
387 | | |
388 | 0 | void init(const Envelope& envA, const Envelope& envB) override { |
389 | 0 | BasicPredicate::requireCovers(envB, envA); |
390 | 0 | } |
391 | | |
392 | 0 | bool isDetermined() const override { |
393 | 0 | return intersectsExteriorOf(RelateGeometry::GEOM_B); |
394 | 0 | } |
395 | | |
396 | 0 | bool valueIM() override { |
397 | 0 | return intMatrix.isCoveredBy(); |
398 | 0 | } |
399 | | |
400 | | }; |
401 | | |
402 | | static std::unique_ptr<IMPredicate> coveredBy(); |
403 | | |
404 | | |
405 | | /************************************************************************ |
406 | | * Creates a predicate to determine whether a geometry crosses another geometry. |
407 | | * |
408 | | * The crosses predicate has the following equivalent definitions: |
409 | | * |
410 | | * The geometries have some but not all interior points in common. |
411 | | * The DE-9IM Intersection Matrix for the two geometries matches |
412 | | * one of the following patterns: |
413 | | * |
414 | | * [T*T******] (for P/L, P/A, and L/A cases) |
415 | | * [T*****T**] (for L/P, A/P, and A/L cases) |
416 | | * [0********] (for L/L cases) |
417 | | * |
418 | | * |
419 | | * For the A/A and P/P cases this predicate returns false. |
420 | | * |
421 | | * The SFS defined this predicate only for P/L, P/A, L/L, and L/A cases. |
422 | | * To make the relation symmetric |
423 | | * JTS extends the definition to apply to L/P, A/P and A/L cases as well. |
424 | | * |
425 | | * @return the predicate instance |
426 | | */ |
427 | | |
428 | | class CrossesPredicate : public IMPredicate { |
429 | | |
430 | 0 | std::string name() const override { |
431 | 0 | return std::string("crosses"); |
432 | 0 | } |
433 | | |
434 | 0 | void init(int _dimA, int _dimB) override { |
435 | 0 | IMPredicate::init(_dimA, _dimB); |
436 | 0 | bool isBothPointsOrAreas = |
437 | 0 | (dimA == Dimension::P && dimB == Dimension::P) || |
438 | 0 | (dimA == Dimension::A && dimB == Dimension::A); |
439 | 0 | require(!isBothPointsOrAreas); |
440 | 0 | } |
441 | | |
442 | 0 | bool isDetermined() const override { |
443 | 0 | if (dimA == Dimension::L && dimB == Dimension::L) { |
444 | | //-- L/L interaction can only be dim = P |
445 | 0 | if (getDimension(Location::INTERIOR, Location::INTERIOR) > Dimension::P) |
446 | 0 | return true; |
447 | 0 | } |
448 | 0 | else if (dimA < dimB) { |
449 | 0 | if (isIntersects(Location::INTERIOR, Location::INTERIOR) && |
450 | 0 | isIntersects(Location::INTERIOR, Location::EXTERIOR)) { |
451 | 0 | return true; |
452 | 0 | } |
453 | 0 | } |
454 | 0 | else if (dimA > dimB) { |
455 | 0 | if (isIntersects(Location::INTERIOR, Location::INTERIOR) && |
456 | 0 | isIntersects(Location::EXTERIOR, Location::INTERIOR)) { |
457 | 0 | return true; |
458 | 0 | } |
459 | 0 | } |
460 | 0 | return false; |
461 | 0 | } |
462 | | |
463 | 0 | bool valueIM() override { |
464 | 0 | return intMatrix.isCrosses(dimA, dimB); |
465 | 0 | } |
466 | | }; |
467 | | |
468 | | static std::unique_ptr<IMPredicate> crosses(); |
469 | | |
470 | | |
471 | | /************************************************************************ |
472 | | * Creates a predicate to determine whether two geometries are |
473 | | * topologically equal. |
474 | | * |
475 | | * The equals predicate has the following equivalent definitions: |
476 | | * |
477 | | * The two geometries have at least one point in common, |
478 | | * and no point of either geometry lies in the exterior of the other geometry. |
479 | | * The DE-9IM Intersection Matrix for the two geometries matches |
480 | | * the pattern T*F**FFF* |
481 | | * |
482 | | * @return the predicate instance |
483 | | */ |
484 | | class EqualsTopoPredicate : public IMPredicate { |
485 | | |
486 | 0 | std::string name() const override { |
487 | 0 | return std::string("equals"); |
488 | 0 | } |
489 | | |
490 | 0 | bool requireInteraction() const override { |
491 | | //-- allow EMPTY = EMPTY |
492 | 0 | return false; |
493 | 0 | }; |
494 | | |
495 | 0 | void init(int _dimA, int _dimB) override { |
496 | 0 | IMPredicate::init(_dimA, _dimB); |
497 | | //-- don't require equal dims, because EMPTY = EMPTY for all dims |
498 | 0 | } |
499 | | |
500 | 0 | void init(const Envelope& envA, const Envelope& envB) override { |
501 | | //-- handle EMPTY = EMPTY cases |
502 | 0 | setValueIf(true, envA.isNull() && envB.isNull()); |
503 | |
|
504 | 0 | require(envA.equals(&envB)); |
505 | 0 | } |
506 | | |
507 | 0 | bool isDetermined() const override { |
508 | 0 | bool isEitherExteriorIntersects = |
509 | 0 | isIntersects(Location::INTERIOR, Location::EXTERIOR) || |
510 | 0 | isIntersects(Location::BOUNDARY, Location::EXTERIOR) || |
511 | 0 | isIntersects(Location::EXTERIOR, Location::INTERIOR) || |
512 | 0 | isIntersects(Location::EXTERIOR, Location::BOUNDARY); |
513 | |
|
514 | 0 | return isEitherExteriorIntersects; |
515 | 0 | } |
516 | | |
517 | 0 | bool valueIM() override { |
518 | 0 | return intMatrix.isEquals(dimA, dimB); |
519 | 0 | } |
520 | | |
521 | | }; |
522 | | |
523 | | static std::unique_ptr<IMPredicate> equalsTopo(); |
524 | | |
525 | | |
526 | | /************************************************************************ |
527 | | * Creates a predicate to determine whether a geometry overlaps another geometry. |
528 | | * |
529 | | * The overlaps predicate has the following equivalent definitions: |
530 | | * |
531 | | * The geometries have at least one point each not shared by the other |
532 | | * (or equivalently neither covers the other), |
533 | | * they have the same dimension, |
534 | | * and the intersection of the interiors of the two geometries has |
535 | | * the same dimension as the geometries themselves. |
536 | | * The DE-9IM Intersection Matrix for the two geometries matches |
537 | | * [T*T***T**] (for P/P and A/A cases) |
538 | | * or [1*T***T**] (for L/L cases) |
539 | | * |
540 | | * If the geometries are of different dimension this predicate returns false. |
541 | | * This predicate is symmetric. |
542 | | * |
543 | | * @return the predicate instance |
544 | | */ |
545 | | class OverlapsPredicate : public IMPredicate { |
546 | | |
547 | 0 | std::string name() const override { |
548 | 0 | return std::string("overlaps"); |
549 | 0 | } |
550 | | |
551 | 0 | void init(int _dimA, int _dimB) override { |
552 | 0 | IMPredicate::init(_dimA, _dimB); |
553 | 0 | require(dimA == dimB); |
554 | 0 | } |
555 | | |
556 | 0 | bool isDetermined() const override { |
557 | 0 | if (dimA == Dimension::A || dimA == Dimension::P) { |
558 | 0 | if (isIntersects(Location::INTERIOR, Location::INTERIOR) && |
559 | 0 | isIntersects(Location::INTERIOR, Location::EXTERIOR) && |
560 | 0 | isIntersects(Location::EXTERIOR, Location::INTERIOR)) |
561 | 0 | return true; |
562 | 0 | } |
563 | 0 | if (dimA == Dimension::L) { |
564 | 0 | if (isDimension(Location::INTERIOR, Location::INTERIOR, Dimension::L) && |
565 | 0 | isIntersects(Location::INTERIOR, Location::EXTERIOR) && |
566 | 0 | isIntersects(Location::EXTERIOR, Location::INTERIOR)) |
567 | 0 | return true; |
568 | 0 | } |
569 | 0 | return false; |
570 | 0 | } |
571 | | |
572 | 0 | bool valueIM() override { |
573 | 0 | return intMatrix.isOverlaps(dimA, dimB); |
574 | 0 | } |
575 | | }; |
576 | | |
577 | | static std::unique_ptr<IMPredicate> overlaps(); |
578 | | |
579 | | |
580 | | |
581 | | |
582 | | |
583 | | /************************************************************************ |
584 | | * Creates a predicate to determine whether a geometry touches another geometry. |
585 | | * |
586 | | * The touches predicate has the following equivalent definitions: |
587 | | * |
588 | | * The geometries have at least one point in common, |
589 | | * but their interiors do not intersect. |
590 | | * The DE-9IM Intersection Matrix for the two geometries matches |
591 | | * at least one of the following patterns |
592 | | * |
593 | | * [FT*******] |
594 | | * [F**T*****] |
595 | | * [F***T****] |
596 | | * |
597 | | * |
598 | | * If both geometries have dimension 0, the predicate returns false, |
599 | | * since points have only interiors. |
600 | | * This predicate is symmetric. |
601 | | * |
602 | | * @return the predicate instance |
603 | | */ |
604 | | class TouchesPredicate : public IMPredicate { |
605 | | |
606 | 0 | std::string name() const override { |
607 | 0 | return std::string("touches"); |
608 | 0 | } |
609 | | |
610 | 0 | void init(int _dimA, int _dimB) override { |
611 | 0 | IMPredicate::init(_dimA, _dimB); |
612 | 0 | bool isBothPoints = (dimA == 0 && dimB == 0); |
613 | 0 | require(! isBothPoints); |
614 | 0 | } |
615 | | |
616 | 0 | bool isDetermined() const override { |
617 | 0 | bool isInteriorsIntersects = isIntersects(Location::INTERIOR, Location::INTERIOR); |
618 | 0 | return isInteriorsIntersects; |
619 | 0 | } |
620 | | |
621 | 0 | bool valueIM() override { |
622 | 0 | return intMatrix.isTouches(dimA, dimB); |
623 | 0 | } |
624 | | }; |
625 | | |
626 | | static std::unique_ptr<IMPredicate> touches(); |
627 | | |
628 | | /** |
629 | | * Creates a predicate that matches a DE-9IM matrix pattern. |
630 | | * |
631 | | * @param imPattern the pattern to match |
632 | | * @return a predicate that matches the pattern |
633 | | * |
634 | | * @see IntersectionMatrixPattern |
635 | | */ |
636 | | static std::unique_ptr<TopologyPredicate> matches(const std::string& imPattern) |
637 | 0 | { |
638 | 0 | return std::unique_ptr<TopologyPredicate>(new IMPatternMatcher(imPattern)); |
639 | 0 | } |
640 | | |
641 | | |
642 | | |
643 | | }; // !RelatePredicate |
644 | | |
645 | | |
646 | | } // namespace geos.operation.relateng |
647 | | } // namespace geos.operation |
648 | | } // namespace geos |
649 | | |