@Test public void testDeriveBoundingBox() throws Exception { final byte[] jsonBytes = Files.readAllBytes(Paths.get("src/test/resources/tile-test/tile_with_only_affine_transforms.json")); final String json = new String(jsonBytes); final TileSpec tileSpec = TileSpec.fromJson(json); final double minX = 1108.0; final double minY = 1957.0; final double maxX = 3774.0; final double maxY = 4265.0; tileSpec.deriveBoundingBox(64, true, false); Assert.assertEquals("incorrect minX", minX, tileSpec.getMinX(), MAX_DOUBLE_DELTA); Assert.assertEquals("incorrect minY", minY, tileSpec.getMinY(), MAX_DOUBLE_DELTA); final double hackedDeltaUntilMPICBGLibIsFixed = 1.0; Assert.assertEquals("incorrect maxX", maxX, tileSpec.getMaxX(), hackedDeltaUntilMPICBGLibIsFixed); Assert.assertEquals("incorrect maxY", maxY, tileSpec.getMaxY(), hackedDeltaUntilMPICBGLibIsFixed); tileSpec.deriveBoundingBox(64, true, true); Assert.assertEquals("incorrect minX", minX, tileSpec.getMinX(), MAX_DOUBLE_DELTA); Assert.assertEquals("incorrect minY", minY, tileSpec.getMinY(), MAX_DOUBLE_DELTA); Assert.assertEquals("incorrect maxX", maxX, tileSpec.getMaxX(), MAX_DOUBLE_DELTA); Assert.assertEquals("incorrect maxY", maxY, tileSpec.getMaxY(), MAX_DOUBLE_DELTA); final int iterations = 100; final long sloppyTime = getDerivationTime(tileSpec, true, iterations); final long meshTime = getDerivationTime(tileSpec, false, iterations); Assert.assertTrue("sloppy derivation is not faster than mesh derivation", (sloppyTime < meshTime)); LOG.info("testDeriveBoundingBox: {} iterations, sloppy time: {}ms, mesh time: {}ms", iterations, sloppyTime, meshTime); }
public void deriveBoundingBox(final double meshCellSize, final boolean force, final boolean sloppy) throws IllegalStateException { if (force || (!isBoundingBoxDefined(meshCellSize))) { if (sloppy) { if (! hasWidthAndHeightDefined()) { throw new IllegalStateException("width and height must be set to create a bounding box"); } final CoordinateTransformList<CoordinateTransform> ctList = getTransformList(); final ArrayList<double[]> borderSamples = new ArrayList<>(); final int numXs = (int)Math.max(2, Math.round(width / meshCellSize)); final double dx = (width - 1) / (numXs - 1); for (double xi =0; xi < numXs; ++xi) { final double x = xi * dx; borderSamples.add(new double[]{x, 0}); borderSamples.add(new double[]{x, height}); } final int numYs = (int)Math.max(2, Math.round(height / meshCellSize)); final double dy = (height - 1) / (numYs - 1); for (double yi =0; yi < numYs; ++yi) { final double y = yi * dy; borderSamples.add(new double[]{0, y}); borderSamples.add(new double[]{width, y}); } double xMin = Double.MAX_VALUE; double yMin = Double.MAX_VALUE; double xMax = -Double.MAX_VALUE; double yMax = -Double.MAX_VALUE; for (final double[] point : borderSamples) { ctList.applyInPlace(point); if ( point[ 0 ] < xMin ) xMin = point[ 0 ]; if ( point[ 0 ] > xMax ) xMax = point[ 0 ]; if ( point[ 1 ] < yMin ) yMin = point[ 1 ]; if ( point[ 1 ] > yMax ) yMax = point[ 1 ]; } setBoundingBox(new Rectangle((int)xMin, (int)yMin, (int)Math.ceil(xMax - xMin), (int)Math.ceil(yMax - yMin)), meshCellSize); } else { final TransformMesh mesh = getTransformMesh(meshCellSize); setBoundingBox(mesh.getBoundingBox(), meshCellSize); } } }
TileSpec implements Serializable { public void deriveBoundingBox(final double meshCellSize, final boolean force, final boolean sloppy) throws IllegalStateException { if (force || (!isBoundingBoxDefined(meshCellSize))) { if (sloppy) { if (! hasWidthAndHeightDefined()) { throw new IllegalStateException("width and height must be set to create a bounding box"); } final CoordinateTransformList<CoordinateTransform> ctList = getTransformList(); final ArrayList<double[]> borderSamples = new ArrayList<>(); final int numXs = (int)Math.max(2, Math.round(width / meshCellSize)); final double dx = (width - 1) / (numXs - 1); for (double xi =0; xi < numXs; ++xi) { final double x = xi * dx; borderSamples.add(new double[]{x, 0}); borderSamples.add(new double[]{x, height}); } final int numYs = (int)Math.max(2, Math.round(height / meshCellSize)); final double dy = (height - 1) / (numYs - 1); for (double yi =0; yi < numYs; ++yi) { final double y = yi * dy; borderSamples.add(new double[]{0, y}); borderSamples.add(new double[]{width, y}); } double xMin = Double.MAX_VALUE; double yMin = Double.MAX_VALUE; double xMax = -Double.MAX_VALUE; double yMax = -Double.MAX_VALUE; for (final double[] point : borderSamples) { ctList.applyInPlace(point); if ( point[ 0 ] < xMin ) xMin = point[ 0 ]; if ( point[ 0 ] > xMax ) xMax = point[ 0 ]; if ( point[ 1 ] < yMin ) yMin = point[ 1 ]; if ( point[ 1 ] > yMax ) yMax = point[ 1 ]; } setBoundingBox(new Rectangle((int)xMin, (int)yMin, (int)Math.ceil(xMax - xMin), (int)Math.ceil(yMax - yMin)), meshCellSize); } else { final TransformMesh mesh = getTransformMesh(meshCellSize); setBoundingBox(mesh.getBoundingBox(), meshCellSize); } } } }
TileSpec implements Serializable { public void deriveBoundingBox(final double meshCellSize, final boolean force, final boolean sloppy) throws IllegalStateException { if (force || (!isBoundingBoxDefined(meshCellSize))) { if (sloppy) { if (! hasWidthAndHeightDefined()) { throw new IllegalStateException("width and height must be set to create a bounding box"); } final CoordinateTransformList<CoordinateTransform> ctList = getTransformList(); final ArrayList<double[]> borderSamples = new ArrayList<>(); final int numXs = (int)Math.max(2, Math.round(width / meshCellSize)); final double dx = (width - 1) / (numXs - 1); for (double xi =0; xi < numXs; ++xi) { final double x = xi * dx; borderSamples.add(new double[]{x, 0}); borderSamples.add(new double[]{x, height}); } final int numYs = (int)Math.max(2, Math.round(height / meshCellSize)); final double dy = (height - 1) / (numYs - 1); for (double yi =0; yi < numYs; ++yi) { final double y = yi * dy; borderSamples.add(new double[]{0, y}); borderSamples.add(new double[]{width, y}); } double xMin = Double.MAX_VALUE; double yMin = Double.MAX_VALUE; double xMax = -Double.MAX_VALUE; double yMax = -Double.MAX_VALUE; for (final double[] point : borderSamples) { ctList.applyInPlace(point); if ( point[ 0 ] < xMin ) xMin = point[ 0 ]; if ( point[ 0 ] > xMax ) xMax = point[ 0 ]; if ( point[ 1 ] < yMin ) yMin = point[ 1 ]; if ( point[ 1 ] > yMax ) yMax = point[ 1 ]; } setBoundingBox(new Rectangle((int)xMin, (int)yMin, (int)Math.ceil(xMax - xMin), (int)Math.ceil(yMax - yMin)), meshCellSize); } else { final TransformMesh mesh = getTransformMesh(meshCellSize); setBoundingBox(mesh.getBoundingBox(), meshCellSize); } } } TileSpec(); }
TileSpec implements Serializable { public void deriveBoundingBox(final double meshCellSize, final boolean force, final boolean sloppy) throws IllegalStateException { if (force || (!isBoundingBoxDefined(meshCellSize))) { if (sloppy) { if (! hasWidthAndHeightDefined()) { throw new IllegalStateException("width and height must be set to create a bounding box"); } final CoordinateTransformList<CoordinateTransform> ctList = getTransformList(); final ArrayList<double[]> borderSamples = new ArrayList<>(); final int numXs = (int)Math.max(2, Math.round(width / meshCellSize)); final double dx = (width - 1) / (numXs - 1); for (double xi =0; xi < numXs; ++xi) { final double x = xi * dx; borderSamples.add(new double[]{x, 0}); borderSamples.add(new double[]{x, height}); } final int numYs = (int)Math.max(2, Math.round(height / meshCellSize)); final double dy = (height - 1) / (numYs - 1); for (double yi =0; yi < numYs; ++yi) { final double y = yi * dy; borderSamples.add(new double[]{0, y}); borderSamples.add(new double[]{width, y}); } double xMin = Double.MAX_VALUE; double yMin = Double.MAX_VALUE; double xMax = -Double.MAX_VALUE; double yMax = -Double.MAX_VALUE; for (final double[] point : borderSamples) { ctList.applyInPlace(point); if ( point[ 0 ] < xMin ) xMin = point[ 0 ]; if ( point[ 0 ] > xMax ) xMax = point[ 0 ]; if ( point[ 1 ] < yMin ) yMin = point[ 1 ]; if ( point[ 1 ] > yMax ) yMax = point[ 1 ]; } setBoundingBox(new Rectangle((int)xMin, (int)yMin, (int)Math.ceil(xMax - xMin), (int)Math.ceil(yMax - yMin)), meshCellSize); } else { final TransformMesh mesh = getTransformMesh(meshCellSize); setBoundingBox(mesh.getBoundingBox(), meshCellSize); } } } TileSpec(); String getTileId(); void setTileId(final String tileId); LayoutData getLayout(); void setLayout(final LayoutData layout); String getGroupId(); @SuppressWarnings("UnusedDeclaration") void setGroupId(final String groupId); Double getZ(); void setZ(final Double z); @JsonIgnore String getSectionId(); Double getMinX(); Double getMinY(); Double getMaxX(); Double getMaxY(); double getMeshCellSize(); boolean isBoundingBoxDefined(final double meshCellSize); void setBoundingBox(final Rectangle box, final double meshCellSize); TileBounds toTileBounds(); int getNumberOfTrianglesCoveringWidth(final double meshCellSize); TransformMesh getTransformMesh(final double meshCellSize); CoordinateTransformMesh getCoordinateTransformMesh(final double meshCellSize); void deriveBoundingBox(final double meshCellSize, final boolean force, final boolean sloppy); void deriveBoundingBox(final double meshCellSize, final boolean force); static Rectangle2D.Double deriveBoundingBox(
            final Iterable<TileSpec> tileSpecs,
            final double meshCellSize,
            final boolean force,
            final Rectangle2D.Double preallocated); double[] getWorldCoordinates(final double x, final double y); double[] getLocalCoordinates(final double x, final double y, final double meshCellSize); boolean hasWidthAndHeightDefined(); int getWidth(); void setWidth(final Double width); int getHeight(); void setHeight(final Double height); @JsonIgnore List<ChannelSpec> getAllChannels(); List<ChannelSpec> getChannels(final Set<String> withNames); String getFirstChannelName(); void convertLegacyToChannel(final String channelName); void addChannel(final ChannelSpec channelSpec); @JsonIgnore Map.Entry<Integer, ImageAndMask> getFirstMipmapEntry(); void setMinAndMaxIntensity(final double minIntensity,
                                      final double maxIntensity,
                                      final String forChannelName); void setMipmapPathBuilder(final MipmapPathBuilder mipmapPathBuilder); boolean hasTransforms(); boolean hasTransformWithLabel(final String label); boolean hasMasks(); ListTransformSpec getTransforms(); @JsonIgnore TransformSpec getLastTransform(); void setTransforms(final ListTransformSpec transforms); void addTransformSpecs(final List<TransformSpec> transformSpecs); void removeLastTransformSpec(); void flattenTransforms(); void flattenAndFilterTransforms(final Boolean excludeAll,
                                           final Set<String> excludeAfterLastLabels,
                                           final Set<String> excludeFirstAndAllAfterLabels); void validateMipmaps(); void validate(); @JsonIgnore CoordinateTransformList<CoordinateTransform> getTransformList(); @Override String toString(); String toJson(); static TileSpec fromJson(final String json); static List<TileSpec> fromJsonArray(final String json); static List<TileSpec> fromJsonArray(final Reader json); }
