当前位置:网站首页>Spatial4j introduction practice

Spatial4j introduction practice

2022-06-24 01:25:00 doaction

One Basic introduction

Spatial4j Is a java The open source library of spatial computing , Support ASL Open source licenses , Support geospatial computing .

Spatial4j There are three main functions :1) Support several drawings based on plane geometry or geospatial ;2) Support distance calculation and shape calculation : Calculate the bounding box 、 area 、 The relationship between figures, etc 3) analysis WKT、GeoJSON ISO spatial description standard format

Spatial4j Some JTS The ability of (JTS It's the most popular java Spatial computing library ), For example, polygons are based on JTS Realized . Compared with the JTS,spatial4j It also supports circle and geospatial computing . use JTS, Polygon approximation is usually used instead of circle calculation , It will cause some error to the result , and Spatial4j Circle supported ; in addition , Geospatial computing is now widely used , use spatial4j It will be more convenient .

Because the official website has only a few brief introductions , This article introduces some practical use cases , It aims to help students in need get started faster .

Two Plane geometry

2.1 pom rely on

If polygons are involved , Need to quote JTS; If you use the GeoJSON Serialize or deserialize , Need to rely on noggit

<dependency>
    <groupId>org.locationtech.spatial4j</groupId>
    <artifactId>spatial4j</artifactId>
    <version>0.8</version>
</dependency>

<dependency>
    <groupId>org.locationtech.jts</groupId>
    <artifactId>jts-core</artifactId>
    <version>1.18.1</version>
</dependency>

<dependency>
    <groupId>org.noggit</groupId>
    <artifactId>noggit</artifactId>
    <version>0.8</version>
</dependency>

2.2 Basic graphics

Next, go directly to the actual combat , Let's start with the example of plane geometry .

The first is point 、 round 、 Definition of simple figures such as rectangles , The area of the figure is calculated 、 Bounding box 、 The relationship between graphs .

picture 1
void testEuclidean() {
    //  Generating planar geometry context
    SpatialContextFactory nonGeoContextFactory = new SpatialContextFactory();
    nonGeoContextFactory.geo = false;
    SpatialContext nonGeoContext = new SpatialContext(nonGeoContextFactory);

    //  Define two points 
    Point pointA = new PointImpl(2,6, nonGeoContext);
    Point pointB = new PointImpl(6,5, nonGeoContext);

    //  Define the circle 
    Circle circleA = new CircleImpl(new PointImpl(6,4, nonGeoContext), 2, nonGeoContext);

    //  Judge the relationship between circle and point 
    System.out.println("circleA relate pointA: " + circleA.relate(pointA));
    System.out.println("circleA relate pointB: " + circleA.relate(pointB));

    //  Calculate the area of a circle and its bounding box 
    System.out.println(String.format("circleA area: %.2f", circleA.getArea(nonGeoContext)));
    Rectangle boundingBoxA = circleA.getBoundingBox();
    System.out.println(String.format("circleA bounding box leftDown(%.2f, %.2f), rightUp:(%.2f, %.2f)",
            boundingBoxA.getMinX(), boundingBoxA.getMinY(), boundingBoxA.getMaxX(), boundingBoxA.getMaxY()));

    //  Define a rectangle , Calculate the relationship between rectangle and circle 
    Rectangle rectangleA = new RectangleImpl(3,5,4,8,nonGeoContext);
    System.out.println("rectangleA relate circleA: " + rectangleA.relate(circleA));
}

 Output results :
circleA relate pointA:DISJOINT
circleA relate pointB:CONTAINS
circleA area:12.57
circleA bounding box leftDown(4.00, 2.00), rightUp:(8.00, 6.00)
rectangleA relate circleA:INTERSECTS

2.3 polygon

spatial4j utilize JTS Polygon computing power .

The following sub examples define a concave polygon and a convex polygon respectively , The area of polygons and the relationship between polygons are calculated .

picture 2
void testPolygon() {
    //  be based on JTS Of context
    JtsSpatialContextFactory jtsSpatialContextFactory = new JtsSpatialContextFactory();
    jtsSpatialContextFactory.geo = false;
    JtsSpatialContext jtsSpatialContext = jtsSpatialContextFactory.newSpatialContext();
    JtsShapeFactory jtsShapeFactory = jtsSpatialContext.getShapeFactory();

    //  Define concave polygons A
    ShapeFactory.PolygonBuilder polygonBuilderA = jtsShapeFactory.polygon();
    Shape polygonA = polygonBuilderA
            .pointXY(1, 1)
            .pointXY(2, 2)
            .pointXY(3, 1)
            .pointXY(5,3)
            .pointXY(3,5)
            .pointXY(2, 4)
            .pointXY(1,5)
            .pointXY(1, 1)
            .build();

    //  Define convex polygons B
    ShapeFactory.PolygonBuilder polygonBuilderB = jtsShapeFactory.polygon();
    Shape polygonB = polygonBuilderB
            .pointXY(3, 3)
            .pointXY(5, 1)
            .pointXY(6, 3)
            .pointXY(5, 5)
            .pointXY(3, 3)
            .build();

    //  Calculate the area of the polygon , The relationship of polygons 
    System.out.println(String.format("polygonA area: %.2f", polygonA.getArea(jtsSpatialContext)));
    System.out.println("polygonA relate polygonB: " + polygonA.relate(polygonB));
}

 Output results :
polygonA area:10.00
polygonA relate polygonB:INTERSECTS

3、 ... and Geographical space

Geographical space is a sphere , A range is a dimension -90,+90, longitude -180,+180, Distance calculation and spatial position relationship , It is very different from plane geometry .Spatial4j Support geospatial computing , Is one of its core selling points .

3.1 tool kit

DistanceUtils Some distance conversion tools are provided , For example, radian is converted to distance , Distance is converted into radians .

void testDistanceUtils() {
    //  Physical distance is converted into radians 
    int equatorLengthKm = 40075;
    double equatorDegree = DistanceUtils.dist2Degrees(equatorLengthKm, DistanceUtils.EARTH_EQUATORIAL_RADIUS_KM);
    System.out.println(String.format("equator length to degree: %.2f", equatorDegree));

    //  The equatorial line , Distance per longitude 
    double distPerDegreeKm = DistanceUtils.degrees2Dist(1, DistanceUtils.EARTH_EQUATORIAL_RADIUS_KM);
    System.out.println(String.format("distance per degree: %.2fkm", distPerDegreeKm));
}

 Output results :
equator length to degree:360.00
distance per degree:111.32km

in addition ,Spatial4j It also provides GeoHASH Codec and other toolkits , Students in need can learn more about

3.2 Distance calculation

The distance calculation of geographical space is different from that of plane geometry . As can be seen from the following example , If we use the algorithm of plane set to calculate the distance of geographical space , There will be errors .

void testGeodesicDistance() {
    SpatialContextFactory nonGeoContextFactory = new SpatialContextFactory();
    nonGeoContextFactory.geo = false;
    SpatialContext nonGeoContext = new SpatialContext(nonGeoContextFactory);

    //  Distance in plane coordinate system 
    Point nonGeoCenter = new PointImpl(0, 0, nonGeoContext);
    CartesianDistCalc cartesianDistCalc = new CartesianDistCalc();
    System.out.println(String.format("cartesian distance: %.2f",
            cartesianDistCalc.distance(nonGeoCenter, 30, 40)));

    //  The distance of geographical space ( radian ), use Haversine Formula calculation 
    Point geoCenter = new PointImpl(0,0, SpatialContext.GEO);
    GeodesicSphereDistCalc geodesicSphereDistCalc = new GeodesicSphereDistCalc.Haversine();
    System.out.println(String.format("geodesic distance: %.2f",
            geodesicSphereDistCalc.distance(geoCenter, 30, 40)));
}

 Output results :
cartesian distance: 50.00
geodesic distance: 48.44

3.3 Relationship between graphs

The relationship of geospatial graphics is also different from the plane coordinate system . In the following example , The circle spans 180 Longitude line , Two circles with the same parameters , Do not intersect in the plane coordinate system , In geographical space, they intersect . If you use the algorithm of the plane coordinate system , Conversion needed .

picture 3
picture 4
void testGeodesicRelate() {
    SpatialContextFactory nonGeoContextFactory = new SpatialContextFactory();
    nonGeoContextFactory.geo = false;
    SpatialContext nonGeoContext = new SpatialContext(nonGeoContextFactory);

    //  A circle in a plane coordinate system 
    Point pointLeft = new PointImpl(-179, 0, nonGeoContext);
    Point pointRight = new PointImpl(179, 0, nonGeoContext);
    Circle circleLeft = new CircleImpl(pointLeft, 10, nonGeoContext);
    Circle circleRight = new CircleImpl(pointRight, 10, nonGeoContext);
    System.out.println("cartesian circleLeft relate circleRight: " + circleLeft.relate(circleRight));

    //  Circle in geospatial 
    Point geoCenterWest = new PointImpl(-179, 0, SpatialContext.GEO);
    Point geoCenterEast = new PointImpl(179, 0, SpatialContext.GEO);
    Circle geoCircleWest = new CircleImpl(geoCenterWest, 10, SpatialContext.GEO);
    Circle geoCircleEast = new CircleImpl(geoCenterEast, 10, SpatialContext.GEO);
    System.out.println("geodesic circleWest relate circleEast: " + geoCircleWest.relate(geoCircleEast));
}

 Output results :
cartesian circleLeft relate circleRight: DISJOINT
geodesic circleWest relate circleEast: INTERSECTS

Four Parsing standard data formats

Spatial4j Support serialization and deserialization of standard spatial description syntax , Here is WKT and GeoJson Example . Be careful GeoJSON Of reader or writer All depend on Noggit Serialization tool .

void testReadStdFormat() {
    JtsSpatialContextFactory jtsSpatialContextFactory = new JtsSpatialContextFactory();
    jtsSpatialContextFactory.geo = false;
    JtsSpatialContext jtsSpatialContext = jtsSpatialContextFactory.newSpatialContext();

    //  Reading and writing WKT Format 
    ShapeReader wktReader = jtsSpatialContext.getFormats().getReader(ShapeIO.WKT);
    ShapeWriter wktWriter = jtsSpatialContext.getFormats().getWriter(ShapeIO.WKT);
    try {
        //  Be careful BUFFER yes Spatial4j be based on WKT Extension definition of 
        Circle circle = (Circle) wktReader.read("BUFFER(POINT(0 0), 1)");
        System.out.println(String.format("read WKT shape area: %.2f", circle.getArea(jtsSpatialContext)));

        Rectangle rectangle = new RectangleImpl(1,10,3,8, jtsSpatialContext);
        System.out.println("WKT format string: " + wktWriter.toString(rectangle));

    } catch (Exception e) {
        //
    }

    //  Reading and writing GeoJson Format 
    ShapeReader geoJsonReader = jtsSpatialContext.getFormats().getReader(ShapeIO.GeoJSON);
    ShapeWriter geoJsonWriter = jtsSpatialContext.getFormats().getWriter(ShapeIO.GeoJSON);
    try {
        //  Pay attention to parsing polygon rely on JTS
        Shape polygon =  geoJsonReader.read("{\"type\":\"Polygon\",\"coordinates\":[[[1,1],[2,2],[3,1],[5,3],[3,5],[2,4],[1,5],[1,1]]]}");
        System.out.println(String.format("read GeoJson polygon area: %.2f", polygon.getArea(jtsSpatialContext)));

        Circle circle = new CircleImpl(new PointImpl(0, 0, jtsSpatialContext), 10, jtsSpatialContext);
        System.out.println("GeoJSON format string: " + geoJsonWriter.toString(circle));

    } catch (Exception e) {
        //
    }
}

 Output results :
read WKT shape area: 3.14
WKT format string: ENVELOPE (1, 10, 8, 3)
read GeoJson polygon area: 10.00
GeoJSON format string: {"type":"Circle","coordinates":[0,0],"radius":10}

5、 ... and quote

1 https://github.com/locationtech/spatial4j

原网站

版权声明
本文为[doaction]所创,转载请带上原文链接,感谢
https://yzsam.com/2021/11/20211118173422804b.html