2014-01-20 23 views
2

我希望能够绘制透镜元素的横截面。它们通常由1或2个圆形表面(正面和背面)和任意形状的边缘组成。出于我的目的,我只想绘制一条或两条线来连接正面和背面。如何用HTML5画布绘制镜头横截面?

这里就是我谈论的例子:

enter image description here

在这张图片中的每个元素是由两个[可能]有两个和六个之间直线圆弧连接它们。 (我并不担心画非球面镜片元素)。

我最初的想法是用合适的弧长绘制弧线,然后画线来连接它们。我担心这种做法是弧线和线条可能不匹配,并且由于精度错误可能会出现重叠或间隙。

有没有更好的方法来解决这个问题?我可以绘制包含直线和曲线边的多边形吗?

回答

2

一堆画圆的照片,做一些数学和睡在它之后,我想出了以下解决方案:

//draw the top and bottom edges of the lens  
ctx.beginPath(); 
ctx.moveTo(lens.x - (lens.thickness/2), lens.y - lens.radius); 
ctx.lineTo(lens.x + (lens.thickness/2), lens.y - lens.radius); 
ctx.moveTo(lens.x - (lens.thickness/2), lens.y + lens.radius); 
ctx.lineTo(lens.x + (lens.thickness/2), lens.y + lens.radius); 
ctx.stroke(); 


ctx.beginPath(); 
//draw the left face of the lens 
var lensToCircleRatio = lens.radius/lens.leftRadius; 
var xOffset = lens.leftRadius * Math.cos(Math.asin(lensToCircleRatio)) - (lens.thickness/2); //change the - to a + for a right-side concave face 
var arcStart = Math.PI - Math.asin(lensToCircleRatio); 
var arcEnd = Math.PI + Math.asin(lensToCircleRatio); 
ctx.arc(lens.x + xOffset, lens.y, lens.leftRadius, arcStart, arcEnd); 
ctx.stroke(); 


ctx.beginPath(); 
//draw the right face of the lens 
lensToCircleRatio = lens.radius/lens.rightRadius; 
xOffset = lens.rightRadius * Math.cos(Math.asin(lensToCircleRatio)) - (lens.thickness/2);  //change the - to a + for a left-side concave face 
arcStart = -1 * Math.asin(lensToCircleRatio); 
arcEnd = Math.asin(lensToCircleRatio); 
ctx.arc(lens.x - xOffset, lens.y, lens.rightRadius, arcStart, arcEnd); 
ctx.stroke(); 

这里有一个形象,真的类似于此代码完成: enter image description here

它根据它们各自的曲率半径计算出每个面的弧长,然后计算出这些弧的中心位置。然后绘制弧线和边缘以连接它们(如果需要的话)。我的代码为这个模型增加了什么,如果透镜的两个面都是凸面的,则额外的透镜厚度。幸运的是,即使经过多种不同的尺寸和镜头配置,我认为这种方法可能会出现的精度问题还没有出现。

下面是一个早期的测试(略有更新的代码绘制):

enter image description here