文章目录
前言
本文将叙述Kabeja库的介绍与使用,以及通过Kabeja库提取CAD图的图元、图块、图层等数据,在第三方平台(这里使用的是AnyLogic)复现CAD图。通过引用Kabeja库,编写代码提取DXF文档的数据,并分析提取的源数据与Anylogic中定义的坐标轴、弧线、圆、椭圆等比例数据,以此在Kabeja的基础上编写一个新Jar包,则可以实现CAD图在Anylogic复现。
一、Kabeja库介绍
Kabeja库是Java依赖库,针对DXF格式的CAD图解析与数据提取,提供了大量DXF数据操作函数。
二、DXF格式介绍
CAD图DXF格式文档主要由图块、图元、图层这三者组成。图元由各种不同的几何类型组成包括但不限于线、多线、弧线、点、圆、椭圆等组成。每个图元都有各种属性,如线性、颜色、大小、名称、句柄等。图块可以理解为各种不同图元的固定组合。通过图块,能够重复使用一些设计起来较为复杂但一致的细节。如同样的门、桌子、洗手盆等,一个门图块可能包含了弧线和线两个图元,其中弧线代表门的打开路径、线代表门的宽度等信息。不同的图元可能由不同的线性组成。由此形成一个独特的图块结构。同时图块也有自己的属性,除了插入点、颜色等等外,还包括了旋转角度、缩放角度等。同一个图块在不同的地方,使用不同的缩放大小代表不一致的规格。如大门与室内的小门可用不同缩放的门进行表示。图层通过对不同元素进行分别绘制,以达到更好的规划管理数据的功能。通常将室内建筑数据分为、装饰物、墙面、家具、门窗等不同类型的图层。使用图层可快速筛选需要的数据。
三、使用步骤
1.引入库
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import org.kabeja.dxf.*;
import org.kabeja.dxf.helpers.Point;
import org.kabeja.dxf.objects.DXFDictionary;
import org.kabeja.parser.ParseException;
import org.kabeja.parser.Parser;
import org.kabeja.parser.ParserBuilder;
import java.awt.*;
import java.io.*;
import java.util.*;
import java.util.List;
2.提取数据
代码如下(示例):
/*
1. 提取后的数据要判断可见性
2. 将可见的图层、图快、图元返回
*/
//extract 图元类型
public static ArrayList<String> getDXFEntityTypes(DXFDocument doc){
ArrayList<DXFLayer> dxfLayers = getDXFLayers(doc);
ArrayList<String> types = new ArrayList<>();
HashSet<String> noRepeatTypes = new HashSet<>();
for (DXFLayer dxfLayer:dxfLayers){
Iterator iter = dxfLayer.getDXFEntityTypeIterator();
while (iter.hasNext()){
String type = (String) iter.next();
noRepeatTypes.add(type);
}
}
types.addAll(noRepeatTypes);
return types;
}
/*
根据图元类型提取数据
*/
public static ArrayList<DXFLine> getDXFLines(DXFDocument doc){
ArrayList<DXFLayer> dxfLayers = getDXFLayers(doc);
ArrayList<DXFLine> dxfLines = new ArrayList<>();
for (DXFLayer dxfLayer:dxfLayers){
List dxfEntities = dxfLayer.getDXFEntities(DXFConstants.ENTITY_TYPE_LINE);
if(dxfEntities != null){
dxfLines.addAll(dxfEntities);
}
}
System.out.println("size"+dxfLines.size());
return dxfLines;
}
public static ArrayList<DXFCircle> getDXFCircles(DXFDocument doc){
ArrayList<DXFLayer> dxfLayers = getDXFLayers(doc);
ArrayList<DXFCircle> dxfCircles = new ArrayList<>();
for (DXFLayer dxfLayer:dxfLayers){
List dxfEntities = dxfLayer.getDXFEntities(DXFConstants.ENTITY_TYPE_CIRCLE);
if(dxfEntities != null){
dxfCircles.addAll(dxfEntities);
}
}
return dxfCircles;
}
public static ArrayList<DXFArc> getDXFArcs(DXFDocument doc){
ArrayList<DXFLayer> dxfLayers = getDXFLayers(doc);
ArrayList<DXFArc> dxfArcs = new ArrayList<>();
for (DXFLayer dxfLayer:dxfLayers){
List dxfEntities = dxfLayer.getDXFEntities(DXFConstants.ENTITY_TYPE_ARC);
if(dxfEntities != null){
dxfArcs.addAll(dxfEntities);
}
}
return dxfArcs;
}
public static ArrayList<DXFPolyline> getDXFPolylines(DXFDocument doc){
ArrayList<DXFLayer> dxfLayers = getDXFLayers(doc);
ArrayList<DXFPolyline> dxfPolylines = new ArrayList<>();
for (DXFLayer dxfLayer:dxfLayers){
List dxfEntities = dxfLayer.getDXFEntities(DXFConstants.ENTITY_TYPE_LWPOLYLINE);
if(dxfEntities != null){
dxfPolylines.addAll(dxfEntities);
}
}
return dxfPolylines;
}
public static ArrayList<Point> getDXFPolylinePoints(DXFPolyline dxfPolyline){
ArrayList<Point> dxfVertices = new ArrayList<>();
Iterator iter = dxfPolyline.getVertexIterator();
while(iter.hasNext()){
DXFVertex next = (DXFVertex) iter.next();
dxfVertices.add(next.getPoint());
}
return dxfVertices;
}
public static ArrayList<DXFInsert> getDXFInserts(DXFDocument doc){
ArrayList<DXFLayer> dxfLayers = getDXFLayers(doc);
ArrayList<DXFInsert> dxfInserts = new ArrayList<>();
for (DXFLayer dxfLayer:dxfLayers){
List dxfEntities = dxfLayer.getDXFEntities(DXFConstants.ENTITY_TYPE_INSERT);
if(dxfEntities != null){
dxfInserts.addAll(dxfEntities);
}
}
return dxfInserts;
}public static ArrayList<DXFHatch> getDXFHatchs(DXFDocument doc){
ArrayList<DXFLayer> dxfLayers = getDXFLayers(doc);
ArrayList<DXFHatch> dxfHatches = new ArrayList<>();
for (DXFLayer dxfLayer:dxfLayers){
List dxfEntities = dxfLayer.getDXFEntities(DXFConstants.ENTITY_TYPE_HATCH);
if(dxfEntities != null){
dxfHatches.addAll(dxfEntities);
}
}
return dxfHatches;
}
public static ArrayList<DXFSpline> getDXFSplines(DXFDocument doc){
ArrayList<DXFLayer> dxfLayers = getDXFLayers(doc);
ArrayList<DXFSpline> dxfSplines = new ArrayList<>();
for (DXFLayer dxfLayer:dxfLayers){
List dxfEntities = dxfLayer.getDXFEntities(DXFConstants.ENTITY_TYPE_SPLINE);
if(dxfEntities != null){
dxfSplines.addAll(dxfEntities);
}
}
return dxfSplines;
}
public static ArrayList<DXFMText> getDXFMTexts(DXFDocument doc){
ArrayList<DXFLayer> dxfLayers = getDXFLayers(doc);
ArrayList<DXFMText> dxfmTexts = new ArrayList<>();
for (DXFLayer dxfLayer:dxfLayers){
List dxfEntities = dxfLayer.getDXFEntities(DXFConstants.ENTITY_TYPE_MTEXT);
if(dxfEntities != null){
dxfmTexts.addAll(dxfEntities);
}
}
return dxfmTexts;
}
public static ArrayList<DXFEllipse> getDXFEllipses(DXFDocument doc){
ArrayList<DXFLayer> dxfLayers = getDXFLayers(doc);
ArrayList<DXFEllipse> dxfEllipses = new ArrayList<>();
for (DXFLayer dxfLayer:dxfLayers){
List dxfEntities = dxfLayer.getDXFEntities(DXFConstants.ENTITY_TYPE_ELLIPSE);
if(dxfEntities != null){
dxfEllipses.addAll(dxfEntities);
}
}
return dxfEllipses;
}
public static ArrayList<DXFDimension> getDXFDimensions(DXFDocument doc){
ArrayList<DXFLayer> dxfLayers = getDXFLayers(doc);
ArrayList<DXFDimension> dxfDimensions = new ArrayList<>();
for (DXFLayer dxfLayer:dxfLayers){
List dxfEntities = dxfLayer.getDXFEntities(DXFConstants.ENTITY_TYPE_DIMENSION);
if(dxfEntities != null){
dxfDimensions.addAll(dxfEntities);
}
}
return dxfDimensions;
}
public static ArrayList<DXFViewport> getDXFViewports(DXFDocument doc){
ArrayList<DXFLayer> dxfLayers = getDXFLayers(doc);
ArrayList<DXFViewport> dxfViewports = new ArrayList<>();
for (DXFLayer dxfLayer:dxfLayers){
List dxfEntities = dxfLayer.getDXFEntities(DXFConstants.ENTITY_TYPE_VIEWPORT);
if(dxfEntities != null){
dxfViewports.addAll(dxfEntities);
}
}
return dxfViewports;
}
//提取CAD每一个图块中的图元数据
public static List<DXFEntity> getDXFEntitiesByDXFBlock(DXFBlock dxfBlock){
ArrayList<DXFEntity> list = new ArrayList<>();
Iterator iter = dxfBlock.getDXFEntitiesIterator();
Integer num = 0;
System.out.println("图块名称:"+dxfBlock.getName());
while (iter.hasNext()){
num++;
DXFEntity next = (DXFEntity) iter.next();
list.add(next);
}
return list;
}
//获取CAD图中尺寸标注信息
public static List<DXFDimensionStyle> getDXFDimensionStyle(DXFDocument dxfdoc){
ArrayList<DXFDimensionStyle> list = new ArrayList<>();
Iterator iter = dxfdoc.getDXFDimensionStyleIterator();
while(iter.hasNext()){
DXFDimensionStyle dxfDimensionStyle = (DXFDimensionStyle) iter.next();
list.add(dxfDimensionStyle);
}
return list;
}
//提取CAD图中所有的图块
public static ArrayList<DXFBlock> getDXFBlocks(DXFDocument dxfdoc){
ArrayList<DXFBlock> dxfBlocks = new ArrayList<>();
Iterator iter = dxfdoc.getDXFBlockIterator();
while(iter.hasNext()){
DXFBlock dXFBlock = (DXFBlock)iter.next();
dxfBlocks.add(dXFBlock);
}
return dxfBlocks;
}
//获取所有的entity
public static List<DXFEntity> getDXFEntities(DXFDocument dxfdoc){
//创建一个用于存储实体对象的列表
List<DXFEntity> list = new ArrayList<DXFEntity>();
//获取DXF文档的图层迭代器
Integer num = 0;
Iterator iter = dxfdoc.getDXFLayerIterator();
while(iter.hasNext()){//遍历每个图层
//获取当前图层对象
DXFLayer dXFLayer = (DXFLayer)iter.next();
num++;
//获取当前图层的实体类型列表
List<String> l = getDXFEntityTypes(dXFLayer);
for(String s : l){
//获取当前实体类型下的所有实体对象列表
List<DXFEntity> ld = dXFLayer.getDXFEntities(s);
for(DXFEntity d : ld){
list.add(d);
}
}
}
return list;
}
//根据图层名称获取entity
public static List<DXFEntity> getDXFEntitiesByLayerName(DXFDocument dxfdoc,String layerName){
List<DXFEntity> list = new ArrayList<DXFEntity>();
Iterator iter = dxfdoc.getDXFLayerIterator();
while(iter.hasNext()){
DXFLayer dXFLayer = (DXFLayer)iter.next();
if(dXFLayer.getName().equals(layerName)){
List<String> l = getDXFEntityTypes(dXFLayer);
for(String s : l){
List<DXFEntity> ld = dXFLayer.getDXFEntities(s);
for(DXFEntity d : ld){
list.add(d);
}
}
}
}
return list;
}
//根据图层获取entity
public static List<DXFEntity> getDXFEntitiesByLayer(DXFLayer dxfLayer){
List<DXFEntity> list = new ArrayList<DXFEntity>();
List<String> l = getDXFEntityTypes(dxfLayer);
for(String s : l){
List<DXFEntity> ld = dxfLayer.getDXFEntities(s);
for(DXFEntity d : ld){
if(d.isVisibile()) list.add(d);
}
}
return list;
}
//提取CAD图中所有图层数据
public static ArrayList<DXFLayer> getDXFLayers(DXFDocument dxfdoc){
ArrayList<DXFLayer> dxfLayers = new ArrayList<>();
Iterator iter = dxfdoc.getDXFLayerIterator();
while(iter.hasNext()){
DXFLayer dXFLayer = (DXFLayer)iter.next();
if(dXFLayer.isVisible()) dxfLayers.add(dXFLayer);
// getDXFSubEntityByEntity(dXFLayer);
}
System.out.println("Layers"+dxfLayers.size());
return dxfLayers;
}
//通过DXFBlock获取entity
public static List<DXFEntity> getEntityByDXFBlock(DXFBlock dXFBlock){
List<DXFEntity> list = new ArrayList<DXFEntity>();
Iterator iter = dXFBlock.getDXFEntitiesIterator();
while(iter.hasNext()){
DXFEntity d = (DXFEntity)iter.next();
list.add(d);
}
return list;
}
//通过图层获取DXFEntityType
public static List<String> getDXFEntityTypes(DXFLayer dXFLayer){
List<String> list = new ArrayList<String>();
Iterator iter = dXFLayer.getDXFEntityTypeIterator();
while(iter.hasNext()){
String d = (String)iter.next();
list.add(d);
}
return list;
}
//getDXFLineTypeIterator() 线型
public static List<DXFLineType> getDXFLineTypes(DXFDocument dxfdoc){
List<DXFLineType> dXFLineTypes = new ArrayList<DXFLineType>();
Iterator iter = dxfdoc.getDXFLineTypeIterator();
while(iter.hasNext()){
DXFLineType dXFLineType = (DXFLineType)iter.next();
dXFLineTypes.add(dXFLineType);
}
return dXFLineTypes;
}
//getDXFStyleIterator()
public static List<DXFStyle> getDXFStyles(DXFDocument dxfdoc){
List<DXFStyle> dXFStyles = new ArrayList<DXFStyle>();
Iterator iter = dxfdoc.getDXFStyleIterator();
while(iter.hasNext()){
DXFStyle dXFStyle = (DXFStyle)iter.next();
dXFStyles.add(dXFStyle);
}
return dXFStyles;
}
//getDXFViewIterator()
public static List<DXFView> getDXFViews(DXFDocument dxfdoc){
List<DXFView> dXFViews = new ArrayList<DXFView>();
Iterator iter = dxfdoc.getDXFViewIterator();
while(iter.hasNext()){
DXFView dXFView = (DXFView)iter.next();
dXFViews.add(dXFView);
}
return dXFViews;
}
3.颜色属性
private static final String[] colorCorrelation ={
"0,0,0"
,"255,0,0"
,"255,255,0"
,"0,255,0"
,"0,255,255"
,"0,0,255"
,"255,0,255"
,"255,255,255"
,"128,128,128"
,"192,192,192"
,"255,0,0"
,"255,127,127"
,"204,0,0"
,"204,102,102"
,"153,0,0"
,"153,76,76"
,"127,0,0"
,"127,63,63"
,"76,0,0"
,"76,38,38"
,"255,63,0"
,"255,159,127"
,"204,51,0"
,"204,127,102"
,"153,38,0"
,"153,95,76"
,"127,31,0"
,"127,79,63"
,"76,19,0"
,"76,47,38"
,"255,127,0"
,"255,191,127"
,"204,102,0"
,"204,153,102"
,"153,76,0"
,"153,114,76"
,"127,63,0"
,"127,95,63"
,"76,38,0"
,"76,57,38"
,"255,191,0"
,"255,223,127"
,"204,153,0"
,"204,178,102"
,"153,114,0"
,"153,133,76"
,"127,95,0"
,"127,111,63"
,"76,57,0"
,"76,66,38"
,"255,255,0"
,"255,255,127"
,"204,204,0"
,"204,204,102"
,"153,153,0"
,"153,153,76"
,"127,127,0"
,"127,127,63"
,"76,76,0"
,"76,76,38"
,"191,255,0"
,"223,255,127"
,"153,204,0"
,"178,204,102"
,"114,153,0"
,"133,153,76"
,"95,127,0"
,"111,127,63"
,"57,76,0"
,"66,76,38"
,"127,255,0"
,"191,255,127"
,"102,204,0"
,"153,204,102"
,"76,153,0"
,"114,153,76"
,"63,127,0"
,"95,127,63"
,"38,76,0"
,"57,76,38"
,"63,255,0"
,"159,255,127"
,"51,204,0"
,"127,204,102"
,"38,153,0"
,"95,153,76"
,"31,127,0"
,"79,127,63"
,"19,76,0"
,"47,76,38"
,"0,255,0"
,"127,255,127"
,"0,204,0"
,"102,204,102"
,"0,153,0"
,"76,153,76"
,"0,127,0"
,"63,127,63"
,"0,76,0"
,"38,76,38"
,"0,255,63"
,"127,255,159"
,"0,204,51"
,"102,204,127"
,"0,153,38"
,"76,153,95"
,"0,127,31"
,"63,127,79"
,"0,76,19"
,"38,76,47"
,"0,255,127"
,"127,255,191"
,"0,204,102"
,"102,204,153"
,"0,153,76"
,"76,153,114"
,"0,127,63"
,"63,127,95"
,"0,76,38"
,"38,76,57"
,"0255,191"
,"127,255,223"
,"0,204,153"
,"102,204,178"
,"0,153,114"
,"76,153,133"
,"0,127,95"
,"63,127,111"
,"0,76,57"
,"38,76,66"
,"0,255,255"
,"127,255,255"
,"0,204,204"
,"102,204,204"
,"0,153,153"
,"76,153,153"
,"0,127,127"
,"63,127,127"
,"0,76,76"
,"38,76,76"
,"0,191,255"
,"127,223,255"
,"0,153,204"
,"102,178,204"
,"0,114,153"
,"76,13,153"
,"0,95,127"
,"63,111,127"
,"0,57,76"
,"38,66,76"
,"0,127,255"
,"127,191,255"
,"0,102,204"
,"102,153,204"
,"0,76,153"
,"76,114,153"
,"0,63,127"
,"63,95 127"
,"0,38,76"
,"38,57,76"
,"0,63,255"
,"127,159,255"
,"0,51,204"
,"102,127,204"
,"0,38,153"
,"76,95 153"
,"0,31,127"
,"63,79,127"
,"0,19,76"
,"38,47,76"
,"0,0,255"
,"127,127,255"
,"0,0,204"
,"102,102,204"
,"0,0,153"
,"76,76,153"
,"0,0,127"
,"63,63 127"
,"0,0,76"
,"38,38,76"
,"63,0,255"
,"159,127,255"
,"51,0,204"
,"127,102204"
,"38,0,153"
,"95,76,153"
,"31,0,127"
,"79,63,127"
,"19,0,76"
,"47,38,76"
,"127,0,255"
,"191,127,255"
,"102,0,204"
,"153,102,204"
,"76,0,153"
,"114,76,153"
,"63,0,127"
,"95,63,127"
,"38,0,76"
,"57,38,76"
,"191,0,255"
,"223,127,255"
,"153,0,204"
,"178,102,204"
,"114,0,153"
,"133,76,153"
,"95,0,127"
,"111,63,127"
,"57,0,76"
,"66,38,76"
,"255,0,255"
,"255,127,255"
,"204,0,204"
,"204,10,204"
,"153,0,153"
,"153,76,153"
,"127,0,127"
,"127,63,127"
,"76,0,76"
,"76,38,76"
,"255,0,191"
,"255,127,223"
,"204,0,153"
,"204,102,178"
,"153,0,114"
,"153,76,133"
,"127,0,95"
,"127,63,111"
,"76,0,57"
,"76,38,66"
,"255,0,127"
,"255,127,191"
,"204,0,102"
,"204,102,153"
,"153,0,76"
,"153,76,114"
,"127,0,63"
,"127,63,95"
,"76,0,38"
,"76,38,57"
,"255,0,63"
,"255,127,159"
,"204,0,51"
,"204,102,127"
,"153,0,38"
,"153,76,95"
,"127,0,31"
,"127,63,79"
,"76,0,19"
,"76,38,47"
,"51,51,51"
,"91,91,91"
,"132,132,132"
,"173,173,173"
,"214,214,214"
,"255,255,255"};
4.Anylogic坐标轴、圆、椭圆、弧线等比例变换
// Anylogic中复现圆数据
ArrayList<DXFCircle> circleList = CadDataExtraction.getDXFCircles(dxfDocument);
for (DXFCircle circle : circleList){
ShapeOval testCircle = new ShapeOval();
testCircle.setX(circle.getCenterPoint().getX()/200 - 1200);
testCircle.setY(-circle.getCenterPoint().getY()/200 + 1150);
testCircle.setRadius(circle.getRadius()/200);
presentation.add(testCircle);
}
// Anylogic中复现弧线数据
ArrayList<DXFArc> arcList = CadDataExtraction.getDXFArcs(dxfDocument);
for(DXFArc arc : arcList){
ShapeArc testArc = new ShapeArc();
testArc.setX(arc.getCenterPoint().getX()/200 - 1200);
testArc.setY(-arc.getCenterPoint().getY()/200 + 1150);
testArc.setAngleStart(Math.toRadians(360 - arc.getEndAngle()) );
testArc.setAngle(Math.toRadians((360-arc.getStartAngle() + arc.getEndAngle())%360));
testArc.setRadius(arc.getRadius()/200);
presentation.add(testArc);
}
// Anylogic中复现直线数据
ArrayList<DXFLine> list = CadDataExtraction.getDXFLines(dxfDocument);
for(DXFLine dxfLine : list){
ShapeLine test = new ShapeLine();
test.setX((dxfLine.getStartPoint().getX())/200-1200);
test.setY((-dxfLine.getStartPoint().getY())/200+1150);
test.setEndX((dxfLine.getEndPoint().getX())/200-1200);
test.setEndY((-dxfLine.getEndPoint().getY())/200+1150);
//traceln(dxfLine.getColor()+ " --");
//int[] color = CadDataExtraction.getColorRGB(dxfLine.getColor());
//traceln(color.length + "----------------");
//test.setColor(new Color(color[0], color[1], color[2]));
presentation.add(test);
}
Anylogic中复现多段线数据
ArrayList<DXFPolyline> polyLineList = CadDataExtraction.getDXFPolylines(dxfDocument);
for(DXFPolyline polyLine : polyLineList ){
ShapePolyLine test = new ShapePolyLine();
ArrayList<Point> points = CadDataExtraction.getDXFPolylinePoints(polyLine);
int i = 0;
Point p0 = points.get(0);
test.setNPoints(points.size() + 1);
for (Point p : points){
test.setPoint(i, p.getX()/200 - 1200, -p.getY()/200 + 1150);
i++;
}
test.setPoint(i, p0.getX()/200 - 1200, -p0.getY()/200 + 1150);
//test.setLineColor(red);
presentation.add(test);
}
Anylogic中复现文本数据
ArrayList<DXFMText> textList = CadDataExtraction.getDXFMTexts(dxfDocument);
for(DXFMText mText : textList){
ShapeText text = new ShapeText();
text.setText(mText.getText());
text.setPos(mText.getAlignX()/200 - 1200, -mText.getAlignY()/200 +1150);
DXFLayer layer = dxfDocument.getDXFLayer(mText.getLayerName());
text.setFont(new Font("仿宋", Font.PLAIN, 2));
mText.setText(mText.getText().replace("\\P", "\n"));
text.setText(mText.getText());
//text.setColor(new Color(mText.getColor()));
text.setZ(mText.getAlignZ()/200);
traceln(mText.getText() + " "+ mText.getText().getClass() + " " + (mText.getAlignX()/200 - 1200) + " " + (-mText.getAlignY()/200 +1150));
presentation.add(text);
}
四、总结
1.相关Jar包链接
2.Anylogic复现图
在第三方平台复现CAD图,其实际效果是存在多行文本的相关数据提取失败,其他类型的数据均提取完整,这个问题可能是由DXF文档版本过高造成的。复现图颜色问题已经解决,已在第三章节列出相关解决代码。
3.技术难点
在第三方平台复现CAD图,其主要难点是针对DXF文档提取的图元、图层、图块数据与第三方平台的相关实体进行比例转换,其比例系数主要是由试错法进行的,找到最优DXF文档与第三方平台相关实体的比例系数。