This is an automated email from the ASF dual-hosted git repository. desruisseaux pushed a commit to branch geoapi-4.0 in repository https://gitbox.apache.org/repos/asf/sis.git
The following commit(s) were added to refs/heads/geoapi-4.0 by this push: new 943bd0e036 Move the `Process` inner class to a top-level class, renamed `Parallelized`. There is no code change (other than move/renaming) in this commit. 943bd0e036 is described below commit 943bd0e036311f6cf081b2db0065dbb20498e6bc Author: Martin Desruisseaux <martin.desruisse...@geomatys.com> AuthorDate: Mon Aug 15 20:42:50 2022 +0200 Move the `Process` inner class to a top-level class, renamed `Parallelized`. There is no code change (other than move/renaming) in this commit. --- .../sis/internal/processing/isoline/Isolines.java | 109 +++++--------------- .../internal/processing/isoline/Parallelized.java | 112 +++++++++++++++++++++ 2 files changed, 138 insertions(+), 83 deletions(-) diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/processing/isoline/Isolines.java b/core/sis-feature/src/main/java/org/apache/sis/internal/processing/isoline/Isolines.java index a0ec6005f2..76c642c072 100644 --- a/core/sis-feature/src/main/java/org/apache/sis/internal/processing/isoline/Isolines.java +++ b/core/sis-feature/src/main/java/org/apache/sis/internal/processing/isoline/Isolines.java @@ -30,7 +30,6 @@ import java.awt.image.RenderedImage; import org.opengis.coverage.grid.SequenceType; import org.opengis.referencing.operation.MathTransform; import org.opengis.referencing.operation.TransformException; -import org.apache.sis.internal.processing.image.TiledProcess; import org.apache.sis.image.PixelIterator; import org.apache.sis.util.ArgumentChecks; import org.apache.sis.util.ArraysExt; @@ -171,14 +170,35 @@ public final class Isolines { { ArgumentChecks.ensureNonNull("data", data); ArgumentChecks.ensureNonNull("levels", levels); - return new Process(data, cloneAndSort(levels), gridToCRS).execute(); + return new Parallelized(data, cloneAndSort(levels), gridToCRS).execute(); + } + + /** + * Merges results of two partial computations (tiles). + * This is invoked only in multi-threaded isoline computation. + * The {@code isolines} instances are modified in-place. + * The {@code neighbor} instances can be discarded after the merge. + * + * @param isolines the first set of isolines to merge. + * @param neighbor another set of isolines close to the first set. + * + * @see Parallelized + */ + static void merge(final Isolines[] isolines, final Isolines[] neighbor) throws TransformException { + for (int i=0; i<isolines.length; i++) { + final Isolines target = isolines[i]; + final Isolines source = neighbor[i]; + for (int j=0; j<target.levels.length; j++) { + target.levels[j].merge(source.levels[j]); + } + } } /** * Returns a provider of {@link PixelIterator} suitable to isoline computations. * It is critical that iterators use {@link SequenceType#LINEAR} iterator order. */ - private static PixelIterator.Builder iterators() { + static PixelIterator.Builder iterators() { return new PixelIterator.Builder().setIteratorOrder(SequenceType.LINEAR); } @@ -193,7 +213,7 @@ public final class Isolines { * @return the {@code isolines} array, returned for convenience. * @throws TransformException if an error occurred during polylines creation. */ - private static Isolines[] flush(final Isolines[] isolines) throws TransformException { + static Isolines[] flush(final Isolines[] isolines) throws TransformException { for (final Isolines isoline : isolines) { for (final Tracer.Level level : isoline.levels) { level.flush(); @@ -202,90 +222,13 @@ public final class Isolines { return isolines; } - /** - * Wraps {@code Isolines.generate(…)} calculation in a process for parallel execution. - * The source image is divided in sub-region and the isolines in each sub-region will - * be computed in a different thread. - */ - private static final class Process extends TiledProcess<Isolines[]> { - /** - * Values for which to compute isolines. An array should be provided for each band. - * If there is more bands than {@code levels.length}, the last array is reused for - * all remaining bands. - * - * @see #cloneAndSort(double[][]) - */ - private final double[][] levels; - - /** - * Transform from image upper left corner (in pixel coordinates) to geometry coordinates. - */ - private final MathTransform gridToCRS; - - /** - * Creates a process for parallel isoline computation. - * - * @param data image providing source values. - * @param levels values for which to compute isolines. - * @param gridToCRS transform from pixel coordinates to geometry coordinates, or {@code null} if none. - */ - Process(final RenderedImage data, final double[][] levels, final MathTransform gridToCRS) { - super(data, 1, 1, iterators()); - this.levels = levels; - this.gridToCRS = gridToCRS; - } - - /** - * Invoked by {@link TiledProcess} for creating a sub-task - * doing isoline computation on a sub-region of the image. - */ - @Override - protected Task createSubTask() { - return new Tile(); - } - - /** - * A sub-task doing isoline computation on a sub-region of the image. - * The region is determined by the {@link #iterator}. - */ - private final class Tile extends Task { - /** Isolines computed in the sub-region of this sub-task. */ - private Isolines[] isolines; - - /** Creates a new sub-task. */ - Tile() { - } - - /** Invoked in a background thread for performing isoline computation. */ - @Override protected void execute() throws TransformException { - isolines = generate(iterator, levels, gridToCRS); - } - - /** Invoked in a background thread for merging results of two sub-tasks. */ - @Override protected void merge(final Task neighbor) throws TransformException { - for (int i=0; i<isolines.length; i++) { - final Isolines target = isolines[i]; - final Isolines source = ((Tile) neighbor).isolines[i]; - for (int j=0; j<target.levels.length; j++) { - target.levels[j].merge(source.levels[j]); - } - } - } - - /** Invoked on the last sub-task (after all merges) for getting final result. */ - @Override protected Isolines[] result() throws TransformException { - return flush(isolines); - } - } - } - /** * Generates isolines for the specified levels in the region traversed by the given iterator. * This is the implementation of {@link #generate(RenderedImage, double[][], MathTransform)} * but potentially on a sub-region for parallel "fork-join" execution. */ - private static Isolines[] generate(final PixelIterator iterator, final double[][] levels, - final MathTransform gridToCRS) throws TransformException + static Isolines[] generate(final PixelIterator iterator, final double[][] levels, final MathTransform gridToCRS) + throws TransformException { /* * Prepares a window of size 2×2 pixels over pixel values. Window elements are traversed diff --git a/core/sis-feature/src/main/java/org/apache/sis/internal/processing/isoline/Parallelized.java b/core/sis-feature/src/main/java/org/apache/sis/internal/processing/isoline/Parallelized.java new file mode 100644 index 0000000000..eab25143e5 --- /dev/null +++ b/core/sis-feature/src/main/java/org/apache/sis/internal/processing/isoline/Parallelized.java @@ -0,0 +1,112 @@ +/* + * 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.awt.image.RenderedImage; +import org.opengis.referencing.operation.MathTransform; +import org.opengis.referencing.operation.TransformException; +import org.apache.sis.internal.processing.image.TiledProcess; + + +/** + * Wraps {@code Isolines.generate(…)} calculation in a process for parallel execution. + * The source image is divided in sub-region and the isolines in each sub-region will + * be computed in a different thread. + * + * @author Martin Desruisseaux (Geomatys) + * @version 1.3 + * @since 1.1 + * @module + */ +final class Parallelized extends TiledProcess<Isolines[]> { + /** + * Values for which to compute isolines. An array should be provided for each band. + * If there is more bands than {@code levels.length}, the last array is reused for + * all remaining bands. + * + * @see #cloneAndSort(double[][]) + */ + private final double[][] levels; + + /** + * Transform from image upper left corner (in pixel coordinates) to geometry coordinates. + */ + private final MathTransform gridToCRS; + + /** + * Creates a process for parallel isoline computation. + * + * @param data image providing source values. + * @param levels values for which to compute isolines. + * @param gridToCRS transform from pixel coordinates to geometry coordinates, or {@code null} if none. + */ + Parallelized(final RenderedImage data, final double[][] levels, final MathTransform gridToCRS) { + super(data, 1, 1, Isolines.iterators()); + this.levels = levels; + this.gridToCRS = gridToCRS; + } + + /** + * Invoked by {@link TiledProcess} for creating a sub-task + * doing isoline computation on a sub-region of the image. + */ + @Override + protected Task createSubTask() { + return new Tile(); + } + + /** + * A sub-task doing isoline computation on a sub-region of the image. + * The region is determined by the {@link #iterator}. + */ + private final class Tile extends Task { + /** + * Isolines computed in the sub-region of this sub-task. + */ + private Isolines[] isolines; + + /** + * Creates a new sub-task. + */ + Tile() { + } + + /** + * Invoked in a background thread for performing isoline computation. + */ + @Override + protected void execute() throws TransformException { + isolines = Isolines.generate(iterator, levels, gridToCRS); + } + + /** + * Invoked in a background thread for merging results of two sub-tasks. + */ + @Override + protected void merge(final Task neighbor) throws TransformException { + Isolines.merge(isolines, ((Tile) neighbor).isolines); + } + + /** + * Invoked on the last sub-task (after all merges) for getting final result. + */ + @Override + protected Isolines[] result() throws TransformException { + return Isolines.flush(isolines); + } + } +}