cad文件解析成svg文件后,若需要对svg文件在页面结合前端技术konva.js上进行绘制或编辑操作时,需要在已有svg文件基础上进行图形的点位换算等操作,将SVG代码格式化成DOM形式,本文章主要对于svg的一些规定格式进行计算与操作,若不符合规则即无法有效计算。

说明:本文主要对svg中的矩阵函数(matrix)进行点位计算,计算后文件代码中不含函数部分,所有点位均为绝对点位的值

matrix函数公式

一、对SVG文件内图形的计算处理

    /*** 提取transform(函数)和d(点位)属性的值,用于公式计算* @author caiji* @param node* @param list  //点位属性* @param transform  //函数属性* @return void* @date 2021/11/4 10:19*/public static void handleFileNode(Node node, List<String> list, List<String> transform){for (int i = 0;i<node.getChildNodes().getLength();i++){NamedNodeMap map = node.getChildNodes().item(i).getAttributes();if(null != map){if(map.getNamedItem("d") != null){list.add(map.getNamedItem("d").getNodeValue());}if(map.getNamedItem("transform") != null){transform.add(map.getNamedItem("transform").getNodeValue().substring(map.getNamedItem("transform").getNodeValue().indexOf("(")+1,map.getNamedItem("transform").getNodeValue().lastIndexOf(")")));}}handleFileNode(node.getChildNodes().item(i),list,transform);}}/*** 处理transform中matrix矩阵函数的公式参数值* @author caiji* @param transformAttribute matrix函数值* @return java.util.List<java.lang.Double>* @date 2021/11/4 13:50*/public static List<Double> getTransformItem(String transformAttribute){List<String> strings = Arrays.asList(transformAttribute.split(" "));List<Double> pointItems = new ArrayList<>();Double a = 0d;Double b = 0d;Double c = 0d;Double d = 0d;Double e = 0d;Double f = 0d;for (int i = 0 ; i< strings.size();i++){switch (i){case 0:a = Double.parseDouble(strings.get(i));pointItems.add(a);break;case 1:b = Double.parseDouble(strings.get(i));pointItems.add(b);break;case 2:c = Double.parseDouble(strings.get(i));pointItems.add(c);break;case 3:d = Double.parseDouble(strings.get(i));pointItems.add(d);break;case 4:e = Double.parseDouble(strings.get(i));pointItems.add(e);break;case 5:f = Double.parseDouble(strings.get(i));pointItems.add(f);break;default:break;}}return pointItems;}/*** 按公式计算d属性里面的坐标并且重新赋值* @author caiji* @param node* @param pointItem 矩阵函数matrix的公式参数* @return void* @date 2021/11/4 10:18*/public static void handleNodeForNewPoint(Node node, List<Double> pointItem,List<Double> pointListX,List<Double> pointListY){for (int i = 0;i<node.getChildNodes().getLength();i++){if(node.getChildNodes().item(i).hasAttributes()){//text标签的点位值计算if("text".equals(node.getChildNodes().item(i).getNodeName())){if(node.getChildNodes().item(i).getAttributes().getNamedItem("x") != null && node.getChildNodes().item(i).getAttributes().getNamedItem("y") != null){List<Double> textPointItem = getTransformItem(node.getChildNodes().item(i).getAttributes().getNamedItem("transform").getNodeValue().substring(node.getChildNodes().item(i).getAttributes().getNamedItem("transform").getNodeValue().indexOf("(")+1,node.getChildNodes().item(i).getAttributes().getNamedItem("transform").getNodeValue().lastIndexOf(")")));Double tx = Double.parseDouble(node.getChildNodes().item(i).getAttributes().getNamedItem("x").getNodeValue());Double ty = Double.parseDouble(node.getChildNodes().item(i).getAttributes().getNamedItem("y").getNodeValue());Double newX = textPointItem.get(0)*tx+ty*textPointItem.get(2)+textPointItem.get(4);Double newY = tx*textPointItem.get(1)+ty*textPointItem.get(3)+textPointItem.get(5);Double newXs = pointItem.get(0)*newX+newY*pointItem.get(2)+pointItem.get(4);Double newYs = newX*pointItem.get(1)+newY*pointItem.get(3)+pointItem.get(5);node.getChildNodes().item(i).getAttributes().getNamedItem("x").setNodeValue(newXs.toString());node.getChildNodes().item(i).getAttributes().getNamedItem("y").setNodeValue(newYs.toString());pointListX.add(newXs);pointListY.add(newYs);}}//d属性的点位值计算if(node.getChildNodes().item(i).getAttributes().getNamedItem("d") != null){String data = node.getChildNodes().item(i).getAttributes().getNamedItem("d").getNodeValue();data.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]);//通过transform中的公式算出正确x,y点位Double newX = pointItem.get(0)*numX+numY*pointItem.get(2)+pointItem.get(4);Double newY = numX*pointItem.get(1)+numY*pointItem.get(3)+pointItem.get(5);pointListX.add(newX);pointListY.add(newY);//拼接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());}//将transform属性设置为空if(node.getChildNodes().item(i).getAttributes().getNamedItem("transform") != null){node.getChildNodes().item(i).getAttributes().getNamedItem("transform").setNodeValue("");}}handleNodeForNewPoint(node.getChildNodes().item(i),pointItem,pointListX,pointListY);}}/*** 按公式计算d属性里面的坐标并且重新按偏移量计算赋值* @author caiji* @param node* @param offsetX* @param offsetY* @return void* @date 2021/11/4 10:18*/public static void handleNodeForOffsetPoint(Node node, Double offsetX,Double offsetY,Double scale){for (int i = 0;i<node.getChildNodes().getLength();i++){if(node.getChildNodes().item(i).hasAttributes()){//text标签点位值计算if("text".equals(node.getChildNodes().item(i).getNodeName())){if(node.getChildNodes().item(i).getAttributes().getNamedItem("x") != null && node.getChildNodes().item(i).getAttributes().getNamedItem("y") != null){Double tx = Double.parseDouble(node.getChildNodes().item(i).getAttributes().getNamedItem("x").getNodeValue());Double ty = Double.parseDouble(node.getChildNodes().item(i).getAttributes().getNamedItem("y").getNodeValue());Double newX = tx-offsetX;Double newY = ty-offsetY;node.getChildNodes().item(i).getAttributes().getNamedItem("x").setNodeValue(newX.toString());node.getChildNodes().item(i).getAttributes().getNamedItem("y").setNodeValue(newY.toString());}}//data点位值计算if(node.getChildNodes().item(i).getAttributes().getNamedItem("d") != null){String data = node.getChildNodes().item(i).getAttributes().getNamedItem("d").getNodeValue();data.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,scale);}}

二、处理文件调试

    public static void main(String[] args) {try {String pdfFilePath = "/Users/Desktop/图形计算1.svg";String imgPath = "/Users/Desktop/图形计算2.svg";File file = new File(pdfFilePath);//svg文件内容转换成xml格式String parser = XMLResourceDescriptor.getXMLParserClassName();SAXSVGDocumentFactory fs = new SAXSVGDocumentFactory(parser);Document document =  fs.createDocument(file.toURI().toString());List<String> fileData = new ArrayList<>();List<String> transformData = new ArrayList<>();//svg的高宽值Double svgWidth = Double.parseDouble(document.getDocumentElement().getAttribute("width"));Double svgHeight = Double.parseDouble(document.getDocumentElement().getAttribute("height"));//获取内容中data属性的值handleFileNode(document.getDocumentElement(),fileData,transformData);//单个transformDataList<Double> pointItems = getTransformItem(transformData.get(0));List<Double> pointListX = new ArrayList<>();List<Double> pointListY = new ArrayList<>();//根据data数据获取所有的坐标数据分x,y两个集合存储handleNodeForNewPoint(document.getDocumentElement(), pointItems,pointListX,pointListY);//取图形的最大最小的x、y点位,计算图形高宽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;//计算大约在中间的图形最左上角点位(x轴点位为svg宽度/2-图形宽度/2;y轴点位为svg高度/2-图形高度/2)//因为svg中y轴越往上越小,所以用高度相减   不设置为0,0 留一点编距   按需调整Double initX = 5d;Double initY = 5d;Double offsetX = minXnum - initX;Double offsetY = minYnum - initY;Double ratio = svgHeight>svgWidth?svgHeight:svgWidth;Double scale = ratio/x;//根据偏移量重新计算所有点位handleNodeForOffsetPoint(document.getDocumentElement(),offsetX,offsetY,scale);String viewBox = "0 0 "+(x+initX*2)+" "+(y+initX*2);document.getDocumentElement().setAttribute("viewBox",viewBox);//dom节点转字符串,重新生成svg文件String str = convertElemToSVG(document.getDocumentElement());OutputStream outputStream = new FileOutputStream(imgPath);OutputStreamWriter os = new OutputStreamWriter(outputStream,"utf-8");os.write(str);os.close();}catch (Exception e){e.printStackTrace();}}/*** 将dom对象转换成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;}

ps:希望这篇文章可以对你提供思路或减少困惑,如果计算存在问题或文章存在问题欢迎大佬指点,对于之前只看不写的人,如果文章内容出入比较大还望包涵!!

svg图形计算、矩阵函数计算、图形点位绝对坐标计算相关推荐

  1. python的计算_python 计算方位角实例(根据两点的坐标计算)

    知道两点坐标,怎么计算两点方向的方位角? 答:首先计算坐标增量dx,dy(两个对应坐标分量相减,终点的减始点的). 若dx,dy中有一个为零时,根据另一个的正负决定方位角(0,90,180,270这四 ...

  2. python计算两点间距离_python 计算方位角实例(根据两点的坐标计算)

    知道两点坐标,怎么计算两点方向的方位角? 答:首先计算坐标增量dx,dy(两个对应坐标分量相减,终点的减始点的). 若dx,dy中有一个为零时,根据另一个的正负决定方位角(0,90,180,270这四 ...

  3. 用python计算两点坐标_python 计算方位角实例(根据两点的坐标计算)

    知道两点坐标,怎么计算两点方向的方位角? 答:首先计算坐标增量dx,dy(两个对应坐标分量相减,终点的减始点的). 若dx,dy中有一个为零时,根据另一个的正负决定方位角(0,90,180,270这四 ...

  4. 【Unity】U3D TD游戏制作实例(四)建造防御塔:防御塔生成器、一个int代表多选框,圆上任意点位的坐标计算、制作防御塔预制件

    文章目录 本章内容介绍 制作生成器 生成器Hierarchy 高亮显示生成器 制作箭塔菜单 将创建菜单对齐到选中的生成器 动态生成按钮 动态计算按钮坐标 制作预制件 最终运行效果 本章内容介绍 由于目 ...

  5. python 计算方位角(根据两点的坐标计算)

    知道两点坐标,怎么计算两点方向的方位角? 答:首先计算坐标增量dx,dy(两个对应坐标分量相减,终点的减始点的). 若dx,dy中有一个为零时,根据另一个的正负决定方位角(0,90,180,270这四 ...

  6. matlab找三角网,基于MATLAB的三角网交会点坐标计算的程序设计

    内容简介: 毕业论文 基于MATLAB的三角网交会点坐标计算的程序设计,共36页,14997字. 摘 要:Matlab语言具备高效.可视化及推理能力强等特点,是目前工程界流行最广的科学计算语言,而就测 ...

  7. python计算方位角_实例讲解:用python 计算方位角(根据两点的坐标计算)记得收藏哦...

    今天为大家分享一篇python 计算方位角实例(根据两点的坐标计算),具有很好的参考价值,希望对大家有所帮助.一起来看看吧! 知道两点坐标,怎么计算两点方向的方位角? 答:首先计算坐标增量dx,dy( ...

  8. 528_计算圆弧上某一点的坐标

    计算圆弧上某一点的坐标 计算出x坐标和y坐标 private float getXCoordinate(int angle, double r) {         angle = angle - 3 ...

  9. 数模【Mathematica(安装、入门方法、基本计算、基本图形、创建互动模型、利用数据、幻灯片演示、完整实例)】

    Mathematica 官方中文入门教程 视频中的".nb"文件[链接:https://pan.baidu.com/s/1mpzhfG5igUFGdB1NrGG3SQ   提取码: ...

最新文章

  1. C语言的一个关键字——static
  2. 微软企业库4.1学习笔记(八)创建对象 续集2
  3. 如何在python中显示电脑中的图片-python如何实现多个图片显示在屏幕上?
  4. 教你怎么快速配置 React
  5. python最难学的是什么_python是最难学的语言吗
  6. 记忆化搜素,和递推法
  7. 程序员们请别做下一个小贝
  8. C++实现线段树求区间和-区间查询
  9. java开发技术有什么意义,零基础学Java开发技术有哪些优势和好处?
  10. 1-物联网开发标配方案(预期方案使用说明和演示)
  11. Z-BlogPHP导航主题模版源码 绿色完美版
  12. windows 2003内存设置
  13. Atitit 研发团队建设----福利法案--非物质福利与物质福利法案
  14. 互联网产品经理,全方位入门,图书推荐
  15. nginx反向代理打印日志_Nginx 反向代理 log 显示真IP地址
  16. 手牵手系列之TypeScript开发环境搭建
  17. 小程序获取用户头像大图 小程序获取用户头像模糊的问题 小程序自定义转发头像模糊 小程序自定义转发分享大图...
  18. 初涉VB.NET入门级代码积累
  19. qla2xxx 0000:04:00.0: scsi(1:0:2): Abort command issued -- 1 1b22e 2002.
  20. gsoc 任务_我在GSoC'20中进行编码的第三周

热门文章

  1. 阿里云天池大赛赛题(机器学习)——O2O优惠券预测(完整代码)
  2. 基于Java+Swing实现天气预报系统
  3. python画rgb渐变色_请问如何在matplotlib中画出自定义渐变色?
  4. (LI论文)LIO-SAM: Tightly-coupled Lidar Inertial Odometry via Smoothing and Mapping
  5. 自学Java有什么好方法?
  6. API接口名称(item_get - 根据ID取商品详情)[item_search,item_get,item_search_shop等]
  7. IOS 将文字写绘制成图片并转换为像素数据
  8. 两款简单的拒绝服务攻击工具
  9. 多个乘法 用计算机什么符号,电脑乘法符号怎么打
  10. Holder不等式 Minkowski不等式