Расчет пересечения прямой с произвольным массивом вершин (P5. js) - PullRequest
0 голосов
/ 01 августа 2020

Я пытаюсь разобраться, как рассчитать пересечение между линией и краями произвольного c многоугольника в P5 - https://editor.p5js.org/knectar/sketches/5c-M8K7bS

Проблема в том, что что пересечения не совпадают с линией.

Похоже, есть проблема с формулой наклона, есть идеи по устранению неполадок?

var clickState = 0;

var cellSize = 200;
var gridSize = 400;
var fault;

function setup() {
  createCanvas(windowWidth, windowHeight);

  // cellSize = floor(width/5);
  let cols = floor(width / gridSize);
  let rows = floor(height / gridSize);

  for (let i = 0; i < cols; i++) {
    for (let j = 0; j < rows; j++) {
      cellArr.push(new Cell(i * gridSize, j * gridSize));
    }
  }

  for (let i = cellArr.length - 1; i >= 0; i--) {
    cellArr[i].calcSlopes();
    break;
  }

  fault = new Fault(random(width), 0, random(width), height);

}

function draw() {
  background(10);

  push();
  // translate(width / 3, height / 3);
  for (let i = cellArr.length - 1; i > 0; i--) {
    // cellArr[i].calcSlopes();
    cellArr[i].drawCell();
    cellArr[i].cellNum(i - 1);
    break;
  }
  pop();



  if (clickState == 1) {
    fault.end = createVector(mouseX, mouseY);

    if (fault) {

      fault.render();

      for (let i = cellArr.length - 1; i >= 0; i--) {
        cellArr[i].slice(fault);
      }

    }

  }

  // console.log(cellArr[0]);
  // noLoop();


}

class Cell {

  constructor(x, y) {
    this.centerPos = createVector(x, y);
    this.vertCount = floor(random(4, 10));
    this.vertArr = [];
    this.makeCell();
    this.clr = color(random(150, 255), random(0, 40), random(150, 245), 125);
  }

  makeCell() {

    for (let i = 0; i < this.vertCount; i++) {

      let angle = map(i, 0, this.vertCount, 0, TWO_PI);
      let r = cellSize + random(-cellSize, cellSize);

      let x = this.centerPos.x + r * cos(angle);
      let y = this.centerPos.y + r * sin(angle);

      this.vertArr.push({
        pos: createVector(x, y),
        m: 0,
        b: 0
      })

    }
  }

  calcSlopes() {

    let curr, prev, b, slope;

    curr = createVector(this.vertArr[0].pos.x, this.vertArr[0].pos.y);

    this.vertArr.push({
      pos: createVector(curr.x, curr.y),
      m: 0,
      b: 0
    })

    for (let i = this.vertArr.length - 1; i > 0; i--) {

      curr = createVector(this.vertArr[i].pos.x, this.vertArr[i].pos.y);
      prev = createVector(this.vertArr[i - 1].pos.x, this.vertArr[i - 1].pos.y);
      slope = (curr.y - prev.y) / (curr.x - prev.x);
      b = prev.y - (slope * prev.x);

      this.vertArr[i] = ({
        pos: createVector(curr.x, curr.y),
        m: slope,
        b: b
      })

    }
  }

  cellNum(num) {

    text(num, this.centerPos.x, this.centerPos.y);

  }

  drawCell() {

    // ellipse(100, 100, 100);

    stroke(200);
    strokeWeight(1);
    fill(this.clr);

    beginShape();

    for (let i = 0; i < this.vertArr.length; i++) {
      vertex(this.vertArr[i].pos.x, this.vertArr[i].pos.y);
    }

    endShape(CLOSE);

  }

  slice(fault) {

    // y = (fault_m * x) + fault_b
    // y = (regionLineM * x) + regionLineB
    // (fault_m * x) - (regionLineM * x) = regionLineB - fault_b 
    // x = (regionLineB - fault_b) / (regionLineM + fault_m)
    // y = (regionLineM * x) + regionLineB

    let fault_m = fault.m;
    let fault_b = fault.b;
    
    // console.log("fault_m: " + fault_m);

    for (let edge of this.vertArr) {

      let cellLineM = edge.m;
      let cellLineB = edge.b;

      let intersectionX = (cellLineB - fault_b) / (cellLineM + fault_m);
      let intersectionY = (cellLineM * intersectionX) + cellLineB;

      noStroke();
      fill(200, 140);
      ellipse(intersectionX, intersectionY, 20);

    }

  }

}

class Fault {
  constructor(sx, sy, ex, ey) {
    this.start = createVector(sx, sy);
    this.end = createVector(ex, ey);
    this.b = 0;
    this.m = 0;
  }

  render() {

    this.calcFormula();

    stroke(200);
    strokeWeight(1);
    let topIntercept;
    let botIntercept;
    topIntercept = -this.b / this.m;
    // console.log("Orig_slope: " + this.m);

    botIntercept = (height - this.b) / this.m;
    this.end = createVector(botIntercept, height);
    line(topIntercept, 0, botIntercept, height);
  }

  calcFormula() {
    this.m = (this.end.y - this.start.y) / (this.end.x - this.start.x);
    this.b = this.start.y - (this.m * this.start.x);
  }

}

function mouseClicked() {

  if (clickState == 0) {
    fault.start = createVector(mouseX, mouseY);
  }
  clickState++;

  if (clickState == 2) {
    clickState = 0;
  }

}```


 
...