gpt4 book ai didi

javascript - 如何在不改变线长的情况下 reshape 多边形

转载 作者:行者123 更新时间:2023-12-03 02:32:12 25 4
gpt4 key购买 nike

我可以使用片段中的代码用鼠标 reshape 多边形。绘制多边形后,用户可以通过移动点来改变形状。但我想修改形状而不改变线长度。点将尽可能改变,但线的长度将保持不变。

我该怎么做?

var canvas, ctx;
var canvasIsMouseDown = false;
var radius = 6;
var pointIndex = -1;

var points = [
{ x: 10, y: 10 },
{ x: 100, y: 50 },
{ x: 150, y: 100 },
{ x: 60, y: 110 },
{ x: 30, y: 160 }
];
function start() {
canvas = document.getElementById("cnPolygon");
ctx = canvas.getContext("2d");
canvas.addEventListener("mousemove", canvasMouseMove);
canvas.addEventListener("mousedown", canvasMouseDown);
canvas.addEventListener("mouseup", canvasMouseUp);
draw();
}
function canvasMouseMove(ev) {
if (!canvasIsMouseDown || pointIndex === -1) return;
points[pointIndex].x = ev.pageX - this.offsetLeft;
points[pointIndex].y = ev.pageY - this.offsetTop;
draw();
}
function canvasMouseDown(ev) {
canvasIsMouseDown = true;
var x = ev.pageX - this.offsetLeft;
var y = ev.pageY - this.offsetTop;
pointIndex = -1;
var dist;
for (var i = 0; i < points.length; i++) {
dist = Math.sqrt(Math.pow((x - points[i].x), 2) + Math.pow((y - points[i].y), 2));
if (dist <= radius) {
pointIndex = i;
break;
}
}
}
function canvasMouseUp(ev) {
canvasIsMouseDown = false;
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
for (var i = 0; i < points.length; i++) {
ctx.lineTo(points[i].x, points[i].y);
}
ctx.closePath();
ctx.stroke();
for (var i = 0; i < points.length; i++) {
ctx.beginPath();
ctx.arc(points[i].x, points[i].y, radius, 0, Math.PI * 2);
ctx.stroke();
}
}
document.addEventListener("DOMContentLoaded", start);
<canvas id="cnPolygon" width="200" height="200" style="border:solid 1px silver"></canvas>

最佳答案

看看这个

var canvas, ctx;
var canvasIsMouseDown = false;
var radius = 3;
var pointIndex = -1;
var points = [
{ x: 10, y: 10 },
{ x: 100, y: 50 },
{ x: 150, y: 100 },
{ x: 60, y: 110 },
{ x: 30, y: 160 }
];

// PHYSICS START ----------------
var stiffness = 0.25 // defines how elastic the contrainst should be
var oscillations = 10 // defines how many iterations should be made, more iterations mean higher precision

function getAngle(x1,y1,x2,y2){
return Math.atan2(y2-y1,x2-x1) + Math.PI/2
}
function getConstraintPos(tx,ty,ox,oy,dist){
var rot = getAngle(tx,ty,ox,oy)
var x = tx+Math.sin(rot)*dist
var y = ty-Math.cos(rot)*dist
return [x,y]
}
function applyContraintForce(point,pos){
point.x += (pos[0] - point.x)*stiffness
point.y += (pos[1] - point.y)*stiffness
}
function defineDistances(){
for (var i = 0; i < points.length; i++) {
var next_point = points[(i+1)%points.length]
points[i].distance = Math.sqrt(Math.pow((next_point.x - points[i].x), 2) + Math.pow((next_point.y - points[i].y), 2))
}
}
function updateContraints(){
// forward pass
for (var i=0;i<points.length;i++)
{
if(i==pointIndex) continue
var j = (+i+1)%points.length
var pos = getConstraintPos(points[j].x,points[j].y,points[i].x,points[i].y,points[i].distance)
applyContraintForce(points[i],pos)
}
//backward pass
for (var i=points.length-1;i>=0;i--)
{
if(i==pointIndex) continue
var j = (i-1)
j = j<0 ? points.length+j : j
var pos = getConstraintPos(points[j].x,points[j].y,points[i].x,points[i].y,points[j].distance)
applyContraintForce(points[i],pos)
}
}
// PHYSICS END ----------------



function start() {
canvas = document.getElementById("cnPolygon");
ctx = canvas.getContext("2d");
canvas.addEventListener("mousemove", canvasMouseMove);
canvas.addEventListener("mousedown", canvasMouseDown);
canvas.addEventListener("mouseup", canvasMouseUp);
defineDistances()
draw();
}
function canvasMouseMove(ev) {
if (!canvasIsMouseDown || pointIndex === -1) return;
points[pointIndex].x = ev.pageX - this.offsetLeft;
points[pointIndex].y = ev.pageY - this.offsetTop;
for(var i=0;i<oscillations;i++){
updateContraints()
}
draw();
}
function canvasMouseDown(ev) {
canvasIsMouseDown = true;
var x = ev.pageX - this.offsetLeft;
var y = ev.pageY - this.offsetTop;
pointIndex = -1;
var dist;
for (var i = 0; i < points.length; i++) {
dist = Math.abs(Math.sqrt(Math.pow((x - points[i].x), 2) + Math.pow((y - points[i].y), 2)));
if (dist <= radius) {
pointIndex = i;
break;
}
}
}
function canvasMouseUp(ev) {
canvasIsMouseDown = false;
}
function draw() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
ctx.moveTo(points[0].x, points[0].y);
for (var i = 0; i < points.length; i++) {
ctx.lineTo(points[i].x, points[i].y);
}
ctx.closePath();
ctx.stroke();
for (var i = 0; i < points.length; i++) {
ctx.beginPath();
ctx.arc(points[i].x, points[i].y, radius * 2, 0, Math.PI * 2);
ctx.stroke();
}
}

document.addEventListener("DOMContentLoaded", start);
<canvas id="cnPolygon" width="500" height="300" style="border:solid 1px silver"></canvas>

它的作用是计算两个给定点之间的 Angular ,并根据该 Angular 和距离增量施加力。施加的力乘以刚度

这必须向前(点 A -> 点 B) 和向后(点 A <- 点 B) 进行,以便考虑到链中的最后一个点到第一个点。

注意这并非 100% 准确。精度可以通过迭代计数来提高,但正如 @bhspencer 已经指出的那样,在某些情况下这是不可能的,仅仅是因为几何形状。

关于javascript - 如何在不改变线长的情况下 reshape 多边形,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48691566/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com