简体   繁体   中英

Calculate offset point coordinate between two points

I'm having a hard time figuring out how to word this, so picture time.

I have points arranged in a circle, I know the x,y coordinates for all of them.

在此处输入图像描述

I can iterate each point and draw a line between them, easy

//in a for each dot loop..
ctx.beginPath();
ctx.moveTo(startX, startY);
ctx.lineTo(endX, endY);
ctx.stroke();

在此处输入图像描述

This is where I'm up to now. The rest I can't figure out

While iterating a point, I'd like to create a "diversion" that alternates between left and right (as though you're looking from the one point towards the next point in the sequence).

I want to take the midpoint of that straight line between two points, shoot 90 degrees off either left or right (let's say i % 2 or something), travel set distance d and place a point at the end location. The distance d will be different for each point and I have determined values for each of them.

在此处输入图像描述

Then continue iterating each point while creating offset points at set distances alternating left or right from the reference of the midway line between two points.

在此处输入图像描述

When iterating a point, instead of drawing a straight line from startX, startY to endX, endY , I will draw 2 lines - one from startX, startY to diversionX, diversionY and one from that to endX, endY . The final rendered result would be this.

在此处输入图像描述

What I'm really asking is for help with the offset dot placing, I didn't have a great relationship with geometry at school, forever this has haunted me.. Drawing paths is trivial, I just need to know the point coordinates where to draw to/from..

 var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); var pointSize = 5; var points = [ [300, 50, 10], // x, y, offset point distance [175, 80, 15], [100, 185, 9], [100, 315, 21], [175, 420, 12], [300, 460, 15], [420, 420, 8], [500, 315, 16], [500, 185, 25], [420, 80, 17] ]; for(var i = 0; i < points.length; i++) { x = points[i][0]; y = points[i][1]; d = points[i][2]; // diversion length // draw point ctx.fillStyle = '#000000'; ctx.fillRect(x-(pointSize/2), y-(pointSize/2), pointSize, pointSize); // draw temporary connecting line to next point ctx.strokeStyle = '#d4d4d4'; nextPoint = points[(i + 1) % points.length]; ctx.beginPath(); ctx.moveTo(x, y); ctx.lineWidth = 3; ctx.lineTo(nextPoint[0], nextPoint[1]); ctx.stroke(); // aaaaand I'm lost // get midpoint of drawn line // shoot off 90 degress to a side (i %2) // travel distance of "d" // get "d" x, y position // draw lines between // x,y and dx,dy // dx,dy and nextX, nextY }
 <canvas id="canvas" width="600" height="600"></canvas>

Getting the center point of a line

mid.X = (start.X + end.X) / 2
mid.Y = (start.Y + end.Y) / 2

Getting a vector from two points

vec.X = end.X - start.X;
vec.Y = end.Y - start.Y;

Getting a vector form point => position

This is just like having a vector from 0, 0 to the point => your position so:

vec.X = mid.X;
vec.Y = mid.Y;

Turning by 90 degrees

// Depending on the direction you'd either have to negate the x or y component
const prevY = vec.Y;
vec.Y = vec.X;
vec.X = -prevY;

const prevY = vec.Y
vec.Y = -vec.Y
vec.X = prevY

Going a certain distance

// You have 'point' in your case the center point and the rotated vector 'vec'
// Here you first calculate the length of 'vec'
// then get dX and dY that you move per unit in the direction of 'vec'
// then you multiply that with the distance and get your offset
const vecLength = Math.sqrt(vec.X * vec.X + vec.Y * vec.Y);
const xOffset = vec.X / vecLength * distance;
const yOffset = vec.Y / vecLength * distance;

Add an offset (but I guess that's not the difficult part;) )

point.X += xOffset;
point.Y += yOffset;

This is the implemented solution: There are a few temporary drawings just to make it a bit clearer what is happening at every step.

 var canvas = document.getElementById('canvas'); var ctx = canvas.getContext('2d'); var pointSize = 5; var points = [ [300, 50, 50], // x, y, offset point distance [175, 80, 15], [100, 185, 9], [100, 315, 21], [175, 420, 12], [300, 460, 15], [420, 420, 8], [500, 315, 16], [500, 185, 25], [420, 80, 17] ]; for(var i = 0; i < points.length; i++) { x = points[i][0]; y = points[i][1]; d = points[i][2]; // diversion length // draw point ctx.fillStyle = '#000000'; ctx.fillRect(x-(pointSize/2), y-(pointSize/2), pointSize, pointSize); // draw temporary connecting line to next point ctx.strokeStyle = '#d4d4d4'; nextPoint = points[(i + 1) % points.length]; ctx.beginPath(); ctx.moveTo(x, y); ctx.lineWidth = 3; ctx.lineTo(nextPoint[0], nextPoint[1]); ctx.stroke(); const midX = (x + nextPoint[0]) / 2; const midY = (y + nextPoint[1]) / 2; // draw center point ctx.fillStyle = '#00ff00'; ctx.fillRect(midX-(pointSize/2), midY-(pointSize/2), pointSize, pointSize); const midXVec = nextPoint[0] - midX; const midYVec = nextPoint[1] - midY; const nMidXVec = i % 2 === 0? -midYVec: midYVec; const nMidYVec = i % 2 === 0? midXVec: -midXVec; // draw rotated vector from midpoint ctx.strokeStyle = '#f1f1f1'; ctx.beginPath(); ctx.moveTo(midX, midY); ctx.lineWidth = 3; ctx.lineTo(midX + nMidXVec, midY + nMidYVec); ctx.stroke(); const nMidLength = Math.sqrt(nMidXVec * nMidXVec + nMidYVec * nMidYVec); const dXVec = nMidXVec / nMidLength * d; const dYvec = nMidYVec / nMidLength * d; const dX = midX + dXVec; const dY = midY + dYvec; // draw point dX, dY ctx.fillStyle = '#ff0000'; ctx.fillRect(dX-(pointSize/2), dY-(pointSize/2), pointSize, pointSize); // draw final lines ctx.strokeStyle = '#000000'; ctx.beginPath(); ctx.moveTo(x, y); ctx.lineWidth = 3; ctx.lineTo(dX, dY); ctx.lineTo(nextPoint[0], nextPoint[1]); ctx.stroke(); }
 <canvas id="canvas" width="600" height="600"></canvas>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM