Warm tip: This article is reproduced from serverfault.com, please click

How to format an array of coordinates to a different reference point

发布于 2020-11-28 03:41:23

I looked around and I couldn't find any info on the topic... probably because I can't iterate my problem accurately into a search engine.

I'm trying to take raw line data from a dxf, sort it into squares, find the center of each square, number the center, and print the result to pdf.

I have a data structure similar to the following:

[
[{x: 50, y:50}, {x:52, y:52}],
[{x: 52, y:52}, {x:54, y:54}],
[{x: 54, y:54}, {x:56, y:56}]...
]

These coordinates are obtained from parsing a dxf using dxf-parser, which returns an array of objects that describe the path of the line. Four of these combine to make a square, which I segment using

  function chunkArrayInGroups(arr, size) {
    let result = [];
    let pos = 0;
    while (pos < arr.length) {
      result.push(arr.slice(pos, pos + size));
      pos += size;
    }
    return result;
  }

((Size = 4))

This behaves as intended for the most part, except these coordinates were created with the origin in the center of the screen. The pdf library I'm using to create the final document does not use the same coordinate system. I believe it starts the origin at the top left of the page. This made all of my negative values ((Anything to the left of the center of the model)) cut off the page.

To remedy this, I iterate through the array and collect '0 - all x and y values' in a new array, which I find the max of to give me my offset. I add this offset to my x values before plugging them into my pdf creator to draw the lines.

I'm not sure what is causing it, but the output is 'Da Vinci Style' as I like to call it, it's rotated 180 degrees and written backwards. I thought adding some value to each cell would fix the negative issue... and it did, but the data is still with respect to a central origin. Is there a way I can redefine this data to work with this library, or is there some other library where I can graph this data and also add text at specific spots as my case dictates. I would like to continue to use this library as I use it for other parts of my program, but I am open to new and more efficient ideas.

I appreciate your time and expertise!

What it's supposed to look like

Source Picture

"Da Vinci'fied" Result

Current Output

Copy of the code:


const PDFDocument = require('pdfkit');
const doc = new PDFDocument({ autoFirstPage: true })
const DxfParser = require('dxf-parser')

let fileText = fs.readFileSync('fulltest.dxf', { encoding: 'utf-8' })
let data = []
let data2 = []
let data3 = []
let shiftx = []
let shifty = []
let factor = 5
var parser = new DxfParser();
let i = 0
doc.pipe(fs.createWriteStream('test.pdf'));
try {
  var dxf = parser.parseSync(fileText);
  let array = dxf.entities
  array.forEach(line => {
    if (line.layer === "Modules") {
      data.push(line.vertices)
    }
    if (line.layer === "Buildings") {
      data2.push(line.vertices)
    }
    if (line.layer === "Setbacks") {
      data3.push(line.vertices)
    }
    let segment = line.vertices
    segment.forEach(point => {
      shiftx.push(0 - point.x)
      shifty.push(0 - point.y)
    })

  })
  
  let shift = biggestNumberInArray(shiftx)

  console.log(shift)
  data = chunkArrayInGroups(data, 4)
  data.forEach(module => {
    let midx = []
    let midy = []
    module.forEach(line => {
      let oldx = (line[1].x + shift) * factor
      let oldy = (line[1].y + shift) * factor
      let newx = (line[0].x + shift) * factor
      let newy = (line[0].y + shift) * factor
      doc
        .moveTo(oldx, oldy)
        .lineTo(newx, newy)
        .stroke()
      midx.push(oldx + (newx - oldx) / 2)
      midy.push(oldy + (newy - oldy) / 2)
    })
    let centerx = (midx[0] + (midx[2] - midx[0]) / 2)
    let centery = (midy[0] + (midy[2] - midy[0]) / 2)
    let z = (i + 1).toString()
    doc
      .fontSize(10)
      .text(z, centerx-5, centery-5)
    i++
  })

  data2.forEach(line => {
    let oldx = (line[0].x + shift) * factor
    let oldy = (line[0].y + shift) * factor
    let newx = (line[1].x + shift) * factor
    let newy = (line[1].y + shift) * factor
    doc
      .moveTo(oldx, oldy)
      .lineTo(newx, newy)
      .stroke()
  })
  data3.forEach(line => {
    let oldx = (line[0].x + shift) * factor
    let oldy = (line[0].y + shift) * factor
    let newx = (line[1].x + shift) * factor
    let newy = (line[1].y + shift) * factor
    doc
      .moveTo(oldx, oldy)
      .lineTo(newx, newy)
      .stroke('red')
  })
  doc.end();

} catch (err) {
  return console.error(err.stack);
}


function biggestNumberInArray(arr) {
  const max = Math.max(...arr);
  return max;
}

function chunkArrayInGroups(arr, size) {
  let result = [];
  let pos = 0;
  while (pos < arr.length) {
    result.push(arr.slice(pos, pos + size));
    pos += size;
  }
  return result;
}
Questioner
PaulyP
Viewed
0
PaulyP 2020-11-28 12:54:30

After sitting outside and staring at the fence for a bit, I revisited my computer and looked at the output again. I rotated it 180 as I did before, and studied it. Then I imagined it flipped over the y axis, like right off my computer. THAT WAS IT! I grabbed some paper and drew out the original coordinates, and the coordinates the pdf library.

input coords ^ >

output coords v >

I realized the only difference in the coordinate systems was that the y axis was inverted! Changing the lines to

      let oldx = (line[1].x + shift) * factor
      let oldy = (-line[1].y + shift) * factor
      let newx = (line[0].x + shift) * factor
      let newy = (-line[0].y + shift) * factor

inverted with respect to y and after the shift, printed correctly! Math wins again hahaha