CAD图纸轻量化中圆的处理

2024-03-02 08:59

本文主要是介绍CAD图纸轻量化中圆的处理,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

CAD图纸在建筑行业及工业设计行业中被广泛使用,为了方便不同职能的人员也能方便的查看CAD图纸,就出现了CAD图纸轻量化方案的出现,轻量化后的图纸可直接在网页中查看,而不需要用户安装AutoCAD这样专业的软件。

进入正题,做过图纸轻量化的小伙伴都知道,通常我们会把dwg文件中的各种图形通过程序解析出来,生成一个中间文件,有的是json,有的是gltt,也有自己定义的,然后在网页端通过加载生成好的中间文件,再通过WebGL技术将这些图形重新绘制出来,就实现了让用户通过网页也能查看dwg图纸了。

当然如果确实不会软件编程的小伙伴,也可以直接使用AutoCAD插件,在网页端进行CAD图纸浏览和格式转换。

方案的核心三步如下图所示:

AutoCAD中常用到的图元类型如下:

解析圆通常有如下几种方案,每种方案的都会对比一下其优缺点。

方案一

解析时将圆形打断成很多条小线段,以32段为例来说,然后保存32个点坐标和这32个点的索引数组数据,在WebGL里再来绘制多段线。

坐标点 position: [p0,p1,p2,p3....p31]

每个点的坐标分别由x,y,z 三个float类型数值来表示,就得到坐标点的数组

[x0,y0,z0,x1,y1,z1,x2,y2,z2....x31,y31,z31]

就得到一个长度为96的一个单精度形数组。

索引数组 indices:[0,1,1,2,2,3,3,4,....30,31,31,0]

就得到一个长度为64的整形数组。

有了这两个数组,那么这个图形的描述数据就有了,现在还缺点啥呢?

没有错,形状有了,还没有颜色呢。由于一个圆形通常只有一种颜色,不会出现一个圆形上出现多种产色的情况,所以这里就用一个RGBA值来表示吧

颜色 color:[255,0,0,255]就有一个长度为4的int形数组表示吧。

细心的小伙伴可能发现,除了颜色还有线宽好像没有。对了这里再加一个线宽

线宽 width:1  就用一个整形来表示即可。

在绘制图形时还必须要有一个法向量,法向量是什么意思呢?简单理解就是告诉计算机,这个圆哪一面是正面哪一面是反面。

尽管此处圆形的正反面看上去都是一样的,但是在绘制三维图形的三角面时,这个法向量就至关重要了,因为一个面可能正面和反面的颜色不同,

要是搞反了可就不是我们要的效果了,好了,法向量概念在这里也不再发散了。

圆形的线型要讲来来就比较复杂,我们这里暂时不关心,统一当作实线来处理好了。

由上面的内容我们总结出来要正常描述这个圆形就得如下数据,我整理成一个json格式

{

"position":[x0,y0,z0,x1,y1,z1,x2,y2,z2,...x31,y31,z31],

"indices":[0,1,1,2,2,3,3,4,....30,31,31,0],

"color":[255,0,0,255],

"width":1

"normal":[] //

}

方案一优点

1.中心数据看上清晰易懂,容易扩展。

2.前端页面也方便解析,在绘制方面和多段线一样绘制,无需其他处理。

方案一缺点

1.生成的数据比较大,级数据的存储和网络传输带来压力。

2.生成的圆由于被打成了多条小线段,在放大圆时会发现这个圆不够圆。

方案二

上面的方案缺点太明显了,我们这个方案就针对它进行改良。

大家知道描述一个圆,其实只有一个圆心和一个半径即可,为什么要搞得那么麻烦将其打断成小线段呢?

所以这里我们说改变改。

圆心 center:[p0] 一个点即可表示,换成坐标数据得 [x0,y0,z0] 一个长度为3的单精度形数组。

半径radius:5.0 一个单精度数值即可表示。

颜色和线宽同上面的方案

颜色 color:[255,0,0,255]

线宽 width:1

此时我们可以得到图形的描述数据如下:

{

"type":"circle",  //这里必须指定该数据类型为圆,区别椭圆或弧形

"center":[x0,y0,z0],

"radius":5.0,

"color":[255,0,0,255],

"width":1

"normal":[] //

}

