当前位置: 代码迷 >> 综合 >> Quark-Renderer----第十三篇
  详细解决方案

Quark-Renderer----第十三篇

热度:37   发布时间:2023-11-26 20:12:29.0

2021SC@SDUSC

综述

上次,我们主要对几何学意思上的点进行了分析,它具有正常点的特征,如横纵坐标,以及一些关于点的方法,该类主要作为一个基本的类,然后作为最基本的构件,后面的所有都可以通过这个来进行创建。
本次我们主要对几何意义上的线进行分析。描述几何意义上的线的js文件在描述点的同一文件夹下,都是geometric中的内容,在GeoLine.js中,我们可以看到作者的注释,关于对几何意义上的直线的定义,它看不见,没有宽度,用来进行数学运算,此实现从diagramo改进而来。下面我们将对其中的关键的方法属性分别讨论。

对GeoLine.js的解析

在该js文件中主要就是对于GeoLine类的描述,并将其导出。首先是构造函数,有两个自身属性,分别是起始点和终点。

  constructor(startPoint, endPoint) {
    this.startPoint = startPoint;this.endPoint = endPoint;}

load函数

load主要是的作用就是从JSON对象中创建直线,需要传一个JSON对象,然后调用GeoLine的构造函数,传入参数,然后返回这个直线

  static load(o) {
    let newLine = new GeoLine(GeoPoint.load(o.startPoint), GeoPoint.load(o.endPoint));return newLine;}

contains函数

该函数的作用就是测试某个点是否位于直线上(这里的直线不是数学意义上的无限延长的直线,而是线段),该函数用到的主要算法就是计算斜率,看看(x,y)是否处在这个线段上.
主要流程如下:先检查是否是竖线,即x不变为常数,因为竖线的斜率不存在,因此我们要单独讨论;而后我们在else中进行分析非竖线的情况,先求出直线的斜率a,以及他的b,这个是直线方程式的两个参数,然后判断参数(x,y)是否满足这个式子y == a * x + b,只需返回这个结果就可以了。

  contains(x, y) {
    // if the point is inside rectangle bounds of the segmentif (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)) {
    // check for vertical lineif (this.startPoint.x == this.endPoint.x) {
    return x == this.startPoint.x;} else {
    // usual (not vertical) line can be represented as y = a * x + blet a = (this.endPoint.y - this.startPoint.y) / (this.endPoint.x - this.startPoint.x);let b = this.startPoint.y - a * this.startPoint.x;return y == a * x + b;}} else {
    return false;}}

near函数

该函数的主要作用是判断某个点是否在某个角度上接近这条线,端点也需要考虑。
在该函数中,我们需要传入三个参数,分别是x,y和radius角度,分别表示这个点的坐标和角度。首先判断这个直线是否是竖线,如果是竖线,则直接根据范围进行判断;对于横线也是如此;将这两种特殊情况考虑完之后,我们就需要对该直线进行操作,首先确定起始点和终点的坐标,然后计算点到直线的距离,这个是一个数学式子,通过计算得到的结果,我们再与radius进行比较,得到结果,最后返回结果。

near(x, y, radius) {
    if (this.endPoint.x === this.startPoint.x) {
    //Vertical line, so the vicinity area is a rectanglereturn (((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) {
    //Horizontal line, so the vicinity area is a rectanglereturn (((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);}let startX = mathMin(this.endPoint.x, this.startPoint.x);let startY = mathMin(this.endPoint.y, this.startPoint.y);let endX = mathMax(this.endPoint.x, this.startPoint.x);let endY = mathMax(this.endPoint.y, this.startPoint.y);/*We will compute the distance from point to the line* by using the algorithm from* http://en.wikipedia.org/wiki/Distance_from_a_point_to_a_line* *///First we need to find a,b,c of the line equation ax + by + c = 0let a = this.endPoint.y - this.startPoint.y;let b = this.startPoint.x - this.endPoint.x;let c = -(this.startPoint.x * this.endPoint.y - this.endPoint.x * this.startPoint.y);//Secondly we get the distance let d = mathAbs((a * x + b * y + c) / mathSqrt(mathPow(a, 2) + mathPow(b, 2)));//Thirdly we get coordinates of closest line's point to target pointlet closestX = (b * (b * x - a * y) - a * c) / (mathPow(a, 2) + mathPow(b, 2));let closestY = (a * (-b * x + a * y) - b * c) / (mathPow(a, 2) + mathPow(b, 2));let r =(d <= radius && endX >= closestX && closestX >= startX && endY >= closestY && closestY >= startY) || //the projection of the point falls INSIDE of the segmentthis.startPoint.near(x, y, radius) ||this.endPoint.near(x, y, radius); //the projection of the point falls OUTSIDE of the segmentreturn r;}

GeoLine上的一些自身方法

getPoint函数

该函数的作用就是获得端点,然后构成数组返回。主要就是初始化数组用来存放起始点和终点,然后将这个返回。

  getPoints() {
    let points = [];points.push(this.startPoint);points.push(this.endPoint);return points;}

getPoint 函数

该函数的作用就是获取指定百分比上的点,参数t是百分比。这个百分比主要是通过计算比率,再当前的位置信息,通过t来确定通过当前的点,然后返回。

  getPoint(t) {
    let xp = t * (this.endPoint.x - this.startPoint.x) + this.startPoint.x;let yp = t * (this.endPoint.y - this.startPoint.y) + this.startPoint.y;return new GeoPoint(xp, yp);}

clone函数

该函数得主要作用就是返回一个新的直线,并且直线的信息完全相同,即克隆。

  clone() {
    let ret = new GeoLine(this.startPoint.clone(), this.endPoint.clone());return ret;}

equals函数

该函数的主要作用就是判断当前的线段是否为同一条,首先判断类型,如果传入的不是线段,那么直接返回,其次在判断这两条线的起始点的坐表是否相同。

  equals(anotherLine) {
    if (!(anotherLine instanceof GeoLine)) {
    return false;}return this.startPoint.equals(anotherLine.startPoint) && this.endPoint.equals(anotherLine.endPoint);}

总结

以上便是所有的关于GeoLine的内容,最关键的两个方法就是contain和near方法,判断一个点是否再这条直线上或者是否在附近,其次我们也对他们的自身的一些方法进行了讨论。
总而言之,我们完成了对GeoLine.js的分析,下篇,我们将通过这两次学到的点和线的知识 进行分析其他几何意义上的模型。