Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Improvements for the image layer #263

Merged
merged 2 commits into from
Aug 21, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
62 changes: 25 additions & 37 deletions gama.core/src/gama/core/outputs/layers/ImageLayer.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@
********************************************************************************************************/
package gama.core.outputs.layers;

import java.awt.image.BufferedImage;

import gama.core.common.geometry.Envelope3D;
import gama.core.common.geometry.Scaling3D;
import gama.core.common.interfaces.IGraphics;
Expand All @@ -25,7 +23,6 @@
import gama.gaml.operators.Cast;
import gama.gaml.statements.draw.AssetDrawingAttributes;
import gama.gaml.types.GamaFileType;
import gama.gaml.types.IType;

/**
* Written by drogoul Modified on 9 nov. 2009
Expand All @@ -43,7 +40,7 @@ public class ImageLayer extends AbstractLayer {
IImageProvider cachedImageProvider;

/** The provider. */
IExpression provider;
IExpression providerExpression;

/** The is potentially variable. */
boolean isProviderPotentiallyVariable;
Expand All @@ -64,12 +61,12 @@ public class ImageLayer extends AbstractLayer {
*/
public ImageLayer(final IScope scope, final ILayerStatement layer) {
super(layer);
provider = ((ImageLayerStatement) definition).imageExpression;
isImageProvider = isImageProvider();
isProviderPotentiallyVariable = !provider.isContextIndependant();
providerExpression = ((ImageLayerStatement) definition).imageExpression;
isImageProvider = isImageProvider(scope);
isProviderPotentiallyVariable = !providerExpression.isContextIndependant();
if (!isImageProvider) {
if (provider.isConst() || !isProviderPotentiallyVariable) {
Object value = provider.value(scope);
if (providerExpression.isConst() || !isProviderPotentiallyVariable) {
Object value = providerExpression.value(scope);
if (value instanceof String s) {
cachedImageProvider = createFileFromString(scope, s);
} else if (value instanceof IImageProvider p) {
Expand All @@ -81,7 +78,7 @@ public ImageLayer(final IScope scope, final ILayerStatement layer) {
isImageProvider = true;
}
} else if (!isProviderPotentiallyVariable) {
cachedImageProvider = createImageProviderFromFileExpression(scope);
cachedImageProvider = getImageFromProvider(scope, providerExpression.value(scope));
isImageProvider = true;
}

Expand All @@ -92,27 +89,16 @@ public ImageLayer(final IScope scope, final ILayerStatement layer) {
*
* @return true, if is image provider
*/
private boolean isImageProvider() {
IType<?> providerType = provider.getGamlType();
return IImageProvider.class.isAssignableFrom(providerType.toClass());
private boolean isImageProvider(IScope scope) {
var providerClass = providerExpression.value(scope).getClass(); // Needs to be evaluated else what is GamaIntMatrix at runtime is considered GamaMatrix
return IImageProvider.class.isAssignableFrom(providerClass);
}

@Override
protected ILayerData createData() {
return new ImageLayerData(definition);
}

/**
* Creates the file from file expression.
*
* @param scope
* the scope
* @return the gama image file
*/
private IImageProvider createImageProviderFromFileExpression(final IScope scope) {
return verifyFile(scope, provider.value(scope));
}

/**
* Creates the file from string.
*
Expand All @@ -124,22 +110,22 @@ private IImageProvider createImageProviderFromFileExpression(final IScope scope)
*/
private IImageProvider createFileFromString(final IScope scope, final String imageFileName) {
final IGamaFile<?, ?> result = GamaFileType.createFile(scope, imageFileName, false, null);
return verifyFile(scope, result);
return getImageFromProvider(scope, result);
}

/**
* Verify file.
* Verify that the provider and the environment is well setup and use it to generate an image (reuse the previous one in case it should be cached)
*
* @param scope
* the scope
* @param input
* the input
* @return the gama image file
* @return the gama image provider after the image generation
*/
private IImageProvider verifyFile(final IScope scope, final Object input) throws GamaRuntimeFileException, GamaRuntimeException {
private IImageProvider getImageFromProvider(final IScope scope, final Object input) throws GamaRuntimeFileException, GamaRuntimeException {
if (input == cachedImageProvider) return cachedImageProvider;
if (!(input instanceof IImageProvider result))
throw GamaRuntimeException.error("Not a provider of images: " + provider.serializeToGaml(false), scope);
throw GamaRuntimeException.error("Not a provider of images: " + providerExpression.serializeToGaml(false), scope);
try {
result.getImage(scope, !getData().getRefresh());
} catch (final GamaRuntimeFileException ex) {
Expand Down Expand Up @@ -167,16 +153,17 @@ private Envelope3D computeEnvelope(final IScope scope, final IImageProvider file
}

/**
* Builds the image.
* Builds the image and returns the provider
*
* @param scope
* the scope
* @return the gama image file
* @return the gama image provider
*/
protected IImageProvider buildImage(final IScope scope) {
if (!isProviderPotentiallyVariable) return cachedImageProvider;
return isImageProvider ? createImageProviderFromFileExpression(scope)
: createFileFromString(scope, Cast.asString(scope, provider.value(scope)));
return isImageProvider
? getImageFromProvider(scope, providerExpression.value(scope))
: createFileFromString(scope, Cast.asString(scope, providerExpression.value(scope)));
}


Expand All @@ -187,20 +174,21 @@ public void privateDraw(final IGraphicsScope scope, final IGraphics dg) {
final AssetDrawingAttributes attributes = new AssetDrawingAttributes(null, true);
attributes.setUseCache(!getData().getRefresh());

final IImageProvider file = buildImage(scope);
final IImageProvider actualProvider = buildImage(scope);
if (env != null) {
final GamaPoint loc;
if (dg.is2D()) {
loc = new GamaPoint(env.getMinX(), env.getMinY());
} else {
loc = new GamaPoint(env.getWidth() / 2 + env.getMinX(), env.getHeight() / 2 + env.getMinY());
loc = new GamaPoint(env.getMinX() + env.getWidth() / 2, env.getMinY() + env.getHeight() / 2);
}
attributes.setLocation(loc);
attributes.setSize(Scaling3D.of(env.getWidth(), env.getHeight(), 0));
}

if (file != null) {
dg.drawAsset(file, attributes);
if (actualProvider != null) {
// TODO: possibly drawn a second time ? shouldn't we use drawImage and return a BufferedImage from buildImage instead ?
dg.drawAsset(actualProvider, attributes);
}
else {
//TODO: should probably raise some kind of error/warning
Expand Down
6 changes: 3 additions & 3 deletions gama.core/src/gama/gaml/operators/spatial/SpatialPunctal.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,14 +7,14 @@
import org.locationtech.jts.geom.GeometryCollection;
import org.locationtech.jts.operation.distance.DistanceOp;

import gama.annotations.precompiler.IConcept;
import gama.annotations.precompiler.IOperatorCategory;
import gama.annotations.precompiler.Reason;
import gama.annotations.precompiler.GamlAnnotations.doc;
import gama.annotations.precompiler.GamlAnnotations.example;
import gama.annotations.precompiler.GamlAnnotations.no_test;
import gama.annotations.precompiler.GamlAnnotations.operator;
import gama.annotations.precompiler.GamlAnnotations.test;
import gama.annotations.precompiler.IConcept;
import gama.annotations.precompiler.IOperatorCategory;
import gama.annotations.precompiler.Reason;
import gama.core.common.geometry.GeometryUtils;
import gama.core.metamodel.shape.GamaPoint;
import gama.core.metamodel.shape.IShape;
Expand Down