图纸中角度标注算法
两条非平行线段, 如何合理的标注角度。比方说对于下面2条初始线段:
根据当前鼠标所在位置的不同,我们可能得到如下不同的标注方式:
本人求标注的思路大体思路是:首先求出圆弧(Dimension Line)的两个端点, 然后根据这两个已求得的端点,分别计算出两条引线(Witness Line)的端点。
求圆弧端点的算法:
我们把问题简化下,对于任意2条相交的射线,以下均以锐角为例(钝角求解过程完全一致):
以2线段所在直线交点作为圆心, 鼠标位置到圆心的距离为半径,画一个圆,2条直线与圆必有4个交点,而Dimension Line的2个端点必然为这4个交点中的两个。
问题是我们如何从这4个交点中,选取其中的2个点作为Dimension Line的端点。
方法如下:我们把上面图中的红色实心向量和蓝色实心向量,作为2个参考向量,将图切分为如下4个象限:
然后根据当前的鼠标位置,决定出应该取那个象限, 做法是 记 value = (红色向量 X 橙色向量) . (橙色向量 X 蓝色向量)
如果得到的value值大于0,则当前鼠标必定落在一三象限,否则则在二四象限
接下来就是如何精确点位到鼠标是在一象限呢,还是在三象限。本人想到了用角度去推测,相信应该有更高效便捷的算法存在,只是目前自己没想到。
观察上图我们可以发现:假设当前鼠标在第三象限,那么橙色向量分别到两参考向量(红色实心向量和蓝色实心向量)的角度之和必然大于 180°,如果求得角度和小于180°就可断定为第一象限。(此方法钝角也依然适用,考虑下当前鼠标在上图二象限,以红色虚线向量以及蓝色实线向量作为参考向量)
算法实现如下,思路大体跟上面一致,仅做了点优化:
2 {
3 Point3d centerPoint = GetIntersectPoint(firstSeg3d, secondSeg3d);
4 double radius = thirdPt.DistanceTo(centerPoint);
5
6 Vector3d firstLineVec = (firstSeg3d.EndPoint - centerPoint).Normal();
7 Vector3d secondLineVec = (secondSeg3d.EndPoint - centerPoint).Normal();
8 Vector3d thirdLineVec = (thirdPt - centerPoint).Normal();
9
10 if ((firstLineVec.CrossProduct(thirdLineVec)).DotProduct(thirdLineVec.CrossProduct(secondLineVec)) < 0)
11 secondLineVec = -secondLineVec;
12
13 if ((thirdLineVec.AngleTo(firstLineVec) + thirdLineVec.AngleTo(secondLineVec)) > Math.PI)
14 {
15 firstLineVec = -firstLineVec;
16 secondLineVec = -secondLineVec;
17 }
18
19 firstCrossPt = centerPoint + firstLineVec * radius;
20 secondCrossPt = centerPoint + secondLineVec * radius;
21 }
22
求引线端点的算法:
Witness Line的2个端点为上述4个点中的两个,组合方式取决于绿色圈圈相对于其他3个点的位置,目前本人想到的方案不是很理想,看看明天能不能想到更方便简单的算法来描述,敬请等待明天的更新。
如果大家有更好的标注算法,请不吝指教!