【问题标题】:Can't line ellipse with the coordinates of a vector不能用向量的坐标来画椭圆
【发布时间】:2021-07-05 04:40:38
【问题描述】:

我试图将一些椭圆与移动和旋转的线的端点对齐,最终目标是能够计算所述端点的坐标。我可以计算初始位置,但是一旦我移动汽车,所有的椭圆都会向相反的方向移动。我不擅长几何,我不知道为什么会这样或如何解决它。

到目前为止我所拥有的:
sketch.js

// Declares global variables
const h = window.innerHeight;
const w = window.innerWidth;
var car;
var borders = [];
var pos = {
    x: w / 2, 
    y: h / 2,
    angle: 0
}

function setup () {

    // Creates the canvas
    background ( '#000000' );
    createCanvas ( w, h );
    angleMode ( DEGREES );
    rectMode ( CENTER );
    stroke ( 255 );

    // Creates some borders
    borders.push ( new Border ( 0, height / 2, width, height / 2 ) );

    // Creates the car 
    car = new Car();

}

function draw () {

    // Clears the canvas
    background ( '#000000' );
    fill("white");

    // Displays the borders
    for ( var border of borders ) {
        border.show();
    }

    // Moves the car 
    if ( keyIsDown ( UP_ARROW ) ) {
        car.forward();
    } 

    if ( keyIsDown ( DOWN_ARROW ) ) {
        car.backward();
    }

    // Checks if the car is intersecting
    const intersection = car.intersects ( borders );
    car.emit(borders);
    if ( intersection ) {
        fill("red");
    }


    // Displays the car on the canvas
    translate(pos.x, pos.y);
    rotate(pos.angle);
    car.show();

}

car.js

class Car {

    // Defines the class
    constructor ( ) {

        this.pos = createVector ( 0, 0 );
        this.width = 20;
        this.length = 40;
        this.speed = 0;
        this.rays = [];

        // Creates the car's rays
        for ( var x = 0; x < 360; x += 20 ) {
            this.rays.push ( new Ray ( createVector ( this.pos.x, this.pos.y ), radians ( x ) ) );
        }

    }

    // Displays the car on the canvas
    show () {  

        // Displays the car
        rect ( this.pos.x, this.pos.y, this.width, this.length );

        // Displays the rays
        for ( var ray of this.rays ) {
            ray.show();
        }
    }

    // Checks if any rays are intersecting a border
    emit ( borders ) {

        // Loops through all the rays
        for ( var ray of this.rays ) {

            // Loops through all the borders
            for ( var border of borders ) {

                const intersection = ray.intersects ( border );
                if ( intersection ) {

                    console.log(intersection);

                }

            }

        }

    }

    // Moves forward
    forward () {
        pos.y -= cos(pos.angle) * 4; 
        pos.x += sin(pos.angle) * 4;

        // Steers left
        if ( keyIsDown ( LEFT_ARROW ) ) {
            pos.angle -= 3;
        }

        // Steers right
        if ( keyIsDown ( RIGHT_ARROW ) ) {
            pos.angle += 3;
        }
    }

    // Moves backward
    backward () {
        pos.y += cos(pos.angle) * 4; 
        pos.x -= sin(pos.angle) * 4;

        // Steers left
        if ( keyIsDown ( LEFT_ARROW ) ) {
            pos.angle -= 3;
        }

        // Steers right
        if ( keyIsDown ( RIGHT_ARROW ) ) {
            pos.angle += 3;
        }
    }

    // Checks if the car is intersecting any borders
    intersects ( borders ) {

        // Calculates the car's corners
        var corners = [
            createVector ( pos.x - ( this.width / 2 ), pos.y - ( this.length / 2 ) ),
            createVector ( pos.x + ( this.width / 2 ), pos.y - ( this.length / 2 ) ),
            createVector ( pos.x + ( this.width / 2 ), pos.y + ( this.length / 2 ) ),
            createVector ( pos.x - ( this.width / 2 ), pos.y + ( this.length / 2 ) )
        ];

        var sides = [
            [
                corners[0],
                corners[1]
            ],
            [
                corners[1],
                corners[2]
            ],
            [
                corners[2],
                corners[3]
            ],
            [
                corners[3],
                corners[0]
            ]
        ];

        // Loops through each side
        for ( var side of sides ) {

            // Loops through each border
            for ( var border of borders ) {

                var x1 = side[0].x;
                var y1 = side[0].y;
                var x2 = side[1].x;
                var y2 = side[1].y;

                const x3 = border.x.x;
                const y3 = border.x.y;
                const x4 = border.y.x;
                const y4 = border.y.y;

                // Rotates the corners relative to the car
                var tempX1 = x1 - pos.x;
                var tempY1 = y1 - pos.y;
                var tempX2 = x2 - pos.x;
                var tempY2 = y2 - pos.y;
                var rotatedX1 = tempX1 * cos ( pos.angle ) - tempY1 * sin ( pos.angle );
                var rotatedY1 = tempX1 * sin ( pos.angle ) + tempY1 * cos ( pos.angle );
                var rotatedX2 = tempX2 * cos ( pos.angle ) - tempY2 * sin ( pos.angle );
                var rotatedY2 = tempX2 * sin ( pos.angle ) + tempY2 * cos ( pos.angle );
                x1 = rotatedX1 + pos.x; 
                y1 = rotatedY1 + pos.y;            
                x2 = rotatedX2 + pos.x;
                y2 = rotatedY2 + pos.y;

                // Checks if the car is intersecting
                const d = ( x1 - x2 ) * ( y3 - y4 ) - ( y1 - y2 ) * ( x3 - x4 );

                const t = ( x1 - x3 ) * ( y3 - y4 ) - ( y1 - y3 ) * ( x3 - x4 ) / d;

                if ( 0 <= t && t <= 1 ) {
                         return createVector ( x1 + t * ( x2 - x1 ), y1 + t * ( y2 - y1 ) );
                }
            }

        }

    }

}