数据看上去比前一个小多了。但此时前端将要费点心思用圆心和半径将图形绘制出来,给个参考的Demo代码吧:

将下面代码直接保存为 index.html

<!DOCTYPE html>
<html>
<head>
<title>Draw a Circle with WebGL</title>
</head>
<body>
<canvas id="myCanvas" width="400px" height="400px"></canvas>
<script>
var canvas = document.getElementById('myCanvas');
var gl = canvas.getContext('webgl');
var vertexShaderSource = `
attribute vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
`;
var fragmentShaderSource = `
precision mediump float;
void main() {
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0);
}
`;
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
var vertices = [];
for (var i = 0; i <= 20; i++) {  //为了表现更明显一点,这里将圆切为20个小线段
var angle = i * Math.PI / 180;
var x = Math.cos(angle*360.0/20.0) * 0.5;
var y = Math.sin(angle*360.0/20.0) * 0.5;
vertices.push(x, y);
}
var positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
var positionAttributeLocation = gl.getAttribLocation(program, 'position');
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
gl.clearColor(0.9, 0.9, 0.9, 1.0);
gl.clear(gl.COLOR_BUFFER_BIT);
gl.drawArrays(gl.LINE_LOOP, 0, vertices.length / 2);
</script>
</body>
</html>

运行效果图:

方案二优点

1.中间数据格式看上清晰易懂,容易扩展。

2.生成的中间JSON数据大小明显要小很多。

方案二缺点

1.前端通过Javascrip将该圆生成了了多个小线段然后绘制,前端将消耗更多性能。

2.生成的圆任然是被打成了多条小线段,在放大圆时会发现这个圆不够圆。

该方案只解决了生成的中间数据文件过大的问题,看上去并没有完美的解决问题。

方案三

在上面的方案中存在的问题是前端通过javascrip来实现了将圆切分为多条拟合的小线段,然后再交由WebGL来生成圆形,javascrip的执行效率在小数据量时还能掌一下,当图形中有成千上万个圆时,通过javascrip来做这个动作将是一件糟糕的事情。

有没有一种办法可以高效的生成圆,且图形放大后看上去也很平滑呢?

当然有。

我们的思路是,不要让javascript去做消耗性能高的活,因为它消耗的是CPU的性能。那让谁呢?当然是我们的GPU啦!这里就引入GLSL语言,我们可以考虑让javascrip拿到圆的圆心和半径这些数据后,不做任务处理,直接传递给GLSL语言,然后在GLSL语言中来实现画圆,这样将运算转移到GPU.在GLSL中我们使用片源着色器,直接将圆形投影到屏幕上的像素绘制出来,就达到我们目的了。

下面是示例代码:

<!DOCTYPE html>
<html>
<head>
<title>Draw a Hollow Circle with WebGL an GLSL</title>
</head>
<body  onload="main()">
<canvas id="myCanvas" width="400px" height="400px">
abc
</canvas>
<script type="text/javascript">
var vertexShaderSource = `
attribute vec2 position;
void main() {
gl_Position = vec4(position, 0.0, 1.0);
}
`;
var fragmentShaderSource = `
precision mediump float;
void main() {
float radius = 0.5;
vec2 center = vec2(1, 1);
vec2 position = gl_FragCoord.xy / vec2(200.0, 200.0);
float dist = distance(center, position);
if (abs(dist - radius) < 0.01) { // 使用一个很小的阈值来绘制边界
gl_FragColor = vec4(1.0, 0.0, 0.0, 1.0); // 设置边界颜色
} else {
discard;
}
}
`;
function main(){
// Retrieve <canvas> element
var canvas = document.getElementById('myCanvas');
// Get the rendering context for WebGL
var gl = canvas.getContext('webgl');
if (!gl) {
console.log('Failed to get the rendering context for WebGL');
return;
}
var vertexShader = gl.createShader(gl.VERTEX_SHADER);
gl.shaderSource(vertexShader, vertexShaderSource);
gl.compileShader(vertexShader);
var fragmentShader = gl.createShader(gl.FRAGMENT_SHADER);
gl.shaderSource(fragmentShader, fragmentShaderSource);
gl.compileShader(fragmentShader);
var program = gl.createProgram();
gl.attachShader(program, vertexShader);
gl.attachShader(program, fragmentShader);
gl.linkProgram(program);
gl.useProgram(program);
var vertices = [-1, -1, -1, 1, 1, 1, 1, -1];
var positionBuffer = gl.createBuffer();
gl.bindBuffer(gl.ARRAY_BUFFER, positionBuffer);
gl.bufferData(gl.ARRAY_BUFFER, new Float32Array(vertices), gl.STATIC_DRAW);
var positionAttributeLocation = gl.getAttribLocation(program, 'position');
gl.enableVertexAttribArray(positionAttributeLocation);
gl.vertexAttribPointer(positionAttributeLocation, 2, gl.FLOAT, false, 0, 0);
// Specify the color for clearing <canvas>
gl.clearColor(0.9, 0.9, 0.9, 1);
// Clear <canvas>
gl.clear(gl.COLOR_BUFFER_BIT);
// Draw the rectangle
gl.drawArrays(gl.TRIANGLE_FAN, 0, vertices.length / 2);
}
</script>
</body>
</html>

