kipedia.org/wiki/Dilation_%28morphology%29">"Dilation" article in Wikipedia) with a very large pattern, created by {@link Patterns#newMinkowskiSum(java.util.Collection)}and consisting of millions or milliards points, via sequential dilations with the Minkowski summands of such a pattern, extracted by {@link #minkowskiDecomposition(int)} call.
Coordinate restrictions
There are the following guarantees for coordinates of the points of any pattern:
if p=(x0,x1,...,xn−1) is some point of the pattern, then − {@link #MAX_COORDINATE}≤xj≤ {@link #MAX_COORDINATE}for all j; here this inequality means absolutely precise mathematical inequality;
if p=(x01,x11,...,xn−11) and q=(x02,x12,...,xn−12) are some two points of the pattern, then |xj1−xj2|≤ {@link #MAX_COORDINATE} for all j, where|xj1−xj2| means the absolute value of mathematically precise difference (not the result of Java operators Math.abs(xj1−xj2)). (This condition can be checked with help of {@link Patterns#isAllowedDifference(double,double)} method.)
Each implementation of this interface must fulfil both restriction. The point sets, satisfying these requirements, are called allowed points sets for patterns. Any attempt to create a pattern, the set of points of which is not allowed, leads to {@link TooLargePatternCoordinatesException}.
Note: though patterns are sets of real points, their coordinates are restricted by long-type constant {@link #MAX_COORDINATE}.
Also note: uniform-grid patterns must fulfil, in addition, two similar restrictions for their grid indexes. See more details in the comments to {@link UniformGridPattern} interface,the section "Grid index restrictions".
Below are two important theorems, following from these two restrictions.
Theorem I. If you round the coordinates of all points of a pattern, i.e. replace each pattern's point (x0, x1, ..., xn−1) with a new point (round(x0), round(x1), ..., round(xn−1)), where "round(a)" means the result of (double)StrictMath.round(a) call, then the resulting point set will also be allowed. The same statement is true for the point set, consisting of precise integer points, without type cast to double, i.e. for points (StrictMath.round(x0), StrictMath.round(x1), ..., StrictMath.round(xn−1)) — such mathematical point set also fulfils both restrictions 1 and 2.
It means that you can freely use {@link #round()} method for any pattern:it always constructs another allowed pattern, both in terms of this interface and in terms in {@link UniformGridPattern}, and cannot throw {@link TooLargePatternCoordinatesException}.
Theorem II. If all points of a pattern are integer, i.e. for all pattern's points (x0, x1, ..., xn−1) we have xj==(double)(long)xj for any index j, and (X0,X1,...,Xn−1) is some point of this pattern, then you can subtract (using Java “−” operator) the coordinate Xj (j is any index) from the corresponding coordinate of all points of this pattern, i.e. replace each pattern's point (x0, ..., xj−1, xj, xj+1, ..., xn−1) with (x0, ..., xj−1, xj⊖Xj, xj+1, ..., xn−1), and the resulting point set will also be allowed. Here and below a⊖b (a and b are real values of double Java type) means the computer difference (not strict mathematical), i.e. the result of execution of Java operator “a−b”.
Proof.
First of all, let's remind that the computer difference a⊖b, according IEEE 754 standard and Java language specification, is the nearest double value to the precise mathematical difference a−b. Because all pattern's points are integer, the restriction 2 allows to state that any difference xj−Xj can be represented precisely by double type (see the comments to {@link #MAX_COORDINATE} constant).So, we have xj⊖Xj = xj−Xj: the computer difference is just a mathematical difference.
Now the proof is simple. If is enough to show that the restrictions will be satisfied for the coordinate index j. The restriction 2 is obvious: (mathematical) subtracting Xj does not change the (mathematical!) differences |xj1−xj2|. The new value of this coordinate for each point will be xj−Xj, where both (x0,x1,...,xn−1) and (X0,X1,...,Xn−1) are some points of the pattern; according the condition 2, this difference lies in range − {@link #MAX_COORDINATE}≤xj−Xj≤ {@link #MAX_COORDINATE}. In other words, the restriction 1 is also satisfied. This completes the proof.
Note: this proof is really correct only for patterns, consisting of integer points only. The reason is that all integer coordinates, fulfilling the restriction 1, and all their differences xj−Xj are represented precisely by double Java type. If a pattern contains non-integer points, the statement of this theorem is not true. For example, for 1-dimensional pattern, consisting of three points x1=2251799813685248.00 (= {@link #MAX_COORDINATE}/2), x2=−2251799813685248.00 (=− {@link #MAX_COORDINATE}/2) and x3=−2251799813685247.75 (=− {@link #MAX_COORDINATE}/2+0.25), subtracting the point x3 by Java “−” operator leads to the pattern x'1=4503599627370496.00 (= {@link #MAX_COORDINATE}) (computer subtraction of double values leads to rounding here), x'2=−0.25 and x'3=0.0, which obviously violates the mathematically precise restriction 2: |x'1−x'2|> {@link #MAX_COORDINATE}.
As a result, there is an obvious conclusion. If p is one of the {@link #points() points} ofsome integerpattern (see above), then the method pattern. {@link #shift(Point) shift}(p. {@link Point#symmetric() symmetric()}) always works successfully and never throw {@link TooLargePatternCoordinatesException}.
Note about equals()
The equals() method in the classes, implementing this interface, may return false for two patterns, consisting of the same point sets, for example, if these patterns belong to different pattern types. For example, a rectangular pattern may be considered to be non-equal to a geometrically identical {@link Patterns#newMinkowskiSum(Pattern) Minkowski sum} of several segments,because the thorough comparison of these patterns can require too long time and large memory. (Please consider 10000x10000x10000 3-dimensional parallelepiped, consisting of 1012 points with integer coordinates in range 0..9999. It is geometrically equal to Minkowski sum of 3 orthogonal segments with 10000 integer points in every segment, but we have no resources to check this fact via direct comparison of the point sets.) However, the patterns of the same kind (for example, two rectangular patterns, two {@link Patterns#newMinkowskiSum(Pattern) Minkowski sums} ortwo {@link Patterns#newUnion(Pattern) unions}) are usually compared precisely. In particular, there are the following guarantees:
if both patterns are direct point-set (see above), then equals() method always returns true for geometrically identical patterns;
if both patterns are rectangular (see above), then, also, equals() method always returns true for geometrically identical patterns;
and, of course, there is the reverse guarantee, that if the equals() method returns true, then two patterns consists of the identical point sets.
Multithread compatibility
The classes, implementing this interface, are immutable and thread-safe: there are no ways to modify settings of the created instance.
AlgART Laboratory 2007–2014
@author Daniel Alievsky
@version 1.2
@since JDK 1.5
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.