ray.js

class Ray {

    // Defines the class
    constructor ( position, angle ) {

        this.pos = position;
        this.angle = angle;
        this.dir = p5.Vector.fromAngle ( angle );

    }

    // Checks if the ray is intersecting a border
    intersects ( border ) {

        // const endpoints = [

        // ];
        

        var x1 = pos.x;
        var y1 = pos.y;
        var x2 = this.dir.x * 100;
        var y2 = this.dir.y * 100;

        const x3 = border.x.x;
        const y3 = border.x.y;
        const x4 = border.y.x;
        const y4 = border.y.y;

        // Rotates the corners relative to the car
        var tempX2 = x2 - pos.x;
        var tempY2 = y2 - pos.y;
        var rotatedX2 = tempX2 * cos ( pos.angle ) - tempY2 * sin ( pos.angle );
        var rotatedY2 = tempX2 * sin ( pos.angle ) + tempY2 * cos ( pos.angle );
        x2 = rotatedX2 + pos.x;
        y2 = rotatedY2 + pos.y;

        /* This is where I'm having difficulty */

        push();
        translate(pos.x, pos.y);
        ellipse(x2, y2, 10);
        pop();

        // const den = ( ( x1 - x2 ) * ( y3 - y4 ) - ( y1 - y2 ) * ( x3 - x4 ) );

        // if ( den == 0 ) {
        //     console.log(1);
        //     return;
        // }

        // var t = ( ( x1 - x3 ) * ( y3 - y4 ) - ( y1 - y3 ) * ( x3 - x4 ) ) / den;
        // var u = ( ( x2 - x1 ) * ( y1 - y3 ) - ( y2 - y1 ) * ( x1 - x3 ) ) / den;

        // if ( 0 <= t && t <= 1 ) {

        //     const x = x1 + t * ( x2 - x1 );
        //     const y = y1 + t * ( y2 - y1 );

        //     // return createVector ( x, y );
        //     ellipse ( x, y, 10 );

        // } 

        // return;
        
    }

    // Displays the ray on the canvas 
    show () {

        push();
        translate(this.pos.x, this.pos.y);
        line(0, 0, this.dir.x * 100, this.dir.y * 100);
        pop();

    }

}

border.js

class Border {

    // Defines the class
    constructor ( x1, y1, x2, y2 ) {

        this.x = createVector ( x1, y1 );
        this.y = createVector ( x2, y2 );

    }

    show () {

        stroke ( 255 );
        line ( this.x.x, this.x.y, this.y.x, this.y.y );

    }

}

【问题讨论】:

    标签: javascript html p5.js euclidean-distance


    【解决方案1】:

    我的解释是,在 ray.js 的第 31-36 行中,您试图将点 x2, y2 旋转 pos.angle。实际上,您无需执行任何三角操作即可。

    在三角函数中,您从this.dir 中减去了pos。但是this.dir已经是一个以汽车位置为基点的向量,所以this.dir的坐标已经是相对于汽车位置的了。这是一种解决方案,其中 x2 和 y2 使用旋转进行初始化:

    var x2 = this.dir.x * 100 * cos ( pos.angle ) - 
        this.dir.y * 100 * sin ( pos.angle );
    var y2 = this.dir.x * 100 * sin ( pos.angle ) + 
        this.dir.y * 100 * cos ( pos.angle );
    

    不过,正如我上面所说,您不必进行任何触发。您可以使用.rotate() 方法:

    var x2 = this.dir.copy().rotate(radians(pos.angle)).x * 100;
    var y2 = this.dir.copy().rotate(radians(pos.angle)).y * 100;
    

    注意:使用.rotate()和其他矢量方法时需要转换为弧度,因为angleMode()不影响矢量。

    在这两种解决方案中,您都应该去掉第 31-36 行。

    但是,当您尝试应用此功能时,我认为您可能会遇到问题。由于x2y2相对于汽车的位置,因此它们不是屏幕上绘制线条的实际端点。相反,它们位于左上角上方的一圈点中。如果您要尝试测试 x1, y1 和 x2, y2 之间的线段是否与 x3, y3 和 x4, y4 之间的线段相交,您会得到它仅在边界位于 pos 和左上角。

    我认为你真正在寻找的是

    var x2 = this.dir.copy().rotate(radians(pos.angle)).x + pos.x;
    var y2 = this.dir.copy().rotate(radians(pos.angle)).y + pos.y;
    

    注意:您还必须在显示省略号时去掉翻译,以使其看起来正确。 当我在 ray.js 中取消注释您的其他代码时,它在最后一个版本中表现得更好。

    此外,每次引用 this.dir.xthis.dir.y 时,它们似乎都乘以 100。如果您将 this.dir 设为 100 像素长,则可以省略它,这是 .fromAngle() 方法内置的:

    this.dir = p5.Vector.fromAngle(angle, 100);
    

    会给你一个正确方向的向量,长度为 100。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-02-22
      • 1970-01-01
      • 1970-01-01
      • 2013-04-23
      相关资源
      最近更新 更多