TileSpec implements Serializable { public void deriveBoundingBox(final double meshCellSize, final boolean force, final boolean sloppy) throws IllegalStateException { if (force || (!isBoundingBoxDefined(meshCellSize))) { if (sloppy) { if (! hasWidthAndHeightDefined()) { throw new IllegalStateException("width and height must be set to create a bounding box"); } final CoordinateTransformList<CoordinateTransform> ctList = getTransformList(); final ArrayList<double[]> borderSamples = new ArrayList<>(); final int numXs = (int)Math.max(2, Math.round(width / meshCellSize)); final double dx = (width - 1) / (numXs - 1); for (double xi =0; xi < numXs; ++xi) { final double x = xi * dx; borderSamples.add(new double[]{x, 0}); borderSamples.add(new double[]{x, height}); } final int numYs = (int)Math.max(2, Math.round(height / meshCellSize)); final double dy = (height - 1) / (numYs - 1); for (double yi =0; yi < numYs; ++yi) { final double y = yi * dy; borderSamples.add(new double[]{0, y}); borderSamples.add(new double[]{width, y}); } double xMin = Double.MAX_VALUE; double yMin = Double.MAX_VALUE; double xMax = -Double.MAX_VALUE; double yMax = -Double.MAX_VALUE; for (final double[] point : borderSamples) { ctList.applyInPlace(point); if ( point[ 0 ] < xMin ) xMin = point[ 0 ]; if ( point[ 0 ] > xMax ) xMax = point[ 0 ]; if ( point[ 1 ] < yMin ) yMin = point[ 1 ]; if ( point[ 1 ] > yMax ) yMax = point[ 1 ]; } setBoundingBox(new Rectangle((int)xMin, (int)yMin, (int)Math.ceil(xMax - xMin), (int)Math.ceil(yMax - yMin)), meshCellSize); } else { final TransformMesh mesh = getTransformMesh(meshCellSize); setBoundingBox(mesh.getBoundingBox(), meshCellSize); } } } TileSpec(); String getTileId(); void setTileId(final String tileId); LayoutData getLayout(); void setLayout(final LayoutData layout); String getGroupId(); @SuppressWarnings("UnusedDeclaration") void setGroupId(final String groupId); Double getZ(); void setZ(final Double z); @JsonIgnore String getSectionId(); Double getMinX(); Double getMinY(); Double getMaxX(); Double getMaxY(); double getMeshCellSize(); boolean isBoundingBoxDefined(final double meshCellSize); void setBoundingBox(final Rectangle box, final double meshCellSize); TileBounds toTileBounds(); int getNumberOfTrianglesCoveringWidth(final double meshCellSize); TransformMesh getTransformMesh(final double meshCellSize); CoordinateTransformMesh getCoordinateTransformMesh(final double meshCellSize); void deriveBoundingBox(final double meshCellSize, final boolean force, final boolean sloppy); void deriveBoundingBox(final double meshCellSize, final boolean force); static Rectangle2D.Double deriveBoundingBox(
            final Iterable<TileSpec> tileSpecs,
            final double meshCellSize,
            final boolean force,
            final Rectangle2D.Double preallocated); double[] getWorldCoordinates(final double x, final double y); double[] getLocalCoordinates(final double x, final double y, final double meshCellSize); boolean hasWidthAndHeightDefined(); int getWidth(); void setWidth(final Double width); int getHeight(); void setHeight(final Double height); @JsonIgnore List<ChannelSpec> getAllChannels(); List<ChannelSpec> getChannels(final Set<String> withNames); String getFirstChannelName(); void convertLegacyToChannel(final String channelName); void addChannel(final ChannelSpec channelSpec); @JsonIgnore Map.Entry<Integer, ImageAndMask> getFirstMipmapEntry(); void setMinAndMaxIntensity(final double minIntensity,
                                      final double maxIntensity,
                                      final String forChannelName); void setMipmapPathBuilder(final MipmapPathBuilder mipmapPathBuilder); boolean hasTransforms(); boolean hasTransformWithLabel(final String label); boolean hasMasks(); ListTransformSpec getTransforms(); @JsonIgnore TransformSpec getLastTransform(); void setTransforms(final ListTransformSpec transforms); void addTransformSpecs(final List<TransformSpec> transformSpecs); void removeLastTransformSpec(); void flattenTransforms(); void flattenAndFilterTransforms(final Boolean excludeAll,
                                           final Set<String> excludeAfterLastLabels,
                                           final Set<String> excludeFirstAndAllAfterLabels); void validateMipmaps(); void validate(); @JsonIgnore CoordinateTransformList<CoordinateTransform> getTransformList(); @Override String toString(); String toJson(); static TileSpec fromJson(final String json); static List<TileSpec> fromJsonArray(final String json); static List<TileSpec> fromJsonArray(final Reader json);  }