/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.sis.internal.processing.isoline;

import java.util.Map;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.awt.Point;
import java.awt.Rectangle;
import java.awt.Shape;
import java.awt.geom.Path2D;
import org.opengis.referencing.operation.MathTransform;
import org.opengis.referencing.operation.TransformException;
import org.apache.sis.internal.feature.j2d.PathBuilder;
import org.apache.sis.util.Debug;


/**
 * Iterator over contouring grid cells together with an interpolator and an assembler of polyline segments.
 * A single instance of this class is created by {@code Isolines.generate(…)} for all bands to process in a
 * given image. {@code Tracer} is used for doing a single iteration over all image pixels.
 *
 * @author  Johann Sorel (Geomatys)
 * @author  Martin Desruisseaux (Geomatys)
 * @version 1.3
 *
 * @see <a href="https://en.wikipedia.org/wiki/Marching_squares">Marching squares on Wikipedia</a>
 *
 * @since 1.1
 * @module
 */
final class Tracer {
    /**
     * Mask to apply on {@link Level#isDataAbove} for telling that value in a corner is higher than the level value.
     * Values are defined in {@code PixelIterator.Window} iteration order: from left to right, then top to bottom.
     *
     * <p>Note: there is some hard-coded dependencies to those exact values.
     * If values are changed, search for example for {@code log2(UPPER_RIGHT)} in comments.</p>
     */
    static final int UPPER_LEFT = 1, UPPER_RIGHT = 2, LOWER_LEFT = 4, LOWER_RIGHT = 8;

    /**
     * The 2×2 window containing pixel values in the 4 corners of current contouring grid cell.
     * Values are always stored with band index varying fastest, then column index, then row index.
     * The length of this array is <var>(number of bands)</var> × 2 (width) × 2 (height).
     */
    private final double[] window;

    /**
     * Increment to the position for reading next sample value.
     * It corresponds to the number of bands in {@link #window}.
     */
    private final int pixelStride;

    /**
     * Pixel coordinate on the left side of the cell where to interpolate.
     * The range is 0 inclusive to {@code domain.width} exclusive.
     */
    int x;

    /**
     * Pixel coordinate on the top side of the cell where to interpolate.
     * The range is 0 inclusive to {@code domain.height} exclusive.
     */
    int y;

    /**
     * Translation to apply on coordinates. For isolines computed sequentially, this is the image origin
     * (often 0,0 but not necessarily). For isolines computed in parallel, the translations are different
     * for each computation tile.
     */
    private final double translateX, translateY;

    /**
     * Final transform to apply on coordinates (integer source coordinates at pixel centers).
     * Can be {@code null} if none.
     */
    private final MathTransform gridToCRS;

    /**
     * Creates a new position for the given data window.
     *
     * @param  window       the 2×2 window containing pixel values in the 4 corners of current contouring grid cell.
     * @param  pixelStride  increment to the position in {@code window} for reading next sample value.
     * @param  domain       pixel coordinates where iteration will happen.
     * @param  gridToCRS    final transform to apply on coordinates (integer source coordinates at pixel centers).
     */
    Tracer(final double[] window, final int pixelStride, final Rectangle domain, final MathTransform gridToCRS) {
        this.window      = window;
        this.pixelStride = pixelStride;
        this.translateX  = domain.x;
        this.translateY  = domain.y;
        this.gridToCRS   = gridToCRS;
    }

    /**
     * Builder of polylines for a single level. The segments to create are determined by a set
     * of {@linkplain #isDataAbove four flags} (one for each corner) encoded in an integer.
     * The meaning of those flags is described in Wikipedia "Marching squares" article,
     * except that this implementation uses different values.
     */
    final class Level {
        /**
         * Band number where to read values in the {@link #window} array.
         */
        private final int band;

        /**
         * The level value.
         *
         * @see #interpolate(int, int)
         */
        final double value;

