package com.fdkankan.dxf.generate; import com.fdkankan.dxf.generate.model.*; import com.fdkankan.dxf.generate.model.base.BaseDxfEntity; import com.fdkankan.dxf.generate.model.base.DxfEntity; import com.fdkankan.dxf.generate.model.support.DxfExtent; import com.fdkankan.dxf.generate.util.DxfUtil; import com.fdkankan.dxf.generate.util.FreemarkerSupport; import com.fdkankan.dxf.generate.util.StreamUtil; import com.fdkankan.dxf.generate.util.StringUtil; import java.io.*; import java.nio.charset.Charset; import java.nio.charset.StandardCharsets; import java.util.*; /** * Dxf处理类,支持向矿图中添加自定义图形,目前支持的图形有圆形Circle,圆弧Arc,直线Line,多线段LwPolyLine,文字Text 目前仅仅支持对圆形Circle和其子类Arc的颜色填充。 可以通过调用 {@link #addEntity(DxfEntity)} 和 {@link #removeEntity(DxfEntity)} 进行自定义图元的添加和删除。 *
* 并支持对新dxf文件的导出,可以选择调用函数 {@link #save(String, boolean)} 导出所有文件,这样的文件可以在AutoCad中打开 也可以通过函数 {@link #saveEntities(String, boolean)} 仅仅导出entity图元信息,这样的文件仅仅支持使用解析库进行解析 *
* 另外和文件流一样,dxfDocument对象也需要在使用结束后关闭,通过调用 {@link #close()} 函数进行关闭,可以以想流式对象那样使用,如
* ** * @author YTZJJ */ @SuppressWarnings("unused") public class DxfDocWriter implements Closeable { /** * 当选择保存为dxf文件的时候,要保留的Entities类型的数组,不在数组中的对象将会被忽略掉(不包含自定义加入的图元) */ public static final String[] DEFAULT_ENTITY_NO_REDUCE_PART = {"LINE", "CIRCLE", "ARC", "TEXT", "MTEXT", "LWPOLYLINE"}; private List* try(DxfDocument dxf = new DxfDocument(path)) { * body * } ** *
* 也可以通过继承 {@link BaseDxfEntity} 或实现 {@link DxfEntity} 接口来扩展图元
*
* @param dxfEntity 图元
*/
public void addEntity(DxfEntity dxfEntity) {
if (dxfEntity instanceof DxfRay) {
if (Vector3.ZERO.equals(((DxfRay) dxfEntity).getDirection())) {
System.err.println(dxfEntity.getEntityName() + " direction cant be zero!!, will ignore this entity");
return;
}
}
if (dxfEntity instanceof DxfLwPolyLine) {
if (((DxfLwPolyLine) dxfEntity).isEmpty()) {
System.err.println("LwPolyLine not contains any point, will ignore this entity");
return;
}
}
dxfEntity.setMeta(++maxMeta);
this.newDxfEntityList.add(dxfEntity);
if (dxfEntity instanceof DxfCircle || dxfEntity instanceof DxfLwPolyLine) {
if (((BaseDxfEntity) dxfEntity).isSolid()) {
addEntity(DxfHatch.buildHatchBy((BaseDxfEntity) dxfEntity));
}
}
}
/**
* 移除一个自定义的图元
*
* @param dxfEntity 图元
*/
public void removeEntity(DxfEntity dxfEntity) {
this.newDxfEntityList.remove(dxfEntity);
for (DxfEntity entity : newDxfEntityList) {
if (entity instanceof DxfHatch) {
if (((DxfHatch) dxfEntity).getDxfSolid().getDxfEntity() == dxfEntity) {
this.newDxfEntityList.remove(dxfEntity);
}
}
}
}
/**
* 设置要保存的矿图文件中要保留的图元类型列表,如果设置为 null, 那么原矿图中的所有图元都将会被保留 默认的要保存的图元列表表为 {@link #DEFAULT_ENTITY_NO_REDUCE_PART}
*
* @param entityNoReducePart 要保留的图元列表
*/
public void setEntityNoReducePart(String... entityNoReducePart) {
if (entityNoReducePart == null) {
this.entityNoReducePart = null;
} else {
this.entityNoReducePart = Arrays.asList(entityNoReducePart);
}
}
/**
* 仅仅保存矿图中的图元信息(ENTITIES 部分)到文件中,其他部分(HEADER, CLASSES, TABLES...)都将被舍弃 通过 {@link #setEntityNoReducePart(String...)} 可以自定义保留那些类型的图元
*
* @param entitiesFilePath 要保存的文件位置
* @param containNewEntity 是否包含自定义添加进去的图元信息
*/
public void saveEntities(String entitiesFilePath, boolean containNewEntity) {
save(entitiesFilePath, true, containNewEntity);
}
/**
* 保存为新的dxf文件
*
* @param saveDxfFilePath 要保存的问题件位置
* @param containNewEntity 是否报刊自定义添加进去的图元信息
*/
public void save(String saveDxfFilePath, boolean containNewEntity) {
save(saveDxfFilePath, false, containNewEntity);
}
public String readString(boolean containNewEntity) {
StringBuilder result = new StringBuilder();
read(false, containNewEntity, result::append);
return result.toString();
}
private void read(boolean justSaveEntity, boolean containNewEntity, ReadDxfConsumer readStr) {
FreemarkerSupport.getInstance();
try {
if (dxfFile != null) {
br.mark((int) (dxfFile.length() + 1));
} else {
String value = FreemarkerSupport.getInstance().processPath("/dxf/empty.dxf.ftl", extent);
br = StreamUtil.getReader(new ByteArrayInputStream(value.getBytes()));
//
// br = StreamUtil.getReader(StreamUtil.getResourceStream("empty.dxf"));
}
StringBuffer writeBuffer = new StringBuffer();
while (true) {
String[] pair = StreamUtil.readNextPair(br);
if (pair == null) {
break;
}
if ("0".equals(pair[0].trim()) && "SECTION".equals(pair[1].trim())) {
// nextPartStart
String[] nextPairTitleTag = StreamUtil.readNextPair(br);
if (nextPairTitleTag == null) {
continue;
}
String nextPartName = nextPairTitleTag[1].trim();
if (justSaveEntity) {
justSaveEntity(writeBuffer, pair, nextPairTitleTag, containNewEntity);
} else {
handleAll(writeBuffer, pair, nextPairTitleTag, containNewEntity);
}
readStr.accept(writeBuffer.toString());
writeBuffer = new StringBuffer();
System.out.println("handle part " + nextPartName + " end");
} else if ("EOF".equals(pair[1].trim())) {
StringUtil.appendLnCrLf(writeBuffer, pair);
readStr.accept(writeBuffer.toString());
System.out.println("completed!! dxf reduce end<<<<<<<<<<<<<");
break;
}
}
} catch (Exception e) {
System.err.println("Reduce dxf fail!!!!!!" + e.getMessage());
} finally {
try {
if (dxfFile != null) {
br.reset();
} else {
br.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
private void save(String saveDxfFilePath, boolean justSaveEntity, boolean containNewEntity) {
try (BufferedWriter fileWriter = StreamUtil.getFileWriter(saveDxfFilePath, charset)) {
read(justSaveEntity, containNewEntity, fileWriter::write);
fileWriter.flush();
} catch (IOException e) {
System.err.println("save fail" + e.getLocalizedMessage());
}
}
private void justSaveEntity(StringBuffer writeBuffer, String[] pair, String[] nextPairTitleTag, boolean containNewEntity) throws IOException {
String nextPartName = nextPairTitleTag[1].trim();
if ("ENTITIES".equals(nextPartName)) {
StringUtil.appendLnCrLf(writeBuffer, pair);
StringUtil.appendLnCrLf(writeBuffer, nextPairTitleTag);
handEntities(writeBuffer, containNewEntity);
} else {
ignoreNextPart();
}
}
private void handleAll(StringBuffer writeBuffer, String[] pair, String[] nextPairTitleTag, boolean containNewEntity) throws IOException {
String nextPartName = nextPairTitleTag[1].trim();
switch (nextPartName) {
case "HEADER":
StringUtil.appendLnCrLf(writeBuffer, pair);
StringUtil.appendLnCrLf(writeBuffer, nextPairTitleTag);
handHeader(writeBuffer);
break;
case "ENTITIES":
StringUtil.appendLnCrLf(writeBuffer, pair);
StringUtil.appendLnCrLf(writeBuffer, nextPairTitleTag);
handEntities(writeBuffer, containNewEntity);
break;
case "CLASSES":
case "TABLES":
case "BLOCKS":
case "OBJECTS":
StringUtil.appendLnCrLf(writeBuffer, pair);
StringUtil.appendLnCrLf(writeBuffer, nextPairTitleTag);
justOutput(writeBuffer);
break;
default:
ignoreNextPart();
break;
}
}
private void ignoreNextPart() throws IOException {
while (true) {
String[] piar = StreamUtil.readNextPair(br);
if (piar == null) {
break;
}
if ("ENDSEC".equals(piar[1].trim())) {
// header end, endsec is the end tag
break;
}
}
}
private void justOutput(StringBuffer writeBuffer) throws IOException {
System.out.println("part keep raw info");
while (true) {
String[] piar = StreamUtil.readNextPair(br);
if (piar == null) {
break;
}
StringUtil.appendLnCrLf(writeBuffer, piar);
if ("ENDSEC".equals(piar[1].trim())) {
// header end, endsec is the end tag
break;
}
}
}
private void handEntities(StringBuffer writeBuffer, boolean containNewEntity) throws IOException {
Map