2021SC@SDUSC山东大学软件学院软件工程应用与实践--quark renderer代码分析 第九篇 几何系统分析(2):线几何对象类(geoline)

本文详细介绍了JavaScript中的线几何对象类GeoLine,该类用于表示两点之间的线段,来源于diagramo的改进。线段不可见且无宽度,主要用于几何运算。文章讨论了如何从JSON创建线对象,以及如何判断一个点是否在线段上,包括垂直线和普通线的情况。此外,还涵盖了计算点到线段距离的方法,涉及平面解析几何的知识。最后,提到了获取线段上特定位置点的坐标功能。
摘要由CSDN通过智能技术生成

2021SC@SDUSC

今天继续来看几何部分的另一个重要组件,线几何对象类(geoine),这个也是从 diagramo中的同类改进而来(链接:Flowchart software | Diagram software | Flowchart diagram),这个类中的线是何学意义上的直线,它不可见,没有宽度,用来进行数学运算。实际上在封装中,这个类是在上一期的点类的前面的,但为了便于理解先对点进行了分析。

var GeoLine = /*#__PURE__*/function () {
  function GeoLine(startPoint, endPoint) {
    _classCallCheck(this, GeoLine);

    this.startPoint = startPoint;
    this.endPoint = endPoint;
  }

首先是从JSON 对象创建直线。每个直线包含两个值,也就是两点确定一条线的两个点:起始点(startpoint)和终点(endpoint)。可以看出来这里的直线不是数学意义上的无线延长直线,而是线段。

function contains(x, y) {
      if (mathMin(this.startPoint.x, this.endPoint.x) <= x && x <= mathMax(this.startPoint.x, this.endPoint.x) && mathMin(this.startPoint.y, this.endPoint.y) <= y && y <= mathMax(this.startPoint.y, this.endPoint.y)) {
               if (this.startPoint.x == this.endPoint.x) {
          return x == this.startPoint.x;
        } else {
          // 通常(非垂直)线可以表示为y=a*x+b
          var a = (this.endPoint.y - this.startPoint.y) / (this.endPoint.x - this.startPoint.x);
          var b = this.startPoint.y - a * this.startPoint.x;
          return y == a * x + b;
        }
      } else {
        return false;
      }
    }

然后就是测试某个点是否位于直线上的函数(再次强调,这里不是数学意义上的无线延长直线,而是线段)。利用的计算方法:计算斜率,看(x,y)点是否位于线段上。

if (mathMin(this.startPoint.x, this.endPoint.x) <= x && x <= mathMax(this.startPoint.x, this.endPoint.x) && mathMin(this.startPoint.y, this.endPoint.y) <= y && y <= mathMax(this.startPoint.y, this.endPoint.y))

首先是判断点是否位于线段的矩形边界内,如果超出了以线段为对角线的矩形的话,点必不可能在线段上。

        if (this.startPoint.x == this.endPoint.x) {
          return x == this.startPoint.x;
        }

然后检查垂直线段,如果点在垂直线上则不在线上(不考虑焦点)。

然后就是利用平面解析几何中的公式。直线方程的一般式为:ax+by+c=0 ,在平面直角坐标系中,我们知道任意两个点的坐标就可求出经过这两个点的直线方程,即:

a=y2-y1
b=x1-x2//注意别写反了
c=-ax1+by1

代码如下

 var a = (this.endPoint.y - this.startPoint.y) / (this.endPoint.x - this.startPoint.x);
          var b = this.startPoint.y - a * this.startPoint.x;
          return y == a * x + b;

利用点的坐标和线的起始点和终止点带入即可,当然要先求出线的坐标方程。

同样的,自然还有对点与线距离的判断。

if (this.endPoint.x === this.startPoint.x) {
       return (this.startPoint.y - radius <= y && this.endPoint.y + radius >= y || this.endPoint.y - radius <= y && this.startPoint.y + radius >= y) && x > this.startPoint.x - radius && x < this.startPoint.x + radius;
      }

首先是两种情况。

第一种情况是点位于垂直线上,因此附近区域为矩形。

 if (this.startPoint.y === this.endPoint.y) {
        return (this.startPoint.x - radius <= x && this.endPoint.x + radius >= x || this.endPoint.x - radius <= x && this.startPoint.x + radius >= x) && y > this.startPoint.y - radius && y < this.startPoint.y + radius;
      }

第二种是位于水平线上。

此外就是标准的利用点到线的距离进行运算。

var startX = mathMin(this.endPoint.x, this.startPoint.x);
      var startY = mathMin(this.endPoint.y, this.startPoint.y);
      var endX = mathMax(this.endPoint.x, this.startPoint.x);
      var endY = mathMax(this.endPoint.y, this.startPoint.y);

为运算中的各个值进行定义。

      var a = this.endPoint.y - this.startPoint.y;
      var b = this.startPoint.x - this.endPoint.x;
      var c = -(this.startPoint.x * this.endPoint.y - this.endPoint.x * this.startPoint.y);

首先我们需要找到直线方程ax+by+c=0的a,b,c

 var d = mathAbs((a * x + b * y + c) / mathSqrt(mathPow(a, 2) + mathPow(b, 2)));

然后我们可以得到距离 。来自于"Mathematics for Computer Graphics, 2nd Ed., by John Vice, page 227"

紧接着,我们可以得出到目标点最近的线上的点的坐标

var closestX = (b * (b * x - a * y) - a * c) / (mathPow(a, 2) + mathPow(b, 2));
      var closestY = (a * (-b * x + a * y) - b * c) / (mathPow(a, 2) + mathPow(b, 2));

当点的投影点位于线段内部时

 var r = d <= radius && endX >= closestX && closestX >= startX && endY >= closestY && closestY >= startY ||

当点的投影点位于线段外部时

this.startPoint.near(x, y, radius) || this.endPoint.near(x, y, radius);

这样我们就可以求出点到线的距离了。

 key: "getPoint",
    value: function getPoint(t) {
      var xp = t * (this.endPoint.x - this.startPoint.x) + this.startPoint.x;
      var yp = t * (this.endPoint.y - this.startPoint.y) + this.startPoint.y;
      return new GeoPoint(xp, yp);
    }

这里是获取指定百分比上的点,参数 t 是百分比。也就是在线上百分之几的位置的点的坐标的获取。

剩下的关于线的克隆输出和两个线的对比和前面的点的操作大同小异,就不一一赘述了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

云亦纵

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值