运行效果如下:

嗯。这个圆看上去比上面那个要圆多了。

此时要用到的JSON和方案二一样如下所示:

{

"type":"circle",  //这里必须指定该数据类型为圆,区别椭圆或弧形

"center":[x0,y0,z0],

"radius":5.0,

"color":[255,0,0,255],

"width":1

"normal":[] //

}

我在考虑这个JSON有没有进一步压缩的可能性。

答案是肯定的。我们发现这些数据中,有用的数据都是数字,

如果我们将它转为一个数值类型的数组存储,然后将该数值型数组生成到一个二进制文件,那么相信文件大小会更小。

定义 :

圆的类型为:1      //  椭圆的类型为:2  等等...为我们要处理的图形定义类型

圆心:[x0,y0,z0]    //假如圆心为0点,则有 [0,0,0]

半径:5.0

颜色:[255,0,0,255]  由于在AutoCAD中并没有那么多种颜色,它使用的是索引色,就是将所有的RGB色提炼成我们肉眼容易区分的255种颜色,

分别用1到255数值表示,如纯白RGB为[255,255,255]对应的索引色就是 7,纯红色RGB为[255,0,0] 对应的索引色就是1  ,有人可能会问那RGB为[254,0,0]的红色对应的索引色是多少呢?答案是1,没有错,跟上面的红色一样,因为人的肉眼无法区分RGB[255,0,0]和RGB[254,0,0]两种红色的区别,所以在索引色中都归为了1 红色。

这里颜色就可以用一个整型数值来表示。

宽度:1 //用一位整型数值表示

法向量: 由于二维图纸的渲染,不比三维模型,这里可以固定法向量为由屏幕指向用户的眼睛。也不必在中间数据中保存了。

这时我们得到一个数组:

[1,x0,y0,z0,5,7,1,x1,y1,z1,5,7.....]

第一项的1表示为圆,接下来要读取后面5项的数据来获取该圆的相关参数。

第二项到第四项的 x0,y0,z0就分别表示该圆的圆心坐标点。

第五项表示圆的半径。

第六项表示圆的颜色。

后面同理。

替换为真实数据如下:

[1,0,0,0,5,7,1,1,1,1,5,7]

就表示的是两个半径为5颜色为红色的圆形。

如果该数组是float型数组,那么每一项占用4个字节,表示一个圆要6项,那么就占用6*4=24个字节,

如果再将这个24字节的文件再用zip压缩一下,大小通常会压缩成原来的1/3到1/5,这里取1/4吧。

那么表示一个圆的数据大小就是24*1/4=6字节。

没有错只要6个字节即将这个圆的图形数据传递能WegGL并正确的渲染出来。

我们来总结下该方案的优缺点。

方案三优点

1.中间数据被极致压缩,文件更小,占用空间及网络传输更有优势。

2.使用的WegGL的片源着色器绘制,图形更圆滑,放大也不会看到小线段。

3.绘图的动作全部交给GLSL语言来完成,消耗的是GPU资源,性能更好。

方案三缺点

1.对前端技术要求较高,使用了GLSL,开发门槛更高。

2.中间数据为二进制,不便查看阅读。

