Java解析dxf并利用openlayer渲染图层矢量切图

数据库用的pg

pom引用(我自己是搭建的maven私服):

   <dependency>
        <groupId>org.kabeja</groupId>
        <artifactId>kabeja</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </dependency>
    <dependency>
        <groupId>org.kabeja</groupId>
        <artifactId>kabeja-svg</artifactId>
        <version>1.0.0-SNAPSHOT</version>
    </dependency>

链接:https://pan.baidu.com/s/1LSk9IKS1w0uL5SmUU3FCew
提取码:0b1d
–kabeja离线包下载地址

解析dxf如下:


```java
@Override
	public Object uploadDxf(MultipartFile file) {
		try {
			Parser dxfParser = ParserBuilder.createDefaultParser();
			dxfParser.parse(file.getInputStream(), "UTF-8");
			DXFDocument doc = dxfParser.getDocument();

			Bounds bounds = doc.getBounds();
			VectorBox box = new VectorBox();
			//包围盒必须是正方形否则进行4096切分是会拉伸变形
			Double subX = bounds.getMaximumX()-bounds.getMinimumX();
			Double subY = bounds.getMaximumY()-bounds.getMinimumY();
			if(subY>subX){
				Double minX = (bounds.getMinimumX()+subX/2)-subY/2;
				Double maxX = (bounds.getMaximumX()-subX/2)+subY/2;
				box.setxMin(minX);
				box.setyMin(bounds.getMinimumY());
				box.setxMax(maxX);
				box.setyMax(bounds.getMaximumY());
			}else{
				Double minY = (bounds.getMinimumY()+subY/2)-subX/2;
				Double maxY = (bounds.getMaximumY()-subY/2)+subX/2;
				box.setxMin(bounds.getMinimumX());
				box.setyMin(minY);
				box.setxMax(bounds.getMaximumX());
				box.setyMax(maxY);
			}
			vectorBoxService.save(box);
			Iterator<DXFLayer> dxfLayerIterator =  doc.getDXFLayerIterator();
			for (Iterator<DXFLayer> it = dxfLayerIterator; it.hasNext(); ) {
				DXFLayer dxfLayer = it.next();
				VectorLayer vectorLayer = new VectorLayer();
				vectorLayer.setName(dxfLayer.getName());
				vectorLayerService.save(vectorLayer);
			}
			List<VectorLayer> vectorLayers = vectorLayerService.list();

			Map<String,VectorLayer> vectorLayerMap = vectorLayers.stream().collect(Collectors.toMap(VectorLayer::getName, e -> e));
			List<DXFEntity> dxfEntities = DXFUtil.getDXFEntities(doc);
			List<VectorTile> vectorTiles = new ArrayList<>();
			for (DXFEntity d : dxfEntities) {
				if (d instanceof DXFLine) {
				    //直线
					DXFLine line = (DXFLine) d;
					VectorTile vectorTile = new VectorTile();
					vectorTile.setName(line.getLayerName());
					String coordinateWkt = "LINESTRING(" + line.getStartPoint().getX() + " " + line.getStartPoint().getY() + "," +
							line.getEndPoint().getX() + " " + line.getEndPoint().getY() +
							")";
					vectorTile.setGeom(coordinateWkt);
					vectorTile.setColor(DXFUtil.getColor(line.getColor()));
					vectorTile.setType("LINESTRING");
					vectorTile.setLineWidth(line.getLineWeight());
					vectorTile.setLayerId(vectorLayerMap.get(line.getLayerName()).getId());
					vectorTiles.add(vectorTile);
				}
				if (d instanceof DXFArc) {
				    //曲线
					DXFArc arc = (DXFArc) d;
					VectorTile vectorTile = new VectorTile();
					vectorTile.setName(arc.getLayerName());
					Point middlePoint = arc.getPointAt(arc.getStartAngle()+arc.getTotalAngle()/2);
					String coordinateWkt = "CIRCULARSTRING(" + arc.getStartPoint().getX() + " " + arc.getStartPoint().getY() + "," +
							middlePoint.getX() + " " + middlePoint.getY() + " "  + "," +
							arc.getEndPoint().getX() + " " + arc.getEndPoint().getY() + " " +
							")";
					vectorTile.setGeom(coordinateWkt);
					vectorTile.setColor(DXFUtil.getColor(arc.getColor()));
					vectorTile.setType("CIRCULARSTRING");
					vectorTile.setLineWidth(arc.getLineWeight());
					vectorTile.setLayerId(vectorLayerMap.get(arc.getLayerName()).getId());
					vectorTiles.add(vectorTile);
				}
				if(d instanceof DXFCircle){
				    //圆或半圆
					DXFCircle circle = (DXFCircle) d;
					VectorTile vectorTile = new VectorTile();
					vectorTile.setName(circle.getLayerName());
					Point startPoint = circle.getPointAt(0);
					Point topPoint = circle.getPointAt(90);
					Point farPoint = circle.getPointAt(180);
					Point bottomPoint = circle.getPointAt(270);
					Point endPoint = circle.getPointAt(360);
					String coordinateWkt = "CIRCULARSTRING(" + startPoint.getX() + " " + startPoint.getY() + "," +
							topPoint.getX() + " " + topPoint.getY() + " "  + "," +
							farPoint.getX() + " " + farPoint.getY() + " "  + "," +
							bottomPoint.getX() + " " + bottomPoint.getY() + " "  + "," +
							endPoint.getX() + " " + endPoint.getY() + " " +
							")";
					vectorTile.setGeom(coordinateWkt);
					vectorTile.setColor(DXFUtil.getColor(circle.getColor()));
					vectorTile.setType("CIRCLE");
					vectorTile.setLineWidth(circle.getLineWeight());
					vectorTile.setLayerId(vectorLayerMap.get(circle.getLayerName()).getId());
					vectorTiles.add(vectorTile);
				}
				if(d instanceof DXFPolyline){
				    //线段
					DXFPolyline dxfPolyline = (DXFPolyline) d;
					VectorTile vectorTile = new VectorTile();
					vectorTile.setName(dxfPolyline.getLayerName());
					Iterator<DXFVertex> lineIte =   dxfPolyline.getVertexIterator();
					List<DXFVertex> lines = new ArrayList<>();
					lineIte.forEachRemaining(lines::add);
					StringBuilder coordinateWkt = new StringBuilder("LINESTRING(");
					for (int i=0; i<lines.size();i++) {
						if(Double.isInfinite(lines.get(i).getPoint().getX()) || Double.isInfinite(lines.get(i).getPoint().getY())){
							break;
						}
						coordinateWkt.append(lines.get(i).getPoint().getX()).append(" ").append(lines.get(i).getPoint().getY());
						if(i!=(lines.size()-1)){
							coordinateWkt.append(" ,");
						}
					}
					coordinateWkt.append(")");
					vectorTile.setGeom(coordinateWkt.toString());
					vectorTile.setColor(DXFUtil.getColor(dxfPolyline.getColor()));
					vectorTile.setType("POLYLINE");
					vectorTile.setLineWidth(dxfPolyline.getLineWeight());
					vectorTile.setLayerId(vectorLayerMap.get(dxfPolyline.getLayerName()).getId());
					vectorTiles.add(vectorTile);
				}
				if(d instanceof DXFText){
				    //TODO 文字还有问题欢迎评论区讨论
                    DXFText dxfText = (DXFText) d;
					Font font = new Font("宋体",Font.PLAIN,(int)Math.rint(dxfText.getHeight()));
//					FontRenderContext frc = new FontRenderContext(AffineTransform.getRotateInstance(360-dxfText.getRotation(),dxfText.getInsertPoint().getX(),dxfText.getInsertPoint().getY()), false, false);
					FontRenderContext frc = new FontRenderContext((AffineTransform)null, false, false);
					GlyphVector v = font.createGlyphVector(FontDesignMetrics.getMetrics(font, frc).getFontRenderContext(), dxfText.getText());
					Shape shape = v.getOutline();
//					Shape shape = v.getGlyphOutline(0,new Double(dxfText.getInsertPoint().getX()).floatValue(),new Double(dxfText.getInsertPoint().getY()).floatValue());
					AffineTransform transform = new AffineTransform();
					transform.setToRotation(Math.toRadians(180));
					transform.setToTranslation(dxfText.getInsertPoint().getX(),dxfText.getInsertPoint().getY());
//					shape = transform.createTransformedShape(shape);
					PathIterator pathIterator = shape.getPathIterator(transform);
					List<Coordinate> path = new ArrayList<>();
					List<List<Coordinate>> pathList = new ArrayList<>();
					while (!pathIterator.isDone()){
						float[] coords = new float[6];
						int type = pathIterator.currentSegment(coords);
						if(PathIterator.SEG_CLOSE == type){
							pathList.add(path);
							path = new ArrayList<>();
							pathIterator.next();
							continue;
						}
						if(PathIterator.SEG_MOVETO == type){
							if(path.size()>0){
								pathList.add(path);
							}
							path = new ArrayList<>();
							pathIterator.next();
							continue;
						}
						if(PathIterator.SEG_LINETO == type){
							Coordinate coordinate = new Coordinate(coords[0],coords[1]);
							path.add(coordinate);
						}
						if(PathIterator.SEG_CUBICTO == type){
							VectorTile vectorTile = new VectorTile();
							vectorTile.setName(dxfText.getLayerName());
							String coordinateWkt = "CIRCULARSTRING(" + coords[0] + " " + coords[1] + "," +
									coords[2] + " " + coords[3] + " "  + "," +
									coords[4] + " " + coords[5] + " " +
									")";
							vectorTile.setGeom(coordinateWkt);
							vectorTile.setColor(DXFUtil.getColor(dxfText.getColor()));
							vectorTile.setType("TEXT");
							vectorTile.setRotation(dxfText.getRotation());
							vectorTile.setLayerId(vectorLayerMap.get(dxfText.getLayerName()).getId());
							vectorTiles.add(vectorTile);
							path = new ArrayList<>();
							pathIterator.next();
							continue;
						}
						if(PathIterator.SEG_QUADTO == type){
							Coordinate c1 = new Coordinate(coords[0],coords[1]);
							Coordinate c2 = new Coordinate(coords[2],coords[3]);
							path.add(c1);
							path.add(c2);
						}
						pathIterator.next();
					}
					for(List<Coordinate> p:pathList){
						VectorTile vectorTile = new VectorTile();
						vectorTile.setName(dxfText.getLayerName());
						StringBuilder coordinateWkt = new StringBuilder("LINESTRING(");
						for (int i=0; i<p.size();i++) {
							coordinateWkt.append(p.get(i).getX()).append(" ").append(p.get(i).getY());
							if(i!=(p.size()-1)){
								coordinateWkt.append(" ,");
							}
						}
						coordinateWkt.append(")");
						vectorTile.setColor(DXFUtil.getColor(dxfText.getColor()));
						vectorTile.setGeom(coordinateWkt.toString());
						vectorTile.setType("TEXT");
						vectorTile.setRotation(dxfText.getRotation());
						vectorTile.setLayerId(vectorLayerMap.get(dxfText.getLayerName()).getId());
						vectorTiles.add(vectorTile);
					}
				}
			}
			this.saveBatch(vectorTiles);
		}catch (Exception e){
			e.printStackTrace();
		}
		return null;
	}

查询矢量切图代码如下:

@Override
public byte[] selectVectorTile(Integer x, Integer y, Integer z, List<Long> layerIds) {
	VectorBox vectorBox = vectorBoxService.lambdaQuery().one();
	 VectorTile vTile=this.baseMapper.selectTile(x,y,z,vectorBox.getxMin(),vectorBox.getyMin(),vectorBox.getxMax(),vectorBox.getyMax(),layerIds);
	return vTile.getTile();
}

查询SQL如下:

        SELECT
            ST_AsMVT (a, 'points',4096,'geom') As tile
        FROM
            (
                SELECT t.id,
                       st_asmvtgeom (
                           (case st_geometrytype(t.geom)
                               when 'ST_CircularString'
                                   then st_curvetoline(t.geom)
                               else t.geom
                               end),
                           ST_TileEnvelope( #{z}, #{x}, #{y},
                               st_makeenvelope (
                                   #{xMin} ,
                                   #{yMin} ,
                                   #{xMax} ,
                                   #{yMax} , 4775)),
                                     4096,
                                     64,
                                     true
                           ) AS geom,
                        t.color AS color
                FROM
                    vector_tile t
                <where>
                    <if test="layerIds !=null ">
                        and t.layer_id in
                        <foreach collection="layerIds" separator="," open="(" close=")" item="item">
                            #{item}
                        </foreach>
                    </if>
                </where>
            ) AS a where a.geom is not null


前端openlayer渲染

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <title>Insert title here</title>
    <!--<link rel="stylesheet" href="https://openlayers.org/en/v4.6.4/css/ol.css" type="text/css">-->
    <!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
    <script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
    <link href="https://cdn.bootcdn.net/ajax/libs/openlayers/4.6.5/ol-debug.css" rel="stylesheet">
    <script src="https://cdn.bootcdn.net/ajax/libs/openlayers/4.6.5/ol-debug.js"></script>
    <style>
        html, body, #map {
            width: 100%;
            height: 100%;
            padding: 0;
            margin: 0;
            background-color: black;
        }
    </style>
</head>
<body>
<div id="map">
</div>
</body>
<script>

    const projection = new ol.proj.Projection({
        code: 'EPSG:4775',
        units: 'degrees',
    });

    const defaultView = new ol.View({
        projection: projection,
        center: [114.15, 22.65],
        //new ol.proj.fromLonLat([114.15, 22.65]),
        zoom: 2
        //旋转
        // rotation: Math.PI/3
    });

    const styleFunction = function (feature) {
        const color = feature.get("color");
        const width = feature.get("linewidth")/100;
        console.log(width)
        const type = feature.get("type");
        const text = feature.get("text");
        const zoom = map.getView().getZoom();
        const textScale = calculateTextScale(zoom);
        const rotation = (360-feature.get("rotation"))*(Math.PI/180);
        if(type=="TEXT"){
            const retStyle = new ol.style.Style({
                text: new ol.style.Text({
                    text: text,
                    placement: 'point',
                    rotation: rotation,
                    rotateWithView:true,
                    font: '14px Microsoft YaHei',
                    fill: new ol.style.Fill({
                        color: color
                    }),
                    textAlign: 'center',
                    textBaseline: 'middle',
                    scale: textScale // 根据地图缩放级别设置文字缩放比例
                })
            });
            return retStyle;
        }else{
            const retStyle = new ol.style.Style({
                stroke: new ol.style.Stroke({
                    color: color,
                    // width: width
                })
            });
            return retStyle;
        }
    };

    const vectorLayer = new ol.layer.VectorTile({
        projection: projection,
        source: new ol.source.VectorTile({
            format: new ol.format.MVT(),
            projection: projection,
            tilePixelRatio: 1,
            url: 'http://127.0.0.1/zgis/vector/tile/{z}/{x}/{y}'
        }),
        style: styleFunction,
    });


    const layers = [
        new ol.layer.Tile({
            source: new ol.source.OSM()
        })
    ];

    layers.push(vectorLayer);

    const map = new ol.Map({
        layers: layers,
        target: 'map',
        view: defaultView
    });

</script>
</html>

目前文字和填充还有些问题,其他可正常支持。
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 7
    评论
评论 7
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值