use of org.geotools.process.function.ProcessFunction in project sldeditor by robward-scisys.
the class SLDEditorBufferedImageLegendGraphicBuilder method buildLegendGraphic.
/**
* Takes a GetLegendGraphicRequest and produces a BufferedImage that then can be used by a
* subclass to encode it to the appropriate output format.
*
* @param request the "parsed" request, where "parsed" means that it's values are already
* validated so this method must not take care of verifying the requested layer exists
* and the like.
*
* @throws ServiceException if there are problems creating a "sample" feature instance for the
* FeatureType <code>request</code> returns as the required layer (which should not
* occur).
*/
public BufferedImage buildLegendGraphic(GetLegendGraphicRequest request) throws ServiceException {
// list of images to be rendered for the layers (more than one if
// a layer group is given)
List<RenderedImage> layersImages = new ArrayList<RenderedImage>();
List<LegendRequest> layers = request.getLegends();
boolean forceLabelsOn = false;
boolean forceLabelsOff = false;
if (request.getLegendOptions().get("forceLabels") instanceof String) {
String forceLabelsOpt = (String) request.getLegendOptions().get("forceLabels");
if (forceLabelsOpt.equalsIgnoreCase("on")) {
forceLabelsOn = true;
} else if (forceLabelsOpt.equalsIgnoreCase("off")) {
forceLabelsOff = true;
}
}
boolean forceTitlesOff = false;
if (request.getLegendOptions().get("forceTitles") instanceof String) {
String forceTitlesOpt = (String) request.getLegendOptions().get("forceTitles");
if (forceTitlesOpt.equalsIgnoreCase("off")) {
forceTitlesOff = true;
}
}
double imageSizeFactor = 1.0;
if (request.getLegendOptions().get("imageSizeFactor") instanceof String) {
String imageSizeFactorOpt = (String) request.getLegendOptions().get("imageSizeFactor");
imageSizeFactor = Double.valueOf(imageSizeFactorOpt);
}
FeatureCountProcessor countProcessor = null;
if (Boolean.TRUE.equals(request.getLegendOption(GetLegendGraphicRequest.COUNT_MATCHED_KEY, Boolean.class))) {
countProcessor = new FeatureCountProcessor(request);
}
for (LegendRequest legend : layers) {
FeatureType layer = legend.getFeatureType();
// style and rule to use for the current layer
Style gt2Style = legend.getStyle();
if (gt2Style == null) {
throw new NullPointerException("request.getStyle()");
}
// get rule corresponding to the layer index
// normalize to null for NO RULE
// was null
String ruleName = legend.getRule();
// width and height, we might have to rescale those in case of DPI usage
int w = request.getWidth();
int h = request.getHeight();
// apply dpi rescale
double dpi = RendererUtilities.getDpi(request.getLegendOptions());
double standardDpi = RendererUtilities.getDpi(Collections.emptyMap());
if (dpi != standardDpi) {
double scaleFactor = dpi / standardDpi;
w = (int) Math.round(w * scaleFactor);
h = (int) Math.round(h * scaleFactor);
DpiRescaleStyleVisitor dpiVisitor = new DpiRescaleStyleVisitor(scaleFactor);
dpiVisitor.visit(gt2Style);
gt2Style = (Style) dpiVisitor.getCopy();
}
// apply UOM rescaling if we have a scale
if (request.getScale() > 0) {
double pixelsPerMeters = RendererUtilities.calculatePixelsPerMeterRatio(request.getScale(), request.getLegendOptions());
UomRescaleStyleVisitor rescaleVisitor = new UomRescaleStyleVisitor(pixelsPerMeters);
rescaleVisitor.visit(gt2Style);
gt2Style = (Style) rescaleVisitor.getCopy();
}
boolean strict = request.isStrict();
final boolean transparent = request.isTransparent();
RenderedImage titleImage = null;
// if we have more than one layer, we put a title on top of each layer legend
if (layers.size() > 1 && !forceTitlesOff) {
titleImage = getLayerTitle(legend, w, h, transparent, request);
}
// Check for rendering transformation
boolean hasVectorTransformation = false;
boolean hasRasterTransformation = false;
List<FeatureTypeStyle> ftsList = gt2Style.featureTypeStyles();
for (int i = 0; i < ftsList.size(); i++) {
FeatureTypeStyle fts = ftsList.get(i);
Expression exp = fts.getTransformation();
if (exp != null) {
ProcessFunction processFunction = (ProcessFunction) exp;
Name processName = processFunction.getProcessName();
Map<String, Parameter<?>> outputs = Processors.getResultInfo(processName, null);
if (outputs.isEmpty()) {
continue;
}
// we assume there is
Parameter<?> output = outputs.values().iterator().next();
// only one output
if (SimpleFeatureCollection.class.isAssignableFrom(output.getType())) {
hasVectorTransformation = true;
break;
} else if (GridCoverage2D.class.isAssignableFrom(output.getType())) {
hasRasterTransformation = true;
break;
}
}
}
final boolean buildRasterLegend = (!strict && layer == null && LegendUtils.checkRasterSymbolizer(gt2Style)) || (LegendUtils.checkGridLayer(layer) && !hasVectorTransformation) || hasRasterTransformation;
// Just checks LegendInfo currently, should check gtStyle
final boolean useProvidedLegend = layer != null && legend.getLayerInfo() != null;
RenderedImage legendImage = null;
if (useProvidedLegend) {
legendImage = getLayerLegend(legend, w, h, transparent, request);
}
if (buildRasterLegend) {
final RasterLayerLegendHelper rasterLegendHelper = new RasterLayerLegendHelper(request, gt2Style, ruleName);
final BufferedImage image = rasterLegendHelper.getLegend();
if (image != null) {
if (titleImage != null) {
layersImages.add(titleImage);
}
layersImages.add(image);
}
} else if (useProvidedLegend && legendImage != null) {
if (titleImage != null) {
layersImages.add(titleImage);
}
layersImages.add(legendImage);
} else {
final Feature sampleFeature;
if (layer == null || hasVectorTransformation) {
sampleFeature = createSampleFeature();
} else {
sampleFeature = createSampleFeature(layer);
}
final FeatureTypeStyle[] ftStyles = gt2Style.featureTypeStyles().toArray(new FeatureTypeStyle[0]);
final double scaleDenominator = request.getScale();
Rule[] applicableRules;
if (ruleName != null) {
Rule rule = LegendUtils.getRule(ftStyles, ruleName);
if (rule == null) {
throw new ServiceException("Specified style does not contains a rule named " + ruleName);
}
applicableRules = new Rule[] { rule };
} else {
applicableRules = LegendUtils.getApplicableRules(ftStyles, scaleDenominator);
}
// do we have to alter the style to do context sensitive feature counts?
if (countProcessor != null && !forceLabelsOff) {
applicableRules = updateRuleTitles(countProcessor, legend, applicableRules);
}
final NumberRange<Double> scaleRange = NumberRange.create(scaleDenominator, scaleDenominator);
final int ruleCount = applicableRules.length;
/**
* A legend graphic is produced for each applicable rule. They're being held here
* until the process is done and then painted on a "stack" like legend.
*/
final List<RenderedImage> legendsStack = new ArrayList<RenderedImage>(ruleCount);
final SLDStyleFactory styleFactory = new SLDStyleFactory();
double minimumSymbolSize = MINIMUM_SYMBOL_SIZE;
// get minSymbolSize from LEGEND_OPTIONS, if defined
if (request.getLegendOptions().get("minSymbolSize") instanceof String) {
String minSymbolSizeOpt = (String) request.getLegendOptions().get("minSymbolSize");
try {
minimumSymbolSize = Double.parseDouble(minSymbolSizeOpt);
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Invalid minSymbolSize value: should be a number");
}
}
// calculate the symbols rescaling factor necessary for them to be
// drawn inside the icon box
double symbolScale = calcSymbolScale(w, h, layer, sampleFeature, applicableRules, minimumSymbolSize);
for (int i = 0; i < ruleCount; i++) {
final RenderedImage image = ImageUtils.createImage(w, h, (IndexColorModel) null, transparent);
final Map<RenderingHints.Key, Object> hintsMap = new HashMap<RenderingHints.Key, Object>();
final Graphics2D graphics = ImageUtils.prepareTransparency(transparent, LegendUtils.getBackgroundColor(request), image, hintsMap);
graphics.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);
Feature sample = getSampleFeatureForRule(layer, sampleFeature, applicableRules[i]);
FilterFactory ff = CommonFactoryFinder.getFilterFactory();
final Symbolizer[] symbolizers = applicableRules[i].getSymbolizers();
final GraphicLegend graphic = applicableRules[i].getLegend();
// If this rule has a legend graphic defined in the SLD, use it
if (graphic != null) {
if (this.samplePoint == null) {
Coordinate coord = new Coordinate(w / 2, h / 2);
try {
this.samplePoint = new LiteShape2(geomFac.createPoint(coord), null, null, false);
} catch (Exception e) {
this.samplePoint = null;
}
}
shapePainter.paint(graphics, this.samplePoint, graphic, scaleDenominator, false);
} else {
for (int sIdx = 0; sIdx < symbolizers.length; sIdx++) {
Symbolizer symbolizer = symbolizers[sIdx];
if (symbolizer instanceof RasterSymbolizer) {
// skip it
} else {
// rescale symbols if needed
if (symbolScale > 1.0 && symbolizer instanceof PointSymbolizer) {
PointSymbolizer pointSymbolizer = (PointSymbolizer) cloneSymbolizer(symbolizer);
if (pointSymbolizer.getGraphic() != null) {
double size = getGraphicSize(sample, pointSymbolizer.getGraphic(), Math.min(w, h) - 4);
pointSymbolizer.getGraphic().setSize(ff.literal(size / symbolScale + minimumSymbolSize));
symbolizer = pointSymbolizer;
}
}
if (!(Math.abs(imageSizeFactor - 1.0) < 0.0001)) {
if (symbolizer instanceof PointSymbolizer) {
PointSymbolizer pointSymbolizer2 = (PointSymbolizer) cloneSymbolizer(symbolizer);
if (pointSymbolizer2.getGraphic() != null) {
double size = getGraphicSize(sample, pointSymbolizer2.getGraphic(), Math.min(w, h) - 4);
pointSymbolizer2.getGraphic().setSize(ff.literal(size * imageSizeFactor + minimumSymbolSize));
symbolizer = pointSymbolizer2;
}
} else if (symbolizer instanceof PolygonSymbolizer) {
PolygonSymbolizer polygonSymbolizer2 = (PolygonSymbolizer) cloneSymbolizer(symbolizer);
if (polygonSymbolizer2.getFill() != null) {
// Fill
double size = 0.0;
if (polygonSymbolizer2.getFill().getGraphicFill() != null) {
size = getGraphicSize(sample, polygonSymbolizer2.getFill().getGraphicFill(), Math.min(w, h) - 4);
polygonSymbolizer2.getFill().getGraphicFill().setSize(ff.literal(size * imageSizeFactor + minimumSymbolSize));
}
}
if (polygonSymbolizer2.getStroke() != null) {
// Stroke
double size = getGraphicSize(sample, polygonSymbolizer2.getStroke().getGraphicFill(), Math.min(w, h) - 4);
polygonSymbolizer2.getStroke().getGraphicFill().setSize(ff.literal(size * imageSizeFactor + minimumSymbolSize));
if (polygonSymbolizer2.getStroke().getGraphicStroke() != null) {
size = getGraphicSize(sample, polygonSymbolizer2.getStroke().getGraphicStroke(), Math.min(w, h) - 4);
polygonSymbolizer2.getStroke().getGraphicStroke().setSize(ff.literal(size * imageSizeFactor + minimumSymbolSize));
}
}
symbolizer = polygonSymbolizer2;
} else if (symbolizer instanceof LineSymbolizer) {
LineSymbolizer lineSymbolizer2 = (LineSymbolizer) cloneSymbolizer(symbolizer);
if (lineSymbolizer2.getStroke() != null) {
// Stroke
double size = 0.0;
if (lineSymbolizer2.getStroke().getGraphicFill() != null) {
size = getGraphicSize(sample, lineSymbolizer2.getStroke().getGraphicFill(), Math.min(w, h) - 4);
lineSymbolizer2.getStroke().getGraphicFill().setSize(ff.literal(size * imageSizeFactor + minimumSymbolSize));
}
if (lineSymbolizer2.getStroke().getGraphicStroke() != null) {
size = getGraphicSize(sample, lineSymbolizer2.getStroke().getGraphicStroke(), Math.min(w, h) - 4);
lineSymbolizer2.getStroke().getGraphicStroke().setSize(ff.literal(size * imageSizeFactor + minimumSymbolSize));
}
if (lineSymbolizer2.getStroke().getWidth() != null) {
size = getWidthSize(sample, lineSymbolizer2.getStroke().getWidth(), 1);
lineSymbolizer2.getStroke().setWidth(ff.literal(size * imageSizeFactor));
}
}
symbolizer = lineSymbolizer2;
}
}
}
Style2D style2d = styleFactory.createStyle(sample, symbolizer, scaleRange);
LiteShape2 shape = getSampleShape(symbolizer, w, h);
if (style2d != null) {
shapePainter.paint(graphics, shape, style2d, scaleDenominator);
}
}
}
if (image != null && titleImage != null) {
layersImages.add(titleImage);
titleImage = null;
}
legendsStack.add(image);
graphics.dispose();
}
int labelMargin = 3;
if (!StringUtils.isEmpty(request.getLegendOptions().get("labelMargin"))) {
labelMargin = Integer.parseInt(request.getLegendOptions().get("labelMargin").toString());
}
LegendMerger.MergeOptions options = LegendMerger.MergeOptions.createFromRequest(legendsStack, 0, 0, 0, labelMargin, request, forceLabelsOn, forceLabelsOff, forceTitlesOff);
if (ruleCount > 0) {
BufferedImage image = LegendMerger.mergeLegends(applicableRules, request, options);
if (image != null) {
layersImages.add(image);
}
}
}
}
// all legend graphics are merged if we have a layer group
BufferedImage finalLegend = mergeGroups(layersImages, null, request, forceLabelsOn, forceLabelsOff, forceTitlesOff);
if (finalLegend == null) {
throw new IllegalArgumentException("no legend passed");
}
return finalLegend;
}
use of org.geotools.process.function.ProcessFunction in project sldeditor by robward-scisys.
the class FieldConfigBase method populate.
/**
* Populate.
*
* @param expression the expression
*/
public void populate(Expression expression) {
if (attributeSelectionPanel != null) {
attributeSelectionPanel.populateAttributeComboxBox(expression);
}
if (expression == null) {
expressionType = ExpressionTypeEnum.E_VALUE;
revertToDefaultValue();
valueUpdated();
} else {
if (expression instanceof LiteralExpressionImpl) {
LiteralExpressionImpl lExpression = (LiteralExpressionImpl) expression;
Object objValue = lExpression.getValue();
if (objValue instanceof AttributeExpressionImpl) {
expressionType = ExpressionTypeEnum.E_ATTRIBUTE;
if (attributeSelectionPanel != null) {
attributeSelectionPanel.setAttribute((AttributeExpressionImpl) objValue);
}
setCachedExpression((AttributeExpressionImpl) objValue);
} else {
expressionType = ExpressionTypeEnum.E_VALUE;
populateExpression(objValue);
valueUpdated();
}
} else if (expression instanceof ConstantExpression) {
ConstantExpression cExpression = (ConstantExpression) expression;
Object objValue = cExpression.getValue();
expressionType = ExpressionTypeEnum.E_VALUE;
populateExpression(objValue);
valueUpdated();
} else if (expression instanceof NilExpression) {
Object objValue = null;
expressionType = ExpressionTypeEnum.E_VALUE;
populateExpression(objValue);
valueUpdated();
} else if (expression instanceof ProcessFunction) {
ProcessFunction processExpression = (ProcessFunction) expression;
Object objValue = processExpression;
expressionType = ExpressionTypeEnum.E_VALUE;
populateExpression(objValue);
valueUpdated();
} else if (expression instanceof AttributeExpressionImpl) {
expressionType = ExpressionTypeEnum.E_ATTRIBUTE;
if (attributeSelectionPanel != null) {
attributeSelectionPanel.setAttribute(expression);
} else {
populateExpression(expression);
}
setCachedExpression(expression);
} else if (expression instanceof FunctionExpressionImpl) {
expressionType = ExpressionTypeEnum.E_EXPRESSION;
if (attributeSelectionPanel != null) {
attributeSelectionPanel.populate(expression);
}
setCachedExpression(expression);
} else if (expression instanceof BinaryExpression) {
expressionType = ExpressionTypeEnum.E_EXPRESSION;
if (attributeSelectionPanel != null) {
attributeSelectionPanel.populate(expression);
}
setCachedExpression(expression);
} else {
expressionType = ExpressionTypeEnum.E_EXPRESSION;
}
}
setValueFieldState();
}
use of org.geotools.process.function.ProcessFunction in project sldeditor by robward-scisys.
the class FunctionTableModel method getExpression.
/**
* Gets the expression.
*
* @param factory the factory
* @return the expression
*/
public ProcessFunction getExpression(FunctionFactory factory) {
List<Expression> overallParameterList = new ArrayList<Expression>();
for (ProcessFunctionParameterValue value : valueList) {
List<Expression> parameterList = new ArrayList<Expression>();
parameterList.add(ff.literal(value.name));
boolean setValue = true;
if (value.optional) {
setValue = value.included;
}
if (setValue) {
if (value.objectValue != null) {
Expression expression = value.objectValue.getExpression();
if (expression != null) {
parameterList.add(expression);
}
}
}
if (setValue) {
Function function = factory.function(PARAMETER, parameterList, null);
overallParameterList.add(function);
}
}
if (this.selectedFunction.getFunctionName() == null) {
return null;
}
Function processFunction = factory.function(this.selectedFunction.getFunctionName(), overallParameterList, null);
return (ProcessFunction) processFunction;
}
use of org.geotools.process.function.ProcessFunction in project sldeditor by robward-scisys.
the class BuiltInProcessFunctionTest method testExtractParametersProcessFunction.
/**
* Test method for
* {@link com.sldeditor.rendertransformation.BuiltInProcessFunction#extractParameters(org.opengis.filter.capability.FunctionName, org.geotools.process.function.ProcessFunction)}.
*/
@Test
public void testExtractParametersProcessFunction() {
BuiltInProcessFunction obj = new BuiltInProcessFunction();
String testData = "<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>" + "<StyledLayerDescriptor version=\"1.0.0\" xsi:schemaLocation=\"http://www.opengis.net/sld StyledLayerDescriptor.xsd\" xmlns=\"http://www.opengis.net/sld\" xmlns:ogc=\"http://www.opengis.net/ogc\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">" + "<ogc:Function name=\"vec:PointStacker\">" + "<ogc:Function name=\"parameter\">" + " <ogc:Literal>data</ogc:Literal>" + "</ogc:Function>" + "<ogc:Function name=\"parameter\">" + " <ogc:Literal>cellSize</ogc:Literal>" + " <ogc:Literal>30</ogc:Literal>" + "</ogc:Function>" + "<ogc:Function name=\"parameter\">" + " <ogc:Literal>outputBBOX</ogc:Literal>" + " <ogc:Function name=\"env\">" + " <ogc:Literal>wms_bbox</ogc:Literal>" + " </ogc:Function>" + "</ogc:Function>" + "<ogc:Function name=\"parameter\">" + " <ogc:Literal>outputWidth</ogc:Literal>" + " <ogc:Function name=\"env\">" + " <ogc:Literal>wms_width</ogc:Literal>" + " </ogc:Function>" + "</ogc:Function>" + "<ogc:Function name=\"parameter\">" + " <ogc:Literal>outputHeight</ogc:Literal>" + " <ogc:Function name=\"env\">" + " <ogc:Literal>wms_height</ogc:Literal>" + " </ogc:Function>" + " </ogc:Function>" + "</ogc:Function>" + "</StyledLayerDescriptor>";
DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
DocumentBuilder builder;
ProcessFunction tx = null;
try {
builder = factory.newDocumentBuilder();
InputSource is = new InputSource(new StringReader(testData));
Document doc = builder.parse(is);
ExpressionDOMParser parser = new ExpressionDOMParser(CommonFactoryFinder.getFilterFactory2(null));
tx = (ProcessFunction) parser.expression(doc.getDocumentElement().getFirstChild());
} catch (ParserConfigurationException e) {
e.printStackTrace();
} catch (SAXException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
List<ProcessFunctionParameterValue> valueList = obj.extractParameters(null, tx);
assertTrue(valueList.isEmpty());
ProcessFunctionFactory processFunctionFactory = new ProcessFunctionFactory();
for (FunctionName functionName : processFunctionFactory.getFunctionNames()) {
if (functionName.getName().compareTo("PointStacker") == 0) {
valueList = obj.extractParameters(functionName, tx);
assertEquals(functionName.getArguments().size(), valueList.size());
}
}
}
Aggregations