美文网首页开源geotools
geotools学习(九)函数

geotools学习(九)函数

作者: MrSwilder | 来源:发表于2019-10-29 10:03 被阅读0次

    函数教程

    向GeoTools添加函数是扩展该库的非常有用的介绍。这通常用于在样式化时生成值,否则无法使用表达式完成。

    捕捉函数

    1. 下面是一个快速实现从一个点捕捉到一行:
    /*
     *    GeoTools - The Open Source Java GIS Toolkit
     *    http://geotools.org
     *
     *    (C) 2019, Open Source Geospatial Foundation (OSGeo)
     *
     *    This library is free software; you can redistribute it and/or
     *    modify it under the terms of the GNU Lesser General Public
     *    License as published by the Free Software Foundation;
     *    version 2.1 of the License.
     *
     *    This library is distributed in the hope that it will be useful,
     *    but WITHOUT ANY WARRANTY; without even the implied warranty of
     *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     *    Lesser General Public License for more details.
     *
     */
    
    package org.geotools.tutorial.function;
    
    import java.util.List;
    import org.geotools.filter.capability.FunctionNameImpl;
    import org.geotools.util.Converters;
    import org.locationtech.jts.geom.Coordinate;
    import org.locationtech.jts.geom.Geometry;
    import org.locationtech.jts.geom.Point;
    import org.locationtech.jts.linearref.LinearLocation;
    import org.locationtech.jts.linearref.LocationIndexedLine;
    import org.opengis.filter.capability.FunctionName;
    import org.opengis.filter.expression.Expression;
    import org.opengis.filter.expression.ExpressionVisitor;
    import org.opengis.filter.expression.Function;
    import org.opengis.filter.expression.Literal;
    
    /**
     * Quick function that illustrates snapping to a line.
     *
     * @author jody
     */
    public class SnapFunction implements Function {
    
        static FunctionName NAME =
                new FunctionNameImpl(
                        "snap",
                        Point.class,
                        FunctionNameImpl.parameter("point", Point.class),
                        FunctionNameImpl.parameter("line", Geometry.class));
    
        private final List<Expression> parameters;
    
        private final Literal fallback;
    
        public SnapFunction(List<Expression> parameters, Literal fallback) {
            if (parameters == null) {
                throw new NullPointerException("parameters required");
            }
            if (parameters.size() != 2) {
                throw new IllegalArgumentException("snap( point, line) requires two parameters only");
            }
            this.parameters = parameters;
            this.fallback = fallback;
        }
    
        public Object evaluate(Object object) {
            return evaluate(object, Point.class);
        }
    
        public <T> T evaluate(Object object, Class<T> context) {
            Expression pointExpression = parameters.get(0);
            Point point = pointExpression.evaluate(object, Point.class);
    
            Expression lineExpression = parameters.get(1);
            Geometry line = lineExpression.evaluate(object, Geometry.class);
    
            LocationIndexedLine index = new LocationIndexedLine(line);
    
            LinearLocation location = index.project(point.getCoordinate());
    
            Coordinate snap = index.extractPoint(location);
    
            Point pt = point.getFactory().createPoint(snap);
    
            return Converters.convert(pt, context); // convert to requested format
        }
    
        public Object accept(ExpressionVisitor visitor, Object extraData) {
            return visitor.visit(this, extraData);
        }
    
        public String getName() {
            return NAME.getName();
        }
    
        public FunctionName getFunctionName() {
            return NAME;
        }
    
        public List<Expression> getParameters() {
            return parameters;
        }
    
        public Literal getFallbackValue() {
            return fallback;
        }
    }
    
    1. 如果你感兴趣的话,可以在“Snap a Point to a Line”这一单元中学习使用LocationIndexLine的技巧。
    2. 需要注意的一点是,FunctionName的定义用于向新函数的用户描述有效的参数。
      按照惯例,我们将其定义为一个静态的final SnapFunction。但是,这只是一个约定(它将有助于实现下一节)。
    3. 创建实现FunctionFactory的ExampleFunctionFactory
    4. 填写以下代码:
    /*
     *    GeoTools - The Open Source Java GIS Toolkit
     *    http://geotools.org
     *
     *    (C) 2019, Open Source Geospatial Foundation (OSGeo)
     *
     *    This library is free software; you can redistribute it and/or
     *    modify it under the terms of the GNU Lesser General Public
     *    License as published by the Free Software Foundation;
     *    version 2.1 of the License.
     *
     *    This library is distributed in the hope that it will be useful,
     *    but WITHOUT ANY WARRANTY; without even the implied warranty of
     *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     *    Lesser General Public License for more details.
     *
     */
    
    package org.geotools.tutorial.function;
    
    import java.util.ArrayList;
    import java.util.Collections;
    import java.util.List;
    import org.geotools.feature.NameImpl;
    import org.geotools.filter.FunctionFactory;
    import org.opengis.feature.type.Name;
    import org.opengis.filter.capability.FunctionName;
    import org.opengis.filter.expression.Expression;
    import org.opengis.filter.expression.Function;
    import org.opengis.filter.expression.Literal;
    
    public class ExampleFunctionFactory implements FunctionFactory {
    
        public List<FunctionName> getFunctionNames() {
            List<FunctionName> functionList = new ArrayList<>();
            functionList.add(SnapFunction.NAME);
            return Collections.unmodifiableList(functionList);
        }
    
        public Function function(String name, List<Expression> args, Literal fallback) {
            return function(new NameImpl(name), args, fallback);
        }
    
        public Function function(Name name, List<Expression> args, Literal fallback) {
            if (SnapFunction.NAME.getFunctionName().equals(name)) {
                return new SnapFunction(args, fallback);
            }
            return null; // we do not implement that function
        }
    }
    

    6.我们引用静态的final SnapFunction.NAME。
    虽然我们提到这只是一个约定,但是您可以自由地创建一个新的FunctionNameImpl(“snap”、“point”、“line”)作为getFunctionNames()方法的一部分。这样做的好处是避免在用户按名称请求SnapFunction之前加载它。

    1. 我们现在可以通过在META-INF/services/下向jar添加一个文件来注册我们的工厂。
      在你的jar中创建以下文件:
    • src/main/resources/META-INF/services/org.geotools.filter.FunctionFactory
      Maven将src/main/resources的内容收集到jar中,
    1. 填写以下内容(每行一个实现类):
    org.geotools.tutorial.function.ExampleFunctionFactory
    
    1. 那就是SnapFunction现在发布了!
      你可以从你的SLD文件中使用“snap”功能;或者在普通的java程序中。

    扩展

    • 创建一个快速测试用例,以显示上述功能是可用的使用:
    FilterFactory ff = CommonFactoryFinder.getFilterFactory();
    Expression expr = ff.function("snap", ff.property("the_geom"), ff.literal(lines));
    
    • 该函数将非常缓慢写入(当调用捕捉数千点)。
      检查一下你是否可以检测到文字的多重线性化;并在调用函数之间缓存LocationIndexedLine。许多地理工具功能都以这种方式进行了优化。

    • 上面的代码中有相当一部分是“样板代码”,可以使用适当的AbstractFunction类进行简化。
      GeoTools确实提供了两个抽象类,您可以在定义自己的函数时扩展它们。看看FunctionImpl,看看它是否比从头开始更容易。

    • 函数用来处理它们的参数并产生一个答案:

    public Object evaluate(Object feature) {
        Expression geomExpression = parameters.get(0);
        Geometry geom = geomExpression.evaulate(feature, Geometry.class);
    
        return geom.centroid();
    }
    

    当一个函数作为样式的一部分使用时,用户通常希望根据所绘制的特性的属性计算一个值。表达式PropertyName以这种方式用于从特性中提取值并将其传递到函数中进行计算
    重要提示:当我们以一种风格使用您的功能时,我们会尽量提高效率。如果样式在没有引用PropertyName的情况下调用函数,那么它将只被调用一次。假设每次调用该函数时都会产生相同的值,因此对于所有特性都会产生相同的值。通过只调用一次函数(并记住结果),呈现引擎可以执行得更快。
    如果这不是你想要的功能,请实现如下功能:

    public class MagicFunction extends FunctionExpressionImpl implements VolatileFunction {
        Random random;
        public MagicFunction() {
            super("magic");
            random = new Random();
        }
        public int getArgCount() {
            return 0; // no arguments!
        }
        public Object evaluate(Object feature) {
            float r = rand.nextFloat();
            float g = rand.nextFloat();
            float b = rand.nextFloat();
    
            Color color = new Color(r, g, b);
    
            return color;
        }
    }
    

    相关文章

      网友评论

        本文标题:geotools学习(九)函数

        本文链接:https://www.haomeiwen.com/subject/fjrwvctx.html