use of org.geotoolkit.display.PortrayalException in project geotoolkit by Geomatys.
the class RenderingRoutines method optimizeBBox.
public static Envelope optimizeBBox(RenderingContext2D renderingContext, FeatureSet featureSet, double symbolsMargin) throws PortrayalException {
Envelope bbox = renderingContext.getCanvasObjectiveBounds2D();
final CoordinateReferenceSystem bboxCRS = bbox.getCoordinateReferenceSystem();
final CanvasMonitor monitor = renderingContext.getMonitor();
final CoordinateReferenceSystem layerCRS;
try {
layerCRS = FeatureExt.getCRS(featureSet.getType());
} catch (DataStoreException ex) {
throw new PortrayalException(ex.getMessage(), ex);
}
// expand the search area by the maximum symbol size
if (symbolsMargin > 0) {
final GeneralEnvelope env = new GeneralEnvelope(bbox);
env.setRange(0, env.getMinimum(0) - symbolsMargin, env.getMaximum(0) + symbolsMargin);
env.setRange(1, env.getMinimum(1) - symbolsMargin, env.getMaximum(1) + symbolsMargin);
bbox = env;
}
// or if the crs is defined only on the feature geometry
if (layerCRS != null && !Utilities.equalsIgnoreMetadata(layerCRS, bboxCRS)) {
// BBox and layer bounds have different CRS. reproject bbox bounds
Envelope env;
try {
env = Envelopes.transform(bbox, layerCRS);
if (GeneralEnvelope.castOrCopy(env).isEmpty()) {
// possible NaN values or out of crs validity area
GeneralEnvelope benv = GeneralEnvelope.castOrCopy(bbox);
benv.normalize();
env = Envelopes.transform(benv, layerCRS);
}
} catch (TransformException ex) {
// TODO is fixed in geotidy, the result envelope will have infinte values where needed
// TODO should do something about this, since canvas bounds may be over the crs bounds
monitor.exceptionOccured(ex, Level.WARNING);
env = new Envelope2D();
} catch (IllegalArgumentException ex) {
// looks like the coordinate of the bbox are outside of the crs valide area.
// some crs raise this error, other not.
// if so we should reduce our bbox to the valide extent of the crs.
monitor.exceptionOccured(ex, Level.WARNING);
final GeographicBoundingBox gbox = CRS.getGeographicBoundingBox(layerCRS);
if (gbox == null) {
env = new GeneralEnvelope(layerCRS);
} else {
env = new GeneralEnvelope(gbox);
}
} catch (Exception ex) {
// we should not catch this but we must not block the canvas
monitor.exceptionOccured(ex, Level.WARNING);
return null;
}
// TODO looks like the envelope after transform operation doesnt have always exactly the same CRS.
// fix CRS classes method and remove the two next lines.
env = new GeneralEnvelope(env);
((GeneralEnvelope) env).setCoordinateReferenceSystem(layerCRS);
bbox = env;
}
return bbox;
}
use of org.geotoolkit.display.PortrayalException in project geotoolkit by Geomatys.
the class TextSymbolizerRenderer method presentations.
@Override
public Stream<Presentation> presentations(MapLayer layer, Feature feature) {
// test if the symbol is visible on this feature
if (!symbol.isVisible(feature))
return Stream.empty();
// we adjust coefficient for rendering ------------------------------
final float coeff;
if (dispGeom) {
// symbol is in display unit
coeff = 1;
} else {
// we have a special unit we must adjust the coefficient. We adapt it to the current region of interest,
// by computin scale difference between objective and display
final AffineTransform inverse = renderingContext.getObjectiveToDisplay();
coeff = (float) (this.coeff * Math.abs(AffineTransforms2D.getScale(inverse)));
}
// start to extract label parameters---------------------------------
String label = symbol.getLabel(feature);
// nothing to paint
if (label == null)
return Stream.empty();
label = label.trim();
// nothing to paint
if (label.isEmpty())
return Stream.empty();
final CachedHalo halo = symbol.getHalo();
final CachedLabelPlacement placement = symbol.getPlacement();
// extract halo parameters
final float haloWidth;
final Paint haloPaint;
if (halo != null) {
haloWidth = halo.getWidth(feature);
haloPaint = halo.getJ2DPaint(feature, 0, 0, hints);
} else {
haloWidth = 0;
haloPaint = Color.WHITE;
}
/* Extract text parameters.
* Note:
* There's an ambiguity in SE encoding. Section 11 defines that any size, including font size, should use
* defined UOMs. However, text symbology section 11.4.3 states that font size unit is always in pixels.
* For now, we force no coefficient, to match both:
* - Most specific information (11.4.3)
* - Most common use-case. Unit of measurement is useful mostly for displacements, to ensure text does not
* overlap geometry at given zoom levels. However, for texts, pixel values is often preferred, to ensure
* lisibility on screen.
*
* TODO: A better way might be to allow expressions suffixed with "px", as defined in SE section 11, last phrase.
* For now, however, we do not code this solution, because it should be applied on any size in style,
* and would require a big rework. Sizes should provide Measures instead of numeric values to check if measure
* has a local uom (expressed as a suffix), or none, in case the context defined uom should be used.
*/
final Paint fontPaint = symbol.getFontPaint(feature, 0, 0, 1, hints);
final Font j2dFont = symbol.getJ2dFont(feature, 1);
// symbolizer doesnt match the featuretype, no geometry found with this name.
final ProjectedGeometry projectedGeometry = new ProjectedGeometry(renderingContext);
projectedGeometry.setDataGeometry(GO2Utilities.getGeometry(feature, symbol.getSource().getGeometry()), null);
if (placement instanceof CachedPointPlacement) {
final CachedPointPlacement pp = (CachedPointPlacement) placement;
final float[] anchor = pp.getAnchor(feature, null);
final float[] disp = pp.getDisplacement(feature, null);
final float rotation = pp.getRotation(feature);
final LabelDescriptor descriptor = new DefaultPointLabelDescriptor(label, j2dFont, fontPaint, haloWidth, haloPaint, anchor[0], anchor[1], // SE 11.3.2: displacement is expressed in defined unit of measurement
disp[0] * coeff, disp[1] * coeff, rotation, renderingContext.getDisplayCRS(), projectedGeometry);
final TextPresentation tp = new TextPresentation(layer, layer.getData(), feature);
tp.forGrid(renderingContext);
tp.labelDesc = descriptor;
return Stream.of(tp);
} else if (placement instanceof CachedLinePlacement) {
final CachedLinePlacement lp = (CachedLinePlacement) placement;
final LabelDescriptor descriptor = new DefaultLinearLabelDescriptor(label, j2dFont, fontPaint, haloWidth, haloPaint, // SE section 11: Gap and initial gap are defined using UOM.
lp.getGap(feature) * coeff, lp.getInitialGap(feature) * coeff, // SE 11.1.4 and 11.4.4: Perpendicular offset is in defined unit of measurement
lp.getOffset(feature) * coeff, lp.isRepeated(), lp.isAligned(), lp.isGeneralizeLine(), projectedGeometry);
final TextPresentation tp = new TextPresentation(layer, layer.getData(), feature);
tp.forGrid(renderingContext);
tp.labelDesc = descriptor;
return Stream.of(tp);
} else {
ExceptionPresentation ep = new ExceptionPresentation(new PortrayalException("Text symbolizer has no label placement, this should not be possible."));
ep.setLayer(layer);
ep.setResource(layer.getData());
return Stream.of(ep);
}
}
use of org.geotoolkit.display.PortrayalException in project geotoolkit by Geomatys.
the class AbstractSymbolizerRenderer method presentations.
/**
* Obtain the presentation for given resource.Default implementation loops on each feature if resource is a FeatureSet.
* If resource is an Aggregate, loops on each components and concatenate streams.
*
* @param layer
* @param resource
* @return Stream never null, can be empty
* @throws BackingStoreException in stream iteration
*/
@Override
public Stream<Presentation> presentations(MapLayer layer, Resource resource) {
if (resource instanceof FeatureSet) {
/*
Optimise case using envelopes filter and limited propery names.
*/
final FeatureSet fs = (FeatureSet) resource;
Set<String> names;
if (GO2Utilities.mustPreserveAllProperties(getRenderingContext())) {
names = null;
} else {
// extract the used names
final org.geotoolkit.style.visitor.ListingPropertyVisitor visitor = new org.geotoolkit.style.visitor.ListingPropertyVisitor();
names = new HashSet<>();
symbol.getSource().accept(visitor, names);
if (names.contains("*")) {
// we need all properties
names = null;
}
}
// calculate max symbol size, to expand search envelope.
double symbolsMargin = symbol.getMargin(null, renderingContext);
if (Double.isNaN(symbolsMargin) || Double.isInfinite(symbolsMargin)) {
// symbol margin can not be pre calculated, expect a max of 300pixels
symbolsMargin = 300f;
}
if (symbolsMargin > 0) {
final double scale = AffineTransforms2D.getScale(renderingContext.getDisplayToObjective());
symbolsMargin = scale * symbolsMargin;
}
// optimize
final Rule rule = GO2Utilities.STYLE_FACTORY.rule(symbol.getSource());
final Query query;
try {
query = RenderingRoutines.prepareQuery(getRenderingContext(), fs, layer, names, Arrays.asList(rule), symbolsMargin);
} catch (PortrayalException ex) {
ExceptionPresentation ep = new ExceptionPresentation(ex);
ep.setLayer(layer);
ep.setResource(resource);
return Stream.of(ep);
}
final AtomicInteger inc = new AtomicInteger();
final UndefinedCRSException[] firstException = new UndefinedCRSException[1];
try {
return fs.subset(query).features(false).onClose(new Runnable() {
@Override
public void run() {
final int nb = inc.get();
if (nb > 0) {
LOGGER.log(Level.INFO, "Several (" + nb + ") undefined crs geometries have been detected on layer : " + layer.getIdentifier() + "/" + layer.getTitle() + " : " + firstException[0].getMessage(), firstException[0]);
}
}
}).flatMap(new Function<Feature, Stream<Presentation>>() {
@Override
public Stream<Presentation> apply(Feature t) {
try {
return presentations(layer, t);
} catch (UndefinedCRSException ex) {
inc.incrementAndGet();
firstException[0] = ex;
return Stream.empty();
}
}
});
} catch (DataStoreException ex) {
ExceptionPresentation ep = new ExceptionPresentation(ex);
ep.setLayer(layer);
ep.setResource(resource);
return Stream.of(ep);
}
}
return SymbolizerRenderer.super.presentations(layer, resource);
}
use of org.geotoolkit.display.PortrayalException in project geotoolkit by Geomatys.
the class MapFieldRenderer method createValue.
@Override
public Object createValue(final JRField field, final Feature feature) {
final String name = field.getName();
final MapDef map = (MapDef) feature.getPropertyValue(name);
if (map != null && map.getDelegate() == null) {
// only create delegate if not yet assigned
final CanvasDef canvasDef = map.getCanvasDef();
final SceneDef sceneDef = map.getSceneDef();
// create the canvas
final CanvasRenderer renderable = new CanvasRenderer(sceneDef.getContext());
try {
DefaultPortrayalService.prepareCanvas(renderable, canvasDef, sceneDef);
} catch (PortrayalException ex) {
Logger.getLogger("org.geotoolkit.report.graphic.map").log(Level.WARNING, ex.getLocalizedMessage(), ex);
}
map.setDelegate(renderable);
}
if (map != null && map.getDelegate() == null) {
map.setDelegate(EmptyRenderable.INSTANCE);
}
return map;
}
use of org.geotoolkit.display.PortrayalException in project geotoolkit by Geomatys.
the class DefaultPortrayalService method prepareCanvas.
public static void prepareCanvas(final J2DCanvas canvas, final CanvasDef canvasDef, final SceneDef sceneDef) throws PortrayalException {
final ContextContainer2D renderer = new ContextContainer2D(canvas);
canvas.setContainer(renderer);
final Color bgColor = canvasDef.getBackground();
if (bgColor != null) {
canvas.setBackgroundPainter(new SolidColorPainter(bgColor));
}
final CanvasMonitor monitor = canvasDef.getMonitor();
if (monitor != null) {
canvas.setMonitor(monitor);
}
final Hints hints = sceneDef.getHints();
if (hints != null) {
for (Entry<?, ?> entry : hints.entrySet()) {
canvas.setRenderingHint((Key) entry.getKey(), entry.getValue());
}
}
final MapLayers context = sceneDef.getContext();
renderer.setContext(context);
GridGeometry gridGeometry = canvasDef.getGridGeometry();
if (gridGeometry != null) {
try {
canvas.setGridGeometry(gridGeometry);
} catch (FactoryException ex) {
throw new PortrayalException("Could not set objective crs", ex);
}
} else {
final Envelope contextEnv = canvasDef.getEnvelope();
final CoordinateReferenceSystem crs = contextEnv.getCoordinateReferenceSystem();
try {
canvas.setObjectiveCRS(crs);
} catch (TransformException | FactoryException ex) {
throw new PortrayalException("Could not set objective crs", ex);
}
// we specifically say to not repect X/Y proportions
canvas.setAxisProportions(!canvasDef.isStretchImage());
// setVisibleArea -> setAxisRange -> setRange.
if (contextEnv != null) {
try {
canvas.setGridGeometry(canvasDef.getOrCreateGridGeometry());
} catch (Exception e) {
// Rollback to previous behavior
try {
canvas.setVisibleArea(contextEnv);
if (canvasDef.getAzimuth() != 0) {
canvas.rotate(-Math.toRadians(canvasDef.getAzimuth()));
}
} catch (NoninvertibleTransformException | TransformException ex) {
ex.addSuppressed(e);
throw new PortrayalException(ex);
}
}
}
}
// paints all extensions
final List<PortrayalExtension> extensions = sceneDef.extensions();
if (extensions != null) {
for (final PortrayalExtension extension : extensions) {
if (extension != null)
extension.completeCanvas(canvas);
}
}
}
Aggregations