本文主要对CAD文件解析后,若一份CAD文件中整个图有多个图形需要切割拆分,根据指定规则用独特颜色(内容中没有与其相同的颜色,确保不会因为颜色影响图形内容)的框将需要切割图形单独框起来,再做切割,切割后进行文件的大小缩放计算

直接上代码

一、图形计算相关代码

     * [检查一个path的点位是否在框内]* @author caiji* @param pathPoint  path点位* @param framePoint  矩形框的坐标点* @return boolean* @date 2022/4/21 17:21*/public static boolean checkIsInFrame(List<PointEntity> pathPoint, List<PointEntity> framePoint){boolean flag = false;//统一排序后的顺序为 左上,左下,右上,右下framePoint = framePoint.stream().sorted(Comparator.comparing(PointEntity::getPointX).thenComparing(PointEntity::getPointY)).collect(Collectors.toList());for (PointEntity path : pathPoint){//判断点位是否在框的四个点范围内//与左上点比较,x和y都应该大于对应的x,y//与左下点比较,x大于对应x,y小于对应y//与右上点比较,x小于对应x,y大于对应y//与右下点比较,x小于对应x,y小于对应yif((path.getPointX()>framePoint.get(0).getPointX() && path.getPointY()>framePoint.get(0).getPointY()) &&(path.getPointX()>framePoint.get(1).getPointX() && path.getPointY()<framePoint.get(1).getPointY()) &&(path.getPointX()<framePoint.get(2).getPointX() && path.getPointY()>framePoint.get(2).getPointY()) &&(path.getPointX()<framePoint.get(3).getPointX() && path.getPointY()<framePoint.get(3).getPointY())) {flag = true;}}return flag;}/*** [根据path的data数据 获取对应x、y点位]* @author caiji* @param path* @return java.util.List<com.example.importexceldemo.common.PointEntity>* @date 2022/4/21 17:45*/public static List<PointEntity> pathPointHandle(String path){List<PointEntity> result = new ArrayList<>();//切割MList<String> splitArray = Arrays.asList(path.split("M"));for (String o : splitArray) {if (!"".equals(o)) {//切割LList<String> pointArray = Arrays.asList(o.split("L"));for (int k = 0; k < pointArray.size(); k++) {String strItem = pointArray.get(k);//处理其他字母做结尾的坐标if (!Character.isDigit(strItem.substring(strItem.length() - 1).charAt(0))) {strItem = strItem.substring(0, strItem.length() - 1);}//0为x  1为yPointEntity pointEntity = new PointEntity();pointEntity.setPointX(Double.parseDouble(strItem.split(" ")[0]));pointEntity.setPointY(Double.parseDouble(strItem.split(" ")[1]));result.add(pointEntity);}}}return result;}/*** [获取图框的数量(根据颜色),以及点位]* 思路:按照一个矩形框有四条path属性计算,并且矩形的点位仅四个* @author caiji* @param node* @param framePoint* @return void* @date 2022/4/25 18:05*/public static void getFrameCount(final Node node,List<PointEntity> framePoint){for (int i = 0;i<node.getChildNodes().getLength();i++) {// 遍历所有一级子节点NamedNodeMap map = node.getChildNodes().item(i).getAttributes();if(null != map){if(map.getNamedItem("stroke") != null && map.getNamedItem("stroke").getNodeValue().equals("#0000FF")) {//如果为特定颜色,则为指定的矩形框//取当前data数据,并且取第一个点,因为是矩形,所以存在点位重合,只需要取第一个点即可String point = map.getNamedItem("d").getNodeValue();PointEntity pointEntity = new PointEntity();//取第一个点String firstPoint = point.substring(point.indexOf("M")+1,point.indexOf("L"));pointEntity.setPointX(Double.parseDouble(firstPoint.split(" ")[0]));pointEntity.setPointY(Double.parseDouble(firstPoint.split(" ")[1]));framePoint.add(pointEntity);}}getFrameCount(node.getChildNodes().item(i),framePoint);// 递归}}/*** [根据图框数量生成新的DOM格式字符串 -- 即SVG   (前提:CAD解析后并计算绝对坐标点位后再做这些处理)]* 思路:传入整个图的node,然后根据计算是否在框内范围将数据存入新的node* @author songxy* @param node* @param framePoint* @param newDoc* @return void* @date 2022/4/25 18:05*/public static void generateNewDomByFrame(final Node node,List<PointEntity> framePoint,Node newDoc){for (int i = 0;i<node.getChildNodes().getLength();i++) {// 遍历所有一级子节点NamedNodeMap map = node.getChildNodes().item(i).getAttributes();if(null != map && null != map.getNamedItem("d")){String data = map.getNamedItem("d").getNodeValue();List<PointEntity> dataPoint = pathPointHandle(data);//取到本次path的data点位,并与框的点位比较,如果在范围内则保存boolean flag = checkIsInFrame(dataPoint,framePoint);if(flag){Node newChild = node.getChildNodes().item(i).cloneNode(false);newDoc.appendChild(newChild);}}generateNewDomByFrame(node.getChildNodes().item(i),framePoint,newDoc);// 递归}}/*** [处理文件切割后的尺寸计算]* 思路:CAD解析时存在大样图实际尺寸较大(几万+),所以解析时设置固定尺寸后,文件中的图也会相应压缩,切割后可能要处理显示上存在的位置以及尺寸问题* @author songxy* @param node* @return void* @date 2022/4/26 09:54*/public static void handleDomSize(Node node){List<String> list = new ArrayList<>();List<Double> pointListX = new ArrayList<>();List<Double> pointListY = new ArrayList<>();getCadSizeData(node,list,pointListX,pointListY);Map<String,Double> map = calculationCadSize(pointListX,pointListY);Double x = map.get("width");Double y = map.get("height");Double minXnum = map.get("minXnum");Double minYnum = map.get("minYnum");//根据最大最小坐标值计算内容的高宽值//因为svg中y轴越往上越小,所以用高度相减//设置初始点位10,10 计算相对坐标值,不设置为0,0 留一点边距Double initX = 10d;Double initY = 10d;Double offsetX = minXnum - initX;Double offsetY = minYnum - initY;handleNodeForOffsetPoint(node,offsetX,offsetY);x = x+initX*2;y = y+initY*2;String viewBox = "0 0 "+x+" "+y;Node attr = node.getOwnerDocument().createAttribute("viewBox");attr.setNodeValue(viewBox);node.getAttributes().setNamedItem(attr);}/*** [将所有的框的点位平分,得出有几个框就有几个图]* 注意:此处必须是绘制的框是一次性绘制的,不能有框绘制到一半绘制另一个框的情况* @author songxy* @param pointEntities* @return java.util.List<java.util.List<com.example.importexceldemo.common.PointEntity>>* @date 2022/4/22 14:10*/public static List<List<PointEntity>> averagePoint(List<PointEntity> pointEntities){List<List<PointEntity>> result = new ArrayList<>();//框的数量,也是图的数量、需要将pointEntities平分的份数int frameCount = pointEntities.size()/4;//余数int remainder = pointEntities.size()%frameCount;//商int number = pointEntities.size()/frameCount;int offset = 0;for (int i = 0;i<frameCount;i++){List<PointEntity> item = new ArrayList<>();if(remainder > 0){item = pointEntities.subList(i*number+offset,(i+1)*number+offset+1);remainder--;offset++;}else{item = pointEntities.subList(i*number+offset,(i+1)*number+offset);}result.add(item);}return result;}/*** 获取图形宽高尺寸* @author songxy* @param node* @return java.util.Map<java.lang.String,java.lang.Double>* @date 2021/11/5 20:33*/public static void getCadSizeData(Node node, List<String> list,List<Double> pointListX,List<Double> pointListY){for (int i = 0;i<node.getChildNodes().getLength();i++){NamedNodeMap map = node.getChildNodes().item(i).getAttributes();if(null != map && map.getNamedItem("d") != null){list.add(map.getNamedItem("d").getNodeValue());String data = map.getNamedItem("d").getNodeValue().replace("[","").replace("]","");//切割MList<String> splitArray = Arrays.asList(data.split("M"));for (String o : splitArray){if(!"".equals(o)) {//切割LList<String> pointArray = Arrays.asList(o.split("L"));for (int k = 0; k < pointArray.size(); k++) {String strItem = pointArray.get(k);//处理其他字母做结尾的坐标if(!Character.isDigit(strItem.substring(strItem.length()-1).charAt(0))){strItem = strItem.substring(0,strItem.length()-1);}//0为x  1为yDouble numX = Double.parseDouble(strItem.split(" ")[0]);Double numY = Double.parseDouble(strItem.split(" ")[1]);pointListX.add(numX);pointListY.add(numY);}}}}getCadSizeData(node.getChildNodes().item(i),list,pointListX,pointListY);}}/*** 计算图形高宽* @author songxy* @param pointListX* @param pointListY* @return java.util.Map<java.lang.String,java.lang.Double>* @date 2021/11/6 12:55*/public static Map<String,Double> calculationCadSize(List<Double> pointListX, List<Double> pointListY){Double maxXnum = Double.parseDouble(Collections.max(pointListX).toString());Double minXnum = Double.parseDouble(Collections.min(pointListX).toString());Double maxYnum = Double.parseDouble(Collections.max(pointListY).toString());Double minYnum = Double.parseDouble(Collections.min(pointListY).toString());//根据最大最小坐标值计算内容的高宽值Double x = maxXnum-minXnum;Double y = maxYnum-minYnum;Map<String,Double> map = new HashMap<>();map.put("width",x);map.put("height",y);map.put("minXnum",minXnum);map.put("minYnum",minYnum);return map;}/*** 按公式计算d属性里面的坐标并且重新按偏移量计算赋值* @author songxy* @param node* @param offsetX* @param offsetY* @return void* @date 2021/11/4 10:18*/public static void handleNodeForOffsetPoint(Node node, Double offsetX,Double offsetY){for (int i = 0;i<node.getChildNodes().getLength();i++){if(node.getChildNodes().item(i).hasAttributes() && node.getChildNodes().item(i).getAttributes().getNamedItem("d") != null){String data = node.getChildNodes().item(i).getAttributes().getNamedItem("d").getNodeValue().replace("[","").replace("]","");//切割MList<String> splitArray = Arrays.asList(data.split("M"));StringBuffer newData = new StringBuffer();for (String o : splitArray){if(!"".equals(o)) {//切割LList<String> pointArray = Arrays.asList(o.split("L"));for (int k = 0; k < pointArray.size(); k++) {String lastChar = "";String strItem = pointArray.get(k);if(!Character.isDigit(strItem.substring(strItem.length()-1).charAt(0))){lastChar = strItem.substring(strItem.length()-1);strItem = strItem.substring(0,strItem.length()-1);}//0为x  1为yDouble numX = Double.parseDouble(strItem.split(" ")[0]);Double numY = Double.parseDouble(strItem.split(" ")[1]);//根据偏移量计算新点位Double newX = numX-offsetX;Double newY = numY-offsetY;//拼接d属性值的新坐标if (k == 0) {newData.append("M");newData.append(newX);newData.append(" ");newData.append(newY);}else{newData.append("L");newData.append(newX);newData.append(" ");newData.append(newY);newData.append(lastChar);}}}}node.getChildNodes().item(i).getAttributes().getNamedItem("d").setNodeValue(newData.toString());}handleNodeForOffsetPoint(node.getChildNodes().item(i),offsetX,offsetY);}}/*** 将element转换成XML字符串* @param element* @return*/public static String convertElemToSVG(Node element) {TransformerFactory transFactory = TransformerFactory.newInstance();Transformer transformer = null;try {transformer = transFactory.newTransformer();} catch (TransformerConfigurationException e) {e.printStackTrace();}StringWriter buffer = new StringWriter();transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes");try {transformer.transform(new DOMSource(element), new StreamResult(buffer));} catch (TransformerException e) {e.printStackTrace();}String elementStr = buffer.toString();return elementStr;}

二、测试代码 万年main方法调试

    public static void main(String[] args) {String svgFilePath = "/CAD文件/04253.svg";try {File file = new File(svgFilePath);String parser = XMLResourceDescriptor.getXMLParserClassName();SAXSVGDocumentFactory f = new SAXSVGDocumentFactory(parser);Document doc = f.createDocument(file.toURI().toString());List<PointEntity> pointEntities = new ArrayList<>();//获取所有特定框的点位getFrameCount(doc.getDocumentElement(),pointEntities);//处理点位数据,得到有多少个框,即多少个图形和图形的框的四个点位List<List<PointEntity>> frameList = averagePoint(pointEntities);//根据框数将图形全部生成新的文件for (int i = 1;i<=frameList.size();i++){Node newDoc = doc.getDocumentElement().cloneNode(false);//生成新的domgenerateNewDomByFrame(doc.getDocumentElement(),frameList.get(i-1),newDoc);//切割后图形所在的位置不会变更,所以需要处理dom尺寸handleDomSize(newDoc);String str = convertElemToSVG(newDoc);OutputStream outputStream = new FileOutputStream("/CAD文件/0455"+i+".svg");OutputStreamWriter os = new OutputStreamWriter(outputStream,"utf-8");os.write(str);os.close();}}catch (Exception e){e.printStackTrace();}}

CAD文件解析后按照特定规则将图形切割相关推荐

  1. CAD文件解析(DWG to SVG)

    之前有过一个需求,需要将CAD的DWG文件转成SVG,再对图形做处理,简单写了dwg转成svg的解析,后续补充对解析后对的svg图形处理(如:图形位置调整.图形绝对坐标计算等),处理svg文件的计算需 ...

  2. 计算机无法打开cad文件,无法打开cad文件的解决方法

    从一台电脑做好cad图,拷贝到另一台电脑进行操作,但是却打开不了?原因是两台电脑的cad版本不一样,而你保存的cad文件版本是高版本的,低版本的cad软件自然就打不开高版本的cad文件了.无法打开ca ...

  3. CAD打不开服务器里的文件,电脑上cad文件打不开怎么解决

    我们使用cad制作图形文件,却发现打不开了是不是有点崩溃?下面由学习啦小编为大家整理了电脑上cad文件打不开怎么解决的相关方法,希望对大家有帮助! 电脑上cad文件打不开的解决方法和步骤如下 cad图 ...

  4. 计算机无法打开cad文件,电脑打不开cad文件怎么办

    从一台电脑做好cad图,拷贝到另一台电脑进行操作,但是却打开不了怎么办?下面是学习啦小编给大家整理的一些有关电脑打不开cad文件的解决方法,希望对大家有帮助! 电脑打不开cad文件的解决方法 1.有时 ...

  5. 批量打印CAD文件怎么做?来试试这种方法

    我们怎么把CAD文件批量打印出来呢?从事CAD相关工作的小伙伴,在大家的日常工作中,我们绘制好的图纸经常需要打印出来,通过对照图纸来方便施工工作.当我们遇到有多张图纸需要打印,而我们不想一个个打印浪费 ...

  6. 解析完CAD安装包后,如何添加语言?手把手教你~

    2021年,AutoCAD新增了中文支持,这对于外语不好的小伙伴可谓是久旱逢甘霖.由于语音包需要手动安装,很多小伙伴在解析完CAD安装包后对此是束手无策.今天就教你如何下载适用自己的语言产品并管理语言 ...

  7. CAD中的dxf文件解析(二):dxflib的使用

    1.前言 上一篇中对dxf文件及文件中常见的需要解析的直线,圆,圆弧,椭圆,多段线的说明,对dxf文件有了初步的了解,并做好了下载dxflib,dxf帮助文档的准备(没有准备的可以回到上一篇). CA ...

  8. CAD中的dxf文件解析(三):多段线篇

    1.前言 在前面的CAD中的dxf文件解析(二)中讲到了一些CAD的dxf文件解析点.线.圆弧.圆.块等的思路.下面提供链接: (二): CAD中的dxf文件解析(二):dxflib的使用_不爱学习 ...

  9. 本地Host文件解析域名后访问阿里云服务器, 结果请求被拦截, 提示备案问题的解决方式

    文章目录 起因 查找原因 历程 明明是通过本地host文件解析域名为ip地址, 为神马服务器还是知道我访问的域名呢 最终解决方式 起因 上周腾讯云服务器使用时间到期了, 于是就想再换成阿里云服务器试试 ...

最新文章

  1. jquery格式化时间
  2. 快速排序实现以及时间复杂度分析
  3. Spring中ApplicationContextAware的用法
  4. 【原创】最值得推荐wince应用和wince驱动入门书籍
  5. 看看虚函数表是什么样的
  6. [CF920G]List Of Integers
  7. OSPF在企业网络中的应用
  8. 基于Maven的S2SH(Struts2+Spring+Hibernate)框架搭建
  9. python遗传算法(详解)
  10. 打造一款CPS返佣小程序之创建淘宝联盟账号及获取饿了么佣金路径《二》
  11. HONOR荣耀50/荣耀50Pro怎么解锁huawei 荣耀50pro屏幕锁开机锁激活设备锁了应该如何强制解除鸿蒙系统刷机解锁方法流程步骤不开机跳过锁屏移除锁定进系统方法经验
  12. WPS如何按单元格背景颜色求和
  13. Mac 下pyppeteer下载Chromium慢 / pyppeteer下载慢 / Chromium下载慢 / Chromium下载地址
  14. 2018-04-24-c-gluttonous-snake 财务同比环比、SSH和SSM
  15. matlab canon,Canonical state-space realization
  16. jacob实现ppt转图片时存在的问题
  17. 设计模式之路 | 建造者模式
  18. android opengl ppt,Opengl example.ppt
  19. 最新快速提升网站关键词排名方法,附案例
  20. 租用稳定的网通服务器,网通租用服务器

热门文章

  1. Verilog实现4-bit行波进位加法器和超前进位加法器
  2. 计算机一级wpsoffice知识点,2016年计算机一级《WPS Office》考试大纲
  3. 三星android 8.0的变化,三星发布最新android 8.0升级计划 最快11月部分升级
  4. MIT 6.002电路与电子学笔记
  5. VS2015平面四杆机构运动仿真编程
  6. Adobe Premiere Pro 2023导入音乐没有声音,并且提示“MME设备内部错误”
  7. 2022新版版IDEA创建Web项目
  8. 基于jsp+ssm的网上图书商城
  9. 学生成绩管理系统数据库
  10. 主流数据库实时同步/实时ETL工具的比较