You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在Java/Spring/PostGIS中计算Polygon的平方英尺等面积

多边形面积单位转换方案选择及代码优化建议

问题背景

需要将Polygon的面积转换为平方英尺、公顷或英亩等面积单位,已引入以下依赖:

<dependency>
        <groupId>org.hibernate.orm</groupId>
    <artifactId>hibernate-spatial</artifactId>
    <version>${hibernate.version}</version>
</dependency>

<dependency>
    <groupId>org.locationtech.jts</groupId>
    <artifactId>jts-core</artifactId>
    <version>${jts.version}</version>
</dependency>

现有代码实现

已编写部分代码,包含以下组件:

Field实体类

@Entity(name = "field")
@Table(name = "field")
public class Field {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(updatable = false, nullable = false, unique = true)
    private Long id;

    @Column(name = "name", nullable = false)
    private String name;

    @Column(name = "area", columnDefinition = "geometry(Polygon, 4326)", nullable = false)
    private Polygon area;

    @Column(name = "center", columnDefinition = "geometry(Point, 4326)")
    private Point center;

    @Column(name = "size")
    private Double size;

    @ManyToOne
    @JoinColumn(name = "fk_farm_id")
    private Farm farm;
}

FieldRepository

@Repository
public interface FieldRepository extends JpaRepository<Field, Long> {
}

FieldService接口

public interface FieldService {

    CreateFieldResponseDto createNewField(UUID publicFarmId, FieldDto fieldDto);
}

FieldService实现类

@Override
public CreateFieldResponseDto createNewField(UUID publicFarmId, FieldDto fieldDto) {

     Farm farm = farmRepository.findByPublicId(publicFarmId)
                .orElseThrow(() -> new FarmNotFoundException("Farm not found"));

    Field newField = new Field();

    newField.setName(fieldDto.getName());
    newField.setArea(convertToPolygon(fieldDto.getCoordinates()));
    newField.setCenter(calculateCenter(newField.getArea()));
//    newField.setSize(calculateFieldSize(newField.getArea()));
    newField.setFarm(farm);

    fieldRepository.save(newField);

    return fieldMapper.INSTANCE.toCreateFieldResponseDto(newField);
}

//--------------------------------------------|
// HELPER METHODS FOR CREATING A NEW FIELD... |
//--------------------------------------------|

private Polygon convertToPolygon(List<List<List<Double>>> coordinates) {

    GeometryFactory geometryFactory = new GeometryFactory();

    LinearRing shell = geometryFactory.createLinearRing(
            convertToCoordinateArray(coordinates.get(0))
    );

    LinearRing[] holes = new LinearRing[coordinates.size() - 1];

    for (int i = 1; i < coordinates.size(); i++) {
        holes[i - 1] = geometryFactory.createLinearRing(
                convertToCoordinateArray(coordinates.get(i))
        );
    }

    return geometryFactory.createPolygon(shell, holes);
}

private Coordinate[] convertToCoordinateArray(List<List<Double>> coordinatesList) {

    Coordinate[] coordinates = new Coordinate[coordinatesList.size()];

    for (int i = 0; i < coordinatesList.size(); i++) {
        List<Double> point = coordinatesList.get(i);
        coordinates[i] = new Coordinate(point.get(0), point.get(1));
    }

    return coordinates;
}

private Point calculateCenter(Polygon polygon) {

    GeometryFactory geometryFactory = new GeometryFactory();

    return geometryFactory.createPoint(polygon.getCentroid().getCoordinate());
}

控制器类

@PostMapping("/{publicFarmId}/fields")
public ResponseEntity<Object> createField(
    @PathVariable UUID publicFarmId, @RequestBody FieldDto fieldDTO
) {
    CreateFieldResponseDto createdField = fieldService.createNewField(publicFarmId, fieldDTO);

    return ResponseHandler.generateResponse(
            HttpStatus.CREATED,
            "success",
            "Field created successfully.",
            new LinkedHashMap<>() {{
                put("name", createdField.name());
                put("coordinates", createdField.coordinates());
                put("center", createdField.center());
                put("size", createdField.size());
                put("unitOfMeasurement", "metric"); // CODE THIS LATER !!!
            }}
    );
}

FieldDto请求类

public class FieldDto {

    private String name;
    private List<List<List<Double>>> coordinates;
}

疑问与需求

不确定最优解决方案:是在Java代码中计算Polygon面积,还是用PostGIS的SQL方法(如存入后执行UPDATE查询)?也不清楚两种方案的性能差异,同时希望得到现有代码的改进建议。


内容的提问来源于stack exchange,提问作者Juhani

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 17:05:22