最后我想说的是,技术方案没有最好的,只有最适合我们的,我们应该根据项目的实际需求,自身团队技术结构合理选择技术方案。

如果您们后端dwg解析这块技术强,前端技术实力较弱,则方案一比较适合您。

如果你们前端技术实现强,那么方案三比较适合您。

这篇关于CAD图纸轻量化中圆的处理的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/765598

相关文章

电脑提示xlstat4.dll丢失怎么修复? xlstat4.dll文件丢失处理办法

《电脑提示xlstat4.dll丢失怎么修复?xlstat4.dll文件丢失处理办法》长时间使用电脑,大家多少都会遇到类似dll文件丢失的情况,不过,解决这一问题其实并不复杂,下面我们就来看看xls... 在Windows操作系统中,xlstat4.dll是一个重要的动态链接库文件,通常用于支持各种应用程序

SQL Server数据库死锁处理超详细攻略

《SQLServer数据库死锁处理超详细攻略》SQLServer作为主流数据库管理系统,在高并发场景下可能面临死锁问题,影响系统性能和稳定性,这篇文章主要给大家介绍了关于SQLServer数据库死... 目录一、引言二、查询 Sqlserver 中造成死锁的 SPID三、用内置函数查询执行信息1. sp_w

Java对异常的认识与异常的处理小结

《Java对异常的认识与异常的处理小结》Java程序在运行时可能出现的错误或非正常情况称为异常,下面给大家介绍Java对异常的认识与异常的处理,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参... 目录一、认识异常与异常类型。二、异常的处理三、总结 一、认识异常与异常类型。(1)简单定义-什么是

Golang 日志处理和正则处理的操作方法

《Golang日志处理和正则处理的操作方法》:本文主要介绍Golang日志处理和正则处理的操作方法,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考... 目录1、logx日志处理1.1、logx简介1.2、日志初始化与配置1.3、常用方法1.4、配合defer

springboot加载不到nacos配置中心的配置问题处理

《springboot加载不到nacos配置中心的配置问题处理》:本文主要介绍springboot加载不到nacos配置中心的配置问题处理,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录springboot加载不到nacos配置中心的配置两种可能Spring Boot 版本Nacos

python web 开发之Flask中间件与请求处理钩子的最佳实践

《pythonweb开发之Flask中间件与请求处理钩子的最佳实践》Flask作为轻量级Web框架,提供了灵活的请求处理机制,中间件和请求钩子允许开发者在请求处理的不同阶段插入自定义逻辑,实现诸如... 目录Flask中间件与请求处理钩子完全指南1. 引言2. 请求处理生命周期概述3. 请求钩子详解3.1

Python处理大量Excel文件的十个技巧分享

《Python处理大量Excel文件的十个技巧分享》每天被大量Excel文件折磨的你看过来!这是一份Python程序员整理的实用技巧,不说废话,直接上干货,文章通过代码示例讲解的非常详细,需要的朋友可... 目录一、批量读取多个Excel文件二、选择性读取工作表和列三、自动调整格式和样式四、智能数据清洗五、

SpringBoot如何对密码等敏感信息进行脱敏处理

《SpringBoot如何对密码等敏感信息进行脱敏处理》这篇文章主要为大家详细介绍了SpringBoot对密码等敏感信息进行脱敏处理的几个常用方法,文中的示例代码讲解详细,感兴趣的小伙伴可以了解下... 目录​1. 配置文件敏感信息脱敏​​2. 日志脱敏​​3. API响应脱敏​​4. 其他注意事项​​总结

Python使用python-docx实现自动化处理Word文档

《Python使用python-docx实现自动化处理Word文档》这篇文章主要为大家展示了Python如何通过代码实现段落样式复制,HTML表格转Word表格以及动态生成可定制化模板的功能,感兴趣的... 目录一、引言二、核心功能模块解析1. 段落样式与图片复制2. html表格转Word表格3. 模板生

Python Pandas高效处理Excel数据完整指南

《PythonPandas高效处理Excel数据完整指南》在数据驱动的时代,Excel仍是大量企业存储核心数据的工具,Python的Pandas库凭借其向量化计算、内存优化和丰富的数据处理接口,成为... 目录一、环境搭建与数据读取1.1 基础环境配置1.2 数据高效载入技巧二、数据清洗核心战术2.1 缺失