Class AbstractPattern

java.lang.Object
net.algart.math.patterns.AbstractPattern
All Implemented Interfaces:
Pattern
Direct Known Subclasses:
AbstractUniformGridPattern, SimplePattern

public abstract class AbstractPattern extends Object implements Pattern

A skeletal implementation of the Pattern interface to minimize the effort required to implement this interface.

All non-abstract methods are completely implemented here and may be not overridden in subclasses.

Author:
Daniel Alievsky
  • Field Details

    • dimCount

      protected final int dimCount
      The number of space dimensions of this pattern.
  • Constructor Details

    • AbstractPattern

      protected AbstractPattern(int dimCount)
      Creates a pattern with the given number of space dimensions.
      Parameters:
      dimCount - the number of space dimensions.
      Throws:
      IllegalArgumentException - if dimCount<=0.
  • Method Details

    • dimCount

      public final int dimCount()
      This implementation returns dimCount field.
      Specified by:
      dimCount in interface Pattern
      Returns:
      the number of space dimensions of this pattern.
    • pointCount

      public abstract long pointCount()
      Description copied from interface: Pattern
      Returns the number of points in this pattern. This value is always positive (>=1). If the number of points is greater than Long.MAX_VALUE, returns Long.MAX_VALUE.

      Warning! This method can work slowly for some forms of large patterns: the required time can be O(N), where N is the number of points (result of this method). In these cases, this method can also throw TooManyPointsInPatternError or OutOfMemoryError.

      There is a guarantee, that if this object implements QuickPointCountPattern interface, then this method works very quickly (O(1) operations) and without exceptions.

      There is a guarantee, that if this object implements DirectPointSetPattern interface, then the result of this method is not greater than Integer.MAX_VALUE.

      Note: if this method returns some value greater than Integer.MAX_VALUE, it means that you cannot use Pattern.points() and Pattern.roundedPoints() methods, because Java Set object cannot contain more than Integer.MAX_VALUE elements.

      Specified by:
      pointCount in interface Pattern
      Returns:
      the number of points in this pattern.
      See Also:
    • largePointCount

      public double largePointCount()
      This implementation returns (double)pointCount(). Please override this method if the pattern can contain more than Long.MAX_VALUE points.
      Specified by:
      largePointCount in interface Pattern
      Returns:
      the number of integer points in this pattern.
      See Also:
    • isPointCountVeryLarge

      public boolean isPointCountVeryLarge()
      This implementation returns false. Please override this method if the pattern can contain more than Long.MAX_VALUE points.
      Returns:
      true if the number of points in this pattern is greater than Long.MAX_VALUE.
    • points

      public abstract Set<Point> points()
      Description copied from interface: Pattern
      Returns a set of all points of this pattern.

      The result of this method is immutable (Collections.unmodifiableSet). Moreover, the result is always the same for different calls of this method for the same instance — there are no ways to change it, in particular, via any custom methods of the implementation class (it is a conclusion from the common requirement, that all implementations of this interface must be immutable).

      The returned set is always non-empty, and the number of its elements is always equal to Pattern.pointCount().

      Warning! This method can work slowly for some forms of large patterns. In these cases, this method can also throw TooManyPointsInPatternError or OutOfMemoryError. This method surely fails (throws one of these exception), if the total number of points Pattern.pointCount()>Integer.MAX_VALUE, because Java Set object cannot contain more than Integer.MAX_VALUE elements.

      For example, implementations of the rectangular patterns allow to successfully define a very large 3D parallelepiped n x n x n. Fur such pattern, this method will require a lot of memory for n=1000 and will fail (probably with TooManyPointsInPatternError) for n=2000 (20003>Integer.MAX_VALUE).

      There is a guarantee, that if this object implements DirectPointSetPattern interface, then this method requires not greater than O(N) operations and memory (N=pointCount()) and never throws TooManyPointsInPatternError.

      Note: this method works very quickly (O(1) operations) in SimplePattern class.

      Specified by:
      points in interface Pattern
      Returns:
      all points of this pattern.
    • roundedPoints

      public Set<IPoint> roundedPoints()
      This implementation calls points() method and returns a new set, built from the returned set of real points by conversion of every point to an integer point via Point.toRoundedPoint() method, as written in comments to this method in Pattern interface. Please override this method if there is more efficient way to get all rounded points.
      Specified by:
      roundedPoints in interface Pattern
      Returns:
      all points of this pattern, rounded to the nearest integer points.
      Throws:
      TooManyPointsInPatternError - if points() method throws this exception (OutOfMemoryError can be also thrown in this case).
    • coordRange

      public abstract Range coordRange(int coordIndex)
      Description copied from interface: Pattern
      Returns the minimal and maximal coordinate with the given index (Point.coord(coordIndex)) among all points of this pattern. The minimal coordinate will be r.min(), the maximal coordinate will be r.max(), where r is the result of this method.

      There is a guarantee, that if this object implements RectangularPattern interface, then this method works very quickly (O(1) operations) and without exceptions.

      Moreover, all patterns, implemented in this package, have very quick implementations of this method (O(1) operations). Also, the implementations of this method in this package never throw exceptions.

      It is theoretically possible, that in custom implementations of this interface (outside this package) this method will work slowly, up to O(N) operations, N is the number of points in this pattern. However, even in such implementations this method must not lead to TooManyPointsInPatternError / OutOfMemoryError, like Pattern.points() method.

      Specified by:
      coordRange in interface Pattern
      Parameters:
      coordIndex - the index of the coordinate (0 for x, 1 for y, 2 for z, etc.).
      Returns:
      the range from minimal to maximal coordinate with this index.
      See Also:
    • coordArea

      public RectangularArea coordArea()
      This implementation is based on the loop of calls of coordRange(int) method for all coordinate indexes from 0 to dimCount()-1.
      Specified by:
      coordArea in interface Pattern
      Returns:
      the ranges from minimal to maximal grid index for all space dimensions.
      See Also:
    • coordMin

      public Point coordMin()
      This implementation is based on the loop of calls of coordRange(int) method for all coordinate indexes from 0 to dimCount()-1.
      Specified by:
      coordMin in interface Pattern
      Returns:
      minimal coordinates for all space dimensions as a point.
    • coordMax

      public Point coordMax()
      This implementation is based on the loop of calls of coordRange(int) method for all coordinate indexes from 0 to dimCount()-1.
      Specified by:
      coordMax in interface Pattern
      Returns:
      maximal coordinates for all space dimensions as a point.
    • roundedCoordRange

      public IRange roundedCoordRange(int coordIndex)
      This implementation returns coordRange(coordIndex).toRoundedRange().
      Specified by:
      roundedCoordRange in interface Pattern
      Parameters:
      coordIndex - the index of the coordinate (0 for x, 1 for y, 2 for z, etc.).
      Returns:
      the range from minimal to maximal coordinate with this index, rounded to the long values.
      Throws:
      IndexOutOfBoundsException - if coordIndex<0 or coordIndex>=dimCount().
      See Also:
    • roundedCoordArea

      public IRectangularArea roundedCoordArea()
      This implementation is based on the loop of calls of roundedCoordRange(int) method for all coordinate indexes from 0 to dimCount()-1.
      Specified by:
      roundedCoordArea in interface Pattern
      Returns:
      the ranges from minimal to maximal coordinate for all space dimensions, rounded to the long values.
    • isSurelySinglePoint

      public abstract boolean isSurelySinglePoint()
      Description copied from interface: Pattern
      Returns true if this pattern consists of the single point, i.e. if pointCount()==1.

      There are no strict guarantees that this method always returns true if the pattern consist of the single point. (In some complex situations, such analysis can be too difficult. In particular, if the pattern is a Minkowski sum, then limited floating-point precision can lead to equality of all points of the result. Simple example: a Minkowski sum of two-point one-dimensional pattern, consisting of points 0.0 and 0.000001, and one-point 251=2251799813685248.0, contains only 1 point 251, because the computer cannot represent precise value 2251799813685248.000001 in double type and rounds it to 2251799813685248.0. In such situations, this method sometimes may incorrectly return false.)

      But there is the reverse guarantee: if this method returns true, the number of points in this pattern is always 1.

      Unlike Pattern.pointCount() method, there is a guarantee that this method never works very slowly and cannot lead to TooManyPointsInPatternError / OutOfMemoryError. In situations, when the number of points is very large (and, so, Pattern.pointCount() method is not safe in use), this method must detect this fact in reasonable time and return false.

      There is a guarantee, that if this object implements QuickPointCountPattern interface, then this method works very quickly (O(1) operations) and absolutely correctly (always returns true if and only if pointCount()==1).

      Specified by:
      isSurelySinglePoint in interface Pattern
      Returns:
      true if it is one-point pattern.
      See Also:
    • isSurelyOriginPoint

      public boolean isSurelyOriginPoint()
      This implementation checks isSurelySinglePoint(), and if it is true, checks, whether the only element of points() set is the origin.

      This method caches its results: the following calls will work faster.

      Specified by:
      isSurelyOriginPoint in interface Pattern
      Returns:
      true if it is one-point pattern containing the origin of coordinates as the single point.
      See Also:
    • isSurelyInteger

      public boolean isSurelyInteger()
      This implementation calls points() method and checks, whether all returned points are integer, i.e. Point.isInteger() method returns true for all elements the returned set. If all points, returned by points() call, are integer, this method returns true, in other case it returns false.

      This method caches its results: the following calls will work faster.

      Note: according the comments to this method in Pattern interface, such implementation is correct only if minkowskiDecomposition(int), unionDecomposition(int) and allUnionDecompositions(int) methods have default implementations (not overridden). If some of them are overridden and return some non-trivial results, this method must be also overridden.

      Note: according the comments to this method in Pattern interface, this method must be overridden if the number of points can be very large and a call of points() method leads to a risk of TooManyPointsInPatternError / OutOfMemoryError. In particular, this method should be usually overridden in implementations of RectangularPattern.

      Specified by:
      isSurelyInteger in interface Pattern
      Returns:
      true if this pattern assuredly contain only integer points.
    • round

      public UniformGridPattern round()
      This implementation calls roundedPoints() method and constructs a new integer pattern on the base of this set, like as it is performed in Patterns.newIntegerPattern(java.util.Collection) method. Please override this method if there is more efficient way to round this pattern, for example, if this pattern is already an integer one.
      Specified by:
      round in interface Pattern
      Returns:
      the integer pattern, geometrically nearest to this one.
      Throws:
      TooManyPointsInPatternError - if this pattern is not DirectPointSetPattern and not RectangularPattern and if, at the same time, the number of points is greater than Integer.MAX_VALUE or, in some rare situations, is near this limit (OutOfMemoryError can be also thrown instead of this exception).
    • projectionAlongAxis

      public abstract Pattern projectionAlongAxis(int coordIndex)
      Description copied from interface: Pattern
      Returns the projection of this pattern along the given axis. The number of dimensions in the resulting pattern (Pattern.dimCount()) is less by 1, than in this one.

      More precisely, the resulting pattern consists of the points, obtained from all points of this pattern by the call point.projectionAlongAxis(coordIndex).

      The returned pattern always implements DirectPointSetPattern if this pattern implements DirectPointSetPattern

      The returned pattern always implements RectangularPattern if this pattern implements RectangularPattern.

      The returned pattern always implements UniformGridPattern if this pattern implements UniformGridPattern.

      There is a guarantee, that this method does not try to allocate much more memory, that it is required for storing this pattern itself, and that it never throws TooManyPointsInPatternError. For comparison, an attempt to do the same operation via getting all points (Pattern.points() method), correcting them and forming a new pattern via Patterns.newPattern(java.util.Collection) will lead to TooManyPointsInPatternError / OutOfMemoryError for some forms of large patterns.

      Specified by:
      projectionAlongAxis in interface Pattern
      Parameters:
      coordIndex - the index of the coordinate (0 for x-axis , 1 for y-axis, 2 for za-xis, etc.).
      Returns:
      the projection of this pattern (its Pattern.dimCount() is equal to thisInstance.Pattern.dimCount()-1).
    • minBound

      public Pattern minBound(int coordIndex)
      This implementation calls points() method and builds the result on the base of analysis of the returned point set. Please override this method if there is more efficient way to find the result, for example, if this pattern is a rectangular one.
      Specified by:
      minBound in interface Pattern
      Parameters:
      coordIndex - the index of the coordinate (0 for x-axis , 1 for y-axis, 2 for za-xis, etc.).
      Returns:
      the minimal boundary of this pattern for the given axis.
      Throws:
      IndexOutOfBoundsException - if coordIndex<0 or coordIndex>=dimCount().
      TooManyPointsInPatternError - if this pattern is not DirectPointSetPattern and not RectangularPattern and if, at the same time, the number of points is greater than Integer.MAX_VALUE or, in some rare situations, is near this limit (OutOfMemoryError can be also thrown instead of this exception).
      See Also:
    • maxBound

      public Pattern maxBound(int coordIndex)
      This implementation calls points() method and builds the result on the base of analysis of the returned point set. Please override this method if there is more efficient way to find the result, for example, if this pattern is a rectangular one.
      Specified by:
      maxBound in interface Pattern
      Parameters:
      coordIndex - the index of the coordinate (0 for x-axis , 1 for y-axis, 2 for za-xis, etc.).
      Returns:
      the maximal boundary of this pattern for the given axis.
      Throws:
      IndexOutOfBoundsException - if coordIndex<0 or coordIndex>=dimCount().
      TooManyPointsInPatternError - if this pattern is not DirectPointSetPattern and not RectangularPattern and if, at the same time, the number of points is greater than Integer.MAX_VALUE or, in some rare situations, is near this limit (OutOfMemoryError can be also thrown instead of this exception).
      See Also:
    • carcass

      public Pattern carcass()
      This implementation just returns this object. Please override this method (together with maxCarcassMultiplier()), if your class can provide better results.

      Note: AbstractUniformGridPattern class provides much better implementation.

      Specified by:
      carcass in interface Pattern
      Returns:
      the carcass of this pattern.
    • maxCarcassMultiplier

      public int maxCarcassMultiplier()
      This implementation just returns 2. Please override this method (together with carcass()), if your class can provide better results.

      Note: AbstractUniformGridPattern class provides much better implementation.

      Specified by:
      maxCarcassMultiplier in interface Pattern
      Returns:
      the maximal multiplier (≥2), for which the calculation of the Minkowski multiple can be optimized by using the carcass.
    • shift

      public abstract Pattern shift(Point shift)
      Description copied from interface: Pattern
      Returns this pattern, shifted by the argument.

      More precisely, the resulting pattern consists of the points, obtained from all points of this pattern by the call point.add(shift).

      The returned pattern always implements DirectPointSetPattern if this pattern implements DirectPointSetPattern

      The returned pattern always implements RectangularPattern if this pattern implements RectangularPattern.

      The returned pattern always implements UniformGridPattern if this pattern implements UniformGridPattern.

      There is a guarantee, that this method does not try to allocate much more memory, that it is required for storing this pattern itself, and that it never throws TooManyPointsInPatternError. For comparison, an attempt to do the same operation via getting all points (Pattern.points() method), correcting them and forming a new pattern via Patterns.newPattern(java.util.Collection) will lead to TooManyPointsInPatternError / OutOfMemoryError for some forms of large patterns.

      Warning: this method can fail with TooLargePatternCoordinatesException, if some of new points violate restrictions, described in the comments to this interface, section "Coordinate restrictions" (for example, due to very large shift).

      However, TooLargePatternCoordinatesException is impossible in many important cases, when this pattern is an integer pattern and each coordinate Xj=shift.coord(j) of the argument is equal to −xj for some some point (x0, x1, ..., xn−1) of this pattern. In particular, you can use this method for integer patterns without a risk of TooLargePatternCoordinatesException in the following situations:

      See more details in the comments to this interface, section "Coordinate restrictions", the theorem II.

      Specified by:
      shift in interface Pattern
      Parameters:
      shift - the shift.
      Returns:
      the shifted pattern.
    • symmetric

      public Pattern symmetric()
      This implementation calls multiply(-1.0). There are no reasons to override this method usually.
      Specified by:
      symmetric in interface Pattern
      Returns:
      the symmetric pattern.
    • multiply

      public Pattern multiply(double multiplier)
      This implementation creates Java array double[] by the call "a = new double[dimCount]", fills all its elements by multiplier argument and then calls scale(a). There are no reasons to override this method usually.
      Specified by:
      multiply in interface Pattern
      Parameters:
      multiplier - the scale along all coordinates.
      Returns:
      the scaled pattern.
      Throws:
      TooLargePatternCoordinatesException - if the set of scaled points does not fulfil the restrictions, described in the comments to Pattern interface, section "Coordinate restrictions".
      See Also:
    • scale

      public abstract Pattern scale(double... multipliers)
      Description copied from interface: Pattern
      Returns this pattern, scaled by the specified multipliers along all coordinates.

      More precisely, the resulting pattern consists of the points, obtained from all points of this pattern by the call point.scale(multipliers).

      The returned pattern always implements DirectPointSetPattern if this pattern implements DirectPointSetPattern

      The returned pattern always implements RectangularPattern if this pattern implements RectangularPattern.

      The returned pattern always implements UniformGridPattern if this pattern implements UniformGridPattern.

      There is a guarantee, that this method does not try to allocate much more memory, that it is required for storing this pattern itself, and that it never throws TooManyPointsInPatternError. For comparison, an attempt to do the same operation via getting all points (Pattern.points() method), correcting them and forming a new pattern via Patterns.newPattern(java.util.Collection) will lead to TooManyPointsInPatternError / OutOfMemoryError for some forms of large patterns.

      Warning: this method can fail with TooLargePatternCoordinatesException, if some of new points violate restrictions, described in the comments to this interface, section "Coordinate restrictions" (for example, due to very large multipliers). However, such failure is obviously impossible, if all multipliers are in range -1.0<=multipliers[k]<=1.0.

      Specified by:
      scale in interface Pattern
      Parameters:
      multipliers - the scales along coordinates.
      Returns:
      the scaled pattern.
      See Also:
    • minkowskiAdd

      public Pattern minkowskiAdd(Pattern added)
      This implementation is based on the loop for all points returned by points() method in both patterns and always returns a direct point-set pattern, consisting of sums of all point pairs. This algorithm may be very slow for large patterns (O(NM) operations, N=pointCount(), M=added.pointCount()) and does not work at all if the number of resulting points is greater than Integer.MAX_VALUE. Please override this method if there is better implementation.
      Specified by:
      minkowskiAdd in interface Pattern
      Parameters:
      added - another pattern.
      Returns:
      the Minkowski sum of this and another patterns.
      Throws:
      NullPointerException - if the argument is null.
      IllegalArgumentException - if the numbers of space dimensions of both patterns are different.
      TooManyPointsInPatternError - for some forms of large patterns, if the number of points in this, added or result pattern is greater than Integer.MAX_VALUE or, maybe, is near this limit
      TooLargePatternCoordinatesException - if the resulting set of points does not fulfil the restrictions, described in the comments to Pattern interface, section "Coordinate restrictions".
      See Also:
    • minkowskiSubtract

      public Pattern minkowskiSubtract(Pattern subtracted)
      This implementation is based on the loop for all points returned by points() method in both patterns and always returns a direct point-set pattern. This algorithm may be very slow for large patterns (O(NM) operations, N=pointCount(), M=added.pointCount()) and does not work at all if the number of resulting points is greater than Integer.MAX_VALUE. Please override this method if there is better implementation.
      Specified by:
      minkowskiSubtract in interface Pattern
      Parameters:
      subtracted - another pattern.
      Returns:
      the erosion of this pattern by the specified pattern or null if this erosion is the empty set.
      Throws:
      NullPointerException - if the argument is null.
      IllegalArgumentException - if the numbers of space dimensions of both patterns are different.
      TooManyPointsInPatternError - for some forms of large patterns, if the number of points in this, subtracted or result pattern is greater than Integer.MAX_VALUE or, maybe, is near this limit
      TooLargePatternCoordinatesException - if the resulting set of points does not fulfil the restrictions, described in the comments to Pattern interface, section "Coordinate restrictions".
      See Also:
    • minkowskiDecomposition

      public List<Pattern> minkowskiDecomposition(int minimalPointCount)
      This implementation just returns Collections.<Pattern>singletonList(thisInstance).

      Note: AbstractUniformGridPattern class provides much better implementation for patterns, recognized as rectangular by UniformGridPattern.isActuallyRectangular() method.

      Specified by:
      minkowskiDecomposition in interface Pattern
      Parameters:
      minimalPointCount - this method usually does not decompose patterns that contain less than minimalPointCount points.
      Returns:
      the decomposition of this pattern to Minkowski sum; always contains ≥1 elements.
      Throws:
      IllegalArgumentException - if the argument is negative.
    • hasMinkowskiDecomposition

      public boolean hasMinkowskiDecomposition()
      This implementation just returns false.
      Specified by:
      hasMinkowskiDecomposition in interface Pattern
      Returns:
      true if the Minkowski decomposition contains 2 or more elements; always false in this implementation.
    • unionDecomposition

      public List<Pattern> unionDecomposition(int minimalPointCount)
      This implementation returns allUnionDecompositions(minimalPointCount).get(0).
      Specified by:
      unionDecomposition in interface Pattern
      Parameters:
      minimalPointCount - this method usually does not decompose patterns that contain less than minimalPointCount points.
      Returns:
      a decomposition of this pattern into the union of patterns; always contains ≥1 elements.
      Throws:
      IllegalArgumentException - if the argument is negative.
    • allUnionDecompositions

      public List<List<Pattern>> allUnionDecompositions(int minimalPointCount)
      This implementation just returns the list containing 1 list, containing this instance as the only element: Collections.singletonList(Collections.<Pattern>singletonList(thisInstance)).

      Note: AbstractUniformGridPattern class provides much better implementation.

      Specified by:
      allUnionDecompositions in interface Pattern
      Parameters:
      minimalPointCount - this method usually does not decompose patterns that contain less than minimalPointCount points.
      Returns:
      several good variants of decomposition of this pattern to the union of patterns; the result always contains ≥1 elements, and all its elements also contain ≥1 elements.
      Throws:
      IllegalArgumentException - if the argument is negative.
    • isAllowedPoint

      public static boolean isAllowedPoint(Point point)
      Returns true if and only if all coordinates of the specified point lie in range −Pattern.MAX_COORDINATExjPattern.MAX_COORDINATE.

      Actually this method checks the 1st restriction for coordinates of any pattern: see comments to Pattern interface, section "Coordinate restrictions".

      Parameters:
      point - some point.
      Returns:
      whether this point is an allowed point for patterns.
      Throws:
      NullPointerException - if the argument is null.
    • isAllowedCoordRange

      public static boolean isAllowedCoordRange(Range range)
      Returns true if and only if both boundaries of the specified range, a=range.min() and b=range.max(), lie in range Pattern.MAX_COORDINATEabPattern.MAX_COORDINATE and, at the same time, the call Patterns.isAllowedDifference(a,b) returns true.

      This method helps to check the 2nd restriction for coordinates of any pattern: see comments to Pattern interface, section "Coordinate restrictions".

      Parameters:
      range - some range.
      Returns:
      whether this range is an allowed coordinate range for patterns.
      Throws:
      NullPointerException - if the argument is null.
    • checkCoordIndex

      protected final void checkCoordIndex(int coordIndex)
      Throws IndexOutOfBoundsException if coordIndex<0 or coordIndex>=dimCount(). Does nothing in other case.
      Parameters:
      coordIndex - checked index of the coordinate.
      Throws:
      IndexOutOfBoundsException - if coordIndex<0 or coordIndex>=dimCount().