        /**
         * Bitset telling which corners have a value greater than this isoline level {@linkplain #value}.
         * Each corner is associated to one of the bits illustrated below, where bit (0) is the less significant.
         * Note that this bit order is different than the order used in Wikipedia "Marching squares" article.
         * The order used in this class allows more direct bitwise operations as described in next section.
         *
         * {@preformat text
         *     (0)╌╌╌(1)
         *      ╎     ╎
         *     (2)╌╌╌(3)
         * }
         *
         * Bits are set to 1 where the data value is above the isoline {@linkplain #value}, and 0 where the data value
         * is below the isoline value. Data values exactly equal to the isoline value are handled as if they were greater.
         * It does not matter for interpolations: we could flip this convention randomly, the interpolated points would
         * still be the same. It could change the way line segments are assembled in a single {@link PolylineBuffer},
         * but the algorithm stay consistent if we always apply the same rule for all points.
         *
         * <h4>Reusing bits from previous iteration</h4>
         * We will iterate on pixels from left to right, then from top to bottom. With that iteration order,
         * bits 0 and 2 can be obtained from the bit pattern of previous iteration with a simple bit shift.
         *
         * @see #UPPER_LEFT
         * @see #UPPER_RIGHT
         * @see #LOWER_LEFT
         * @see #LOWER_RIGHT
         */
        int isDataAbove;

        /**
         * The polyline to be continued on the next column. This is a single instance because iteration happens
         * from left to right before top to bottom. This instance is non-empty if the cell in previous iteration
         * was like below (all those examples have a line crossing the right border):
         *
         * {@preformat text
         *     ●╌╌╌╌╌╌●              ○╌╱╌╌╌╌●╱             ○╌╌╌╌╲╌●
         *     ╎      ╎              ╎╱     ╱              ╎     ╲╎
         *    ─┼──────┼─             ╱     ╱╎              ╎      ╲
         *     ○╌╌╌╌╌╌○             ╱●╌╌╌╌╱╌○              ○╌╌╌╌╌╌○╲
         * }
         *
         * This field {@link PolylineBuffer#isEmpty() is empty} if the cell in previous iteration was like below
         * (no line cross the right border):
         *
         * {@preformat text
         *     ○╌╲╌╌╌╌●              ○╌╌╌┼╌╌●
         *     ╎  ╲   ╎              ╎   │  ╎
         *     ╎   ╲  ╎              ╎   │  ╎
         *     ○╌╌╌╌╲╌●              ○╌╌╌┼╌╌●
         * }
         */
        private final PolylineBuffer polylineOnLeft;

        /**
         * The polylines in each column which need to be continued on the next row.
         * This array contains empty instances in columns where there are no polylines to continue on next row.
         * For non-empty element at index <var>x</var>, values on the left border are given by pixels at coordinate
         * {@code x} and values on the right border are given by pixels at coordinate {@code x+1}. Example:
         *
         * {@preformat text
         *            ○╌╌╌╌╌╌●╱
         *            ╎ Top  ╱
         *            ╎ [x] ╱╎
         *     ●╌╌╌╌╌╌●╌╌╌╌╱╌○
         *     ╎ Left ╎██████╎ ← Cell where to create a segment
         *    ─┼──────┼██████╎
         *     ○╌╌╌╌╌╌○╌╌╌╌╌╌○
         *            ↑
         *     x coordinate of first pixel (upper-left corner)
         * }
         */
        private final PolylineBuffer[] polylinesOnTop;

        /**
         * Paths that have not yet been closed. The {@link PolylineBuffer} coordinates are copied in this map when
         * iteration finished on a row but the polyline under construction will not be continued by the next row,
         * or when the {@link #closeLeftWithTop(PolylineBuffer)} method has been invoked but the geometry to close
         * is still not complete. This map accumulates those partial shapes for assembling them later when missing
         * parts become available.
         *
         * <h4>Map keys</h4>
         * Keys are grid coordinates rounded toward 0. The coordinate having fraction digits has its bits inverted
         * by the {@code ~} operator. For each point, there is at most one coordinate having such fraction digits.
         *
         * <h4>Map values</h4>
         * {@code Fragments} instances are list of {@code double[]} arrays to be concatenated in a single polygon later.
         * For a given {@code Fragments} list, all {@code double[]} arrays at even indices shall have their points read
         * in reverse order and all {@code double[]} arrays at odd indices shall have their points read in forward order.
         * The list may contain null elements when there is no data in the corresponding iteration order.
         *
         * @see #closeLeftWithTop(PolylineBuffer)
         */
        private final Map<Point,Fragments> partialPaths;

        /**
         * Builder of isolines as a Java2D shape, created when first needed.
         * The {@link PolylineBuffer} coordinates are copied in this path when a geometry is closed.
         *
         * @see #writeTo(Joiner, PolylineBuffer[], boolean)
         */
        private Joiner path;

        /**
         * The isolines as a Java2D shape, created by {@link #finish()}.
         * This is the shape to be returned to user for this level after we finished to process all cells.
         */
        Shape shape;

        /**
         * Creates new isoline levels for the given value.
         *
         * @param  band   band number where to read values in the {@link #window} array.
         * @param  value  the isoline level value.
         * @param  width  the contouring grid cell width (one cell smaller than image width).
         */
        Level(final int band, final double value, final int width) {
            this.band      = band;
            this.value     = value;
            partialPaths   = new HashMap<>();
            polylineOnLeft = new PolylineBuffer();
            polylinesOnTop = new PolylineBuffer[width];
            for (int i=0; i<width; i++) {
                polylinesOnTop[i] = new PolylineBuffer();
            }
        }

        /**
         * Initializes the {@link #isDataAbove} value with values for the column on the right side.
         * After this method call, the {@link #UPPER_RIGHT} and {@link #LOWER_RIGHT} bits still need to be set.
         *
         * @see Isolines#setMaskBit(double, int)
         */
        final void nextColumn() {
            /*
             * Move bits on the right side to the left side.
             * The 1 operand in >>> is the hard-coded value
             * of    log2(UPPER_RIGHT) - log2(UPPER_LEFT)
             * and   log2(LOWER_RIGHT) - log2(LOWER_LEFT).
             */
            isDataAbove = (isDataAbove & (UPPER_RIGHT | LOWER_RIGHT)) >>> 1;
        }

        /**
         * Adds segments computed for values in a single pixel. Interpolations are determined by the 4 lowest bits
         * of {@link #isDataAbove}. The {@link #polylineOnLeft} and {@code polylinesOnTop[x]} elements are updated
         * by this method.
         *
         * <h4>How NaN values are handled</h4>
         * This algorithm does not need special attention for {@link Double#NaN} values. Interpolations will produce
         * {@code NaN} values and append them to the correct polyline (which does not depend on interpolation result)
         * like real values. Those NaN values will be filtered later in another method, when copying coordinates in
         * the {@link PathBuilder}.
         */
        @SuppressWarnings("AssertWithSideEffects")
        final void interpolate() throws TransformException {
            /*
             * Note: `interpolateMissingLeftSide()` and `interpolateMissingTopSide(…)` should do interpolations
             * only for cells in the first column and first row respectively. We could avoid those method calls
             * for all other cells if we add two flags in the `isDataAbove` bitmask: FIRST_ROW and FIRST_COLUMN.
             * The switch cases then become something like below:
             *
             *     case <bitmask> | FIRST_COLUMN | FIRST_ROW:
             *     case <bitmask> | FIRST_COLUMN: {
             *         interpolateMissingLeftSide();
             *         // Fall through
             *     }
             *     case <bitmask> | FIRST_ROW:
             *     case <bitmask>: {
             *         // Interpolations on other borders.
             *         break;
             *     }
             *
             * We tried that approach, but benchmarking on Java 15 suggested a small performance decrease
             * instead of an improvement. It may be worth to try again in the future, after advancement
             * in compiler technology.
             */
            switch (isDataAbove) {
                default: {
                    throw new AssertionError(isDataAbove);      // Should never happen.
                }
                /*     ○╌╌╌╌╌╌○        ●╌╌╌╌╌╌●
                 *     ╎      ╎        ╎      ╎
                 *     ╎      ╎        ╎      ╎
                 *     ○╌╌╌╌╌╌○        ●╌╌╌╌╌╌●
                 */
                case 0:
                case UPPER_LEFT | UPPER_RIGHT | LOWER_LEFT | LOWER_RIGHT: {
                    assert polylinesOnTop[x].isEmpty();
                    assert polylineOnLeft   .isEmpty();
                    break;
                }
                /*     ○╌╌╌╌╌╌○        ●╌╌╌╌╌╌●
                 *    ─┼──────┼─      ─┼──────┼─
                 *     ╎      ╎        ╎      ╎
                 *     ●╌╌╌╌╌╌●        ○╌╌╌╌╌╌○
                 */
                case LOWER_LEFT | LOWER_RIGHT:
                case UPPER_LEFT | UPPER_RIGHT: {
                    assert polylinesOnTop[x].isEmpty();
                    interpolateMissingLeftSide();
                    interpolateOnRightSide();                   // Will be the left side of next column.
                    break;
                }
                /*     ○╌╌╌┼╌╌●        ●╌╌╌┼╌╌○
                 *     ╎   │  ╎        ╎   │  ╎
                 *     ╎   │  ╎        ╎   │  ╎
                 *     ○╌╌╌┼╌╌●        ●╌╌╌┼╌╌○
                 */
                case UPPER_RIGHT | LOWER_RIGHT:
                case UPPER_LEFT  | LOWER_LEFT: {
                    assert polylineOnLeft.isEmpty();
                    final PolylineBuffer polylineOnTop = polylinesOnTop[x];
                    interpolateMissingTopSide(polylineOnTop);
                    interpolateOnBottomSide(polylineOnTop);     // Will be top side of next row.
                    break;
                }
                /*    ╲○╌╌╌╌╌╌○       ╲●╌╌╌╌╌╌●
                 *     ╲      ╎        ╲      ╎
                 *     ╎╲     ╎        ╎╲     ╎
                 *     ●╌╲╌╌╌╌○        ○╌╲╌╌╌╌●
                 */
                case LOWER_LEFT:
                case UPPER_LEFT | UPPER_RIGHT | LOWER_RIGHT: {
                    assert polylinesOnTop[x].isEmpty();
                    interpolateMissingLeftSide();
                    interpolateOnBottomSide(polylinesOnTop[x].transferFrom(polylineOnLeft));
                    break;
                }
                /*     ○╌╌╌╌╲╌●        ●╌╌╌╌╲╌○
                 *     ╎     ╲╎        ╎     ╲╎
                 *     ╎      ╲        ╎      ╲
                 *     ○╌╌╌╌╌╌○╲       ●╌╌╌╌╌╌●╲
                 */
                case UPPER_RIGHT:
                case UPPER_LEFT | LOWER_LEFT | LOWER_RIGHT: {
                    assert polylineOnLeft.isEmpty();
                    interpolateMissingTopSide(polylineOnLeft.transferFrom(polylinesOnTop[x]));
                    interpolateOnRightSide();
                    break;
                }
                /*     ○╌╌╌╌╌╌○╱       ●╌╌╌╌╌╌●╱
                 *     ╎      ╱        ╎      ╱
                 *     ╎     ╱╎        ╎     ╱╎
                 *     ○╌╌╌╌╱╌●        ●╌╌╌╌╱╌○
                 */
                case LOWER_RIGHT:
                case UPPER_LEFT | UPPER_RIGHT | LOWER_LEFT: {
                    assert polylinesOnTop[x].isEmpty();
                    assert polylineOnLeft   .isEmpty();
                    interpolateOnRightSide();
                    interpolateOnBottomSide(polylinesOnTop[x].attach(polylineOnLeft));
                    // Bottom of this cell will be top of next row.
                    break;
                }
                /*     ●╌╱╌╌╌╌○        ○╌╱╌╌╌╌●
                 *     ╎╱     ╎        ╎╱     ╎
                 *     ╱      ╎        ╱      ╎
                 *    ╱○╌╌╌╌╌╌○       ╱●╌╌╌╌╌╌●
                 */
                case UPPER_LEFT:
                case UPPER_RIGHT | LOWER_LEFT | LOWER_RIGHT: {
                    closeLeftWithTop(polylinesOnTop[x]);
                    break;
                }
                /*     ○╌╱╌╌╌╌●╱      ╲●╌╌╌╌╲╌○
                 *     ╎╱     ╱        ╲     ╲╎
                 *     ╱     ╱╎        ╎╲     ╲
                 *    ╱●╌╌╌╌╱╌○        ○╌╲╌╌╌╌●╲
                 *
                 * Disambiguation of saddle points: use the average data value for the center of the cell.
                 * If the estimated center value is greater than the isoline value, the above drawings are
                 * okay and we do not need to change `isDataAbove`. This is the left side illustrated below.
                 * But if the center value is below isoline value, then we need to flip `isDataAbove` bits
                 * (conceptually; not really because we need to keep `isDataAbove` value for next iteration).
                 * This is the right side illustrated below.
                 *
                 *     ○╱╌╌●╱      ╲●╌╌╲○                        ╲○╌╌╲●        ●╱╌╌○╱
                 *     ╱ ● ╱        ╲ ● ╲                         ╲ ○ ╲        ╱ ○ ╱
                 *    ╱●╌╌╱○        ○╲╌╌●╲                        ●╲╌╌○╲      ╱○╌╌╱●
                 */
                case UPPER_RIGHT | LOWER_LEFT:
                case UPPER_LEFT | LOWER_RIGHT: {
                    double average = 0;
                    {   // Compute sum of 4 corners.
                        final double[] data = window;
                        int p = band;
                        do average += data[p];
                        while ((p += pixelStride) < data.length);
                        assert (p -= band) == pixelStride * 4 : p;
                        average /= 4;
                    }
                    boolean LLtoUR = isDataAbove == (LOWER_LEFT | UPPER_RIGHT);
                    LLtoUR ^= (average <= value);
                    final PolylineBuffer polylineOnTop = polylinesOnTop[x];
                    if (LLtoUR) {
                        closeLeftWithTop(polylineOnTop);
                        interpolateOnRightSide();
                        interpolateOnBottomSide(polylineOnTop.attach(polylineOnLeft));
                    } else {
                        interpolateMissingLeftSide();
                        final PolylineBuffer swap = new PolylineBuffer().transferFrom(polylineOnTop);
                        interpolateOnBottomSide(polylineOnTop.transferFrom(polylineOnLeft));
                        interpolateMissingTopSide(polylineOnLeft.transferFrom(swap));
                        interpolateOnRightSide();
                    }
                    break;
                }
            }
        }

        /**
         * Appends to {@link #polylineOnLeft} a point interpolated on the left side if that point is missing.
         * This interpolation should happens only in the first column.
         */
        private void interpolateMissingLeftSide() {
            if (polylineOnLeft.size == 0) {
                polylineOnLeft.append(translateX + (x),
                                      translateY + (y + interpolate(0, 2*pixelStride)));
            }
        }

        /**
         * Appends to {@code polylineOnTop} a point interpolated on the top side if that point is missing.
         * This interpolation should happens only in the first row.
         */
        private void interpolateMissingTopSide(final PolylineBuffer polylineOnTop) {
            if (polylineOnTop.size == 0) {
                interpolateOnTopSide(polylineOnTop);
            }
        }

        /**
         * Appends to the given polyline a point interpolated on the top side.
         */
        private void interpolateOnTopSide(final PolylineBuffer appendTo) {
            appendTo.append(translateX + (x + interpolate(0, pixelStride)),
                            translateY + (y));
        }

        /**
         * Appends to {@link #polylineOnLeft} a point interpolated on the right side.
         * The polyline on right side will become {@code polylineOnLeft} in next column.
         */
        private void interpolateOnRightSide() {
            polylineOnLeft.append(translateX + (x + 1),
                                  translateY + (y + interpolate(pixelStride, 3*pixelStride)));
        }

        /**
         * Appends to the given polyline a point interpolated on the bottom side.
         * The polyline on top side will become a {@code polylineOnBottoù} in next row.
         */
        private void interpolateOnBottomSide(final PolylineBuffer polylineOnTop) {
            polylineOnTop.append(translateX + (x + interpolate(2*pixelStride, 3*pixelStride)),
                                 translateY + (y + 1));
        }

        /**
         * Interpolates the position where the isoline passes between two values.
         *
         * @param  i1  index of first value in the buffer, ignoring band offset.
         * @param  i2  index of second value in the buffer, ignoring band offset.
         * @return a value interpolated between the values at the two given indices.
         */
        private double interpolate(final int i1, final int i2) {
            final double[] data = window;
            final int    p  = band;
            final double v1 = data[p + i1];
            final double v2 = data[p + i2];
            return (value - v1) / (v2 - v1);
        }

        /**
         * Joins {@link #polylineOnLeft} with {@code polylineOnTop}, saves their coordinates
         * and clear those {@link PolylineBuffer} instances for use in next cell.
         * The coordinates are written directly to {@link #path} if we got a closed polygon,
         * or otherwise are saved in {@link #partialPaths} for later processing.
         * This method is invoked for cells like below:
         *
         * {@preformat text
         *     ●╌╱╌╌╌╌○        ○╌╱╌╌╌╌●        ○╌╱╌╌╌╌●╱
         *     ╎╱     ╎        ╎╱     ╎        ╎╱     ╱
         *     ╱      ╎        ╱      ╎        ╱     ╱╎
         *    ╱○╌╌╌╌╌╌○       ╱●╌╌╌╌╌╌●       ╱●╌╌╌╌╱╌○
         * }
         *
         * This method does itself the interpolations on left side and top side. The two polylines
         * {@link #polylineOnLeft} and {@code polylineOnTop} will become empty after this method call.
         *
         * @param  polylineOnTop  value of {@code polylinesOnTop[x]}.
         * @throws TransformException if the {@link Tracer#gridToCRS} transform can not be applied.
         */
        private void closeLeftWithTop(final PolylineBuffer polylineOnTop) throws TransformException {
            interpolateMissingLeftSide();
            interpolateMissingTopSide(polylineOnTop);
            final PolylineBuffer[] polylines;
            if (polylineOnLeft.opposite == polylineOnTop) {
                assert polylineOnTop.opposite == polylineOnLeft;
                /*
                 * We have a loop: the polygon can be closed now, without copying coordinates to temporary buffers.
                 * Points in `PolylineBuffer` instances will be iterated in (reverse, forward) order respectively.
                 * Consequently the points we just interpolated will be first point and last point before closing.
                 */
                polylines = new PolylineBuffer[] {polylineOnTop, polylineOnLeft};    // (reverse, forward) point order.
            } else {
                /*
                 * Joining left and top polylines do not yet create a closed shape. Consequently we may not write
                 * in the `path` now. But maybe we can close the polygon later after more polylines are attached.
                 */
                final Fragments fragment = new Fragments(polylineOnLeft, polylineOnTop);
                if (fragment.isEmpty()) {
                    /*
                     * Fragment starts and ends with NaN values. We will not be able to complete a polygon.
                     * Better to write the polylines now for avoiding temporary copies of their coordinates.
                     */
                    polylines = new PolylineBuffer[] {
                        polylineOnLeft.opposite, polylineOnLeft, polylineOnTop, polylineOnTop.opposite
                    };
                } else if (fragment.addOrMerge(partialPaths)) {
                    /*
                     * The fragment has been merged with previously existing fragments and became a polygon.
                     * We can write the polygon immediately. There are no more references to those coordinates
                     * in the `partialPaths` map.
                     */
                    polylines = fragment.toPolylines();
                } else {
                    return;
                }
            }
            path = writeTo(path, polylines, true);
        }

        /**
         * Writes the content of given polyline without closing it as a polygon.
         * The given polyline will become empty after this method call.
         */
        private void writeFragment(final PolylineBuffer polyline) throws TransformException {
            final Fragments fragment = new Fragments(polyline, null);
            final PolylineBuffer[] polylines;
            final boolean close;
            if (fragment.isEmpty()) {
                close = false;
                polylines = new PolylineBuffer[] {polyline.opposite, polyline};     // (reverse, forward) point order.
            } else {
                close = fragment.addOrMerge(partialPaths);
                if (!close) {
                    // Keep in `partialPaths`. Maybe it can be closed later.
                    return;
                }
                polylines = fragment.toPolylines();
            }
            path = writeTo(path, polylines, close);
        }

        /**
         * Invoked after iteration on a single row has been completed. If there is a polyline
         * finishing on the right image border, the coordinates needs to be saved somewhere
         * because that {@link PolylineBuffer} will not be continued by cells on next rows.
         */
        final void finishedRow() throws TransformException {
            if (!polylineOnLeft.transferToOpposite()) {
                writeFragment(polylineOnLeft);
            }
            isDataAbove = 0;
        }

        /**
         * Invoked after the iteration has been completed on the full area of interest.
         * This method writes all remaining polylines to {@link #partialPaths}.
         * It assumes that {@link #finishedRow()} has already been invoked.
         * This {@link Level} instance can not be used anymore after this call.
         */
        final void finish() throws TransformException {
            assert polylineOnLeft.isEmpty();
            polylineOnLeft.coordinates = null;
            /*
             * This method sets various values to null for letting the garbage collector do its work.
             * This is okay for a `Level` instance which is not going to be used anymore, except for
             * reading the `shape` field.
             */
            for (int i=0; i < polylinesOnTop.length; i++) {
                writeFragment(polylinesOnTop[i]);
                polylinesOnTop[i] = null;
            }
            assert isConsistent();
        }

        /**
         * Verifies that {@link #partialPaths} consistency. Used for assertions only.
         */
        private boolean isConsistent() {
            for (final Map.Entry<Point,Fragments> entry : partialPaths.entrySet()) {
                if (!entry.getValue().isExtremity(entry.getKey())) return false;
            }
            return true;
        }

        /**
         * Transfers all {@code other} polylines into this instance. The {@code other} instance should be a neighbor,
         * i.e. an instance sharing a border with this instance. The {@code other} instance will become empty after
         * this method call.
         *
         * @param  other  a neighbor level (on top, left, right or bottom) to merge with this level.
         * @throws TransformException if an error occurred during polylines creation.
         */
        final void merge(final Level other) throws TransformException {
            assert other != this && other.value == value;
            if (path == null) {
                path = other.path;
            } else {
                path.append(other.path);
            }
            other.path = null;
            assert  this.isConsistent();
            assert other.isConsistent();
            final IdentityHashMap<Fragments,Boolean> done = new IdentityHashMap<>(other.partialPaths.size() / 2);
            for (final Map.Entry<Point,Fragments> entry : other.partialPaths.entrySet()) {
                final Fragments fragment = entry.getValue();
                if (done.put(fragment, Boolean.TRUE) == null) {
                    assert fragment.isExtremity(entry.getKey());
                    if (fragment.addOrMerge(partialPaths)) {
                        path = writeTo(path, fragment.toPolylines(), true);
                        fragment.clear();
                    }
                }
                entry.setValue(null);       // Let the garbage collector do its work.
            }
        }

        /**
         * Flushes any pending {@link #partialPaths} to {@link #path}. This method is invoked after
         * {@link #finish()} has been invoked for all sub-regions (many sub-regions may exist if
         * isoline generation has been splitted for parallel computation).
         *
         * @throws TransformException if an error occurred during polylines creation.
         */
        final void flush() throws TransformException {
            for (final Map.Entry<Point,Fragments> entry : partialPaths.entrySet()) {
                final Fragments fragment = entry.getValue();
                assert fragment.isExtremity(entry.getKey());
                if (!fragment.isEmpty()) {
                    path = writeTo(path, fragment.toPolylines(), false);
                    fragment.clear();       // Necessary because the same list appears twice in the map.
                }
                entry.setValue(null);       // Let the garbage collector do its work.
            }
            if (path != null) {
                shape = path.build();
                path  = null;
            }
        }

        /**
         * Appends the pixel coordinates of this level to the given path, for debugging purposes only.
         * The {@link #gridToCRS} transform is <em>not</em> applied by this method.
         * For avoiding confusing behavior, that transform should be null.
         *
         * @param  appendTo  where to append the coordinates.
         *
         * @see Isolines#toRawPath()
         */
        @Debug
        final void toRawPath(final Path2D appendTo) {
            final Shape s = (path != null) ? path.build() : shape;
            if (s != null) appendTo.append(s, false);
            polylineOnLeft.toRawPath(appendTo);
            for (final PolylineBuffer p : polylinesOnTop) {
                if (p != null) p.toRawPath(appendTo);
            }
        }
    }

    /**
     * Writes all given polylines to the specified path builder. Null {@code PolylineBuffer} instances are ignored.
     * {@code PolylineBuffer} instances at even index are written with their points in reverse order.
     * All given polylines are cleared by this method.
     *
     * @param  path       where to write the polylines, or {@code null} if not yet created.
     * @param  polylines  the polylines to write.
     * @param  close      whether to close the polygon.
     * @return the given path builder, or a newly created builder if the argument was null.
     * @throws TransformException if the {@link #gridToCRS} transform can not be applied.
     */
    private Joiner writeTo(Joiner path, final PolylineBuffer[] polylines, final boolean close) throws TransformException {
        for (int pi=0; pi < polylines.length; pi++) {
            final PolylineBuffer p = polylines[pi];
            if (p == null) {
                continue;
            }
            final int size = p.size;
            if (size == 0) {
                assert p.isEmpty();
                continue;
            }
            if (path == null) {
                path = new Joiner(gridToCRS);
            }
            path.append(p.coordinates, size, (pi & 1) == 0);
            p.clear();
        }
        if (path != null) {
            path.createPolyline(close);
        }
        return path;
    }
}
