Javascript 变换几何形状,保持对称性和边界尺寸完整

Javascript 变换几何形状,保持对称性和边界尺寸完整,javascript,geometry,graph-theory,computational-geometry,Javascript,Geometry,Graph Theory,Computational Geometry,我正在开发一种工具,用于从各种模板修改不同的几何形状。这些形状是在房间里可以找到的基本形状。 例如:L形、T形、六边形、矩形等 我需要做的是使形状符合所有必要的边,以便在用户修改边时保持形状的对称性和边界尺寸不变 形状是这样简单实现的,第一个节点从左上角开始,顺时针绕形状旋转(我使用): 公共类形状{ 私有节点:数组; 专用比例:number;//用于计算相对于给定长度的正确坐标的比例 …//有很多转换方法 然后将其绘制为图形,将数组中的每个节点连接到下一个节点。(参见下文) 例如,如果我将边

我正在开发一种工具,用于从各种模板修改不同的几何形状。这些形状是在房间里可以找到的基本形状。 例如:L形、T形、六边形、矩形等

我需要做的是使形状符合所有必要的边,以便在用户修改边时保持形状的对称性和边界尺寸不变

形状是这样简单实现的,第一个节点从左上角开始,顺时针绕形状旋转(我使用):

公共类形状{
私有节点:数组;
专用比例:number;//用于计算相对于给定长度的正确坐标的比例
…//有很多转换方法
然后将其绘制为图形,将数组中的每个节点连接到下一个节点。(参见下文)

例如,如果我将边C的长度从3.5米改为3米,那么我还希望边E或G改变它们的长度,使侧面保持12米,并向下推E,使边d仍然完全水平。 如果我改为将D面改为2米,那么B将不得不将其长度改为10米,以此类推

(我确实有一些形状也有倾斜的角度,比如一个被切掉一个角的矩形)

问题

我有以下用于修改特定边的代码:

    public updateEdgeLength(start: Point, length: number): void  {
        let startNode: Node;
        let endNode: Node;
        let nodesSize = this.nodes.length;

        // Find start node, and then select end node of selected edge.
        for (let i = 0; i < nodesSize; i++) {
            if (this.nodes[i].getX() === start.x && this.nodes[i].getY() === start.y) {
                startNode = this.nodes[i];
                endNode = this.nodes[(i + 1) % nodesSize];
                break;
            }
        }

        // Calculate linear transformation scalar and create a vector of the edge
        let scaledLength = (length * this.scale);
        let edge: Vector = Vector.create([endNode.getX() - startNode.getX(), endNode.getY() - startNode.getY()]);
        let scalar = scaledLength / startNode.getDistance(endNode);

        edge = edge.multiply(scalar);

        // Translate the new vector to its correct position 
        edge = edge.add([startNode.getX(), startNode.getY()]);
        // Calculate tranlation vector
        edge = edge.subtract([endNode.getX(), endNode.getY()]);

        endNode.translate({x: edge.e(1), y: edge.e(2)});

    }
public-updateEdgeLength(起点:点,长度:编号):void{
设startNode:Node;
让endNode:节点;
让nodesSize=this.nodes.length;
//查找开始节点,然后选择选定边的结束节点。
for(设i=0;i
现在,我需要一个更一般的情况来找到相应的边,这些边也需要修改。我已经开始实现特定于形状的算法,因为我知道哪些节点对应于形状的边,但这在将来不会有太大的扩展性

例如,上面的形状可以这样实现:

public updateSideLength(edge: Position): void {
    // Get start node coordinates
    let startX = edge.start.getX();
    let startY = edge.start.getY();

    // Find index of start node;
    let index: num;
    for (let i = 0; i < this.nodes.length; i++) {
        let node: Node = this.nodes[i];
        if(node.getX() === startX && node.getY() === startY) {
            index = i;
            break;
        }
    }

    // Determine side
    let side: number;
    if (index === 0 || index === 2) {
        side = this.TOP;
    }
    else if (index === 1 || index === 3 || index === 5) {
        side = this.RIGHT;
    }
    else if (index === 4 || index === 6) {
        side = this.BOTTOM;
    }    
    else if (index === 7) {
        side = this.LEFT;
    }

    adaptSideToBoundingBox(index, side); // adapts all other edges of the side except for the one that has been modified
}

public adaptSideToBoundingBox(exceptionEdge: number, side: number) {
    // Modify all other edges
        // Example: C and G will be modified
        Move C.end Y-coord to D.start Y-coord;
        Move G.start Y-coord to D.end Y-coord;       
}
公共更新删除长度(边缘:位置):无效{
//获取开始节点坐标
设startX=edge.start.getX();
让startY=edge.start.getY();
//查找起始节点的索引;
let索引:num;
for(设i=0;i
以此类推……但对每个形状(5 atm.)和未来的形状实现这一点将非常耗时

所以我想知道的是,是否有一个更普遍的方法来解决这个问题


谢谢!

保留一个点对列表和约束它们的键,并在更新时使用该列表覆盖坐标

这适用于您给出的示例:

var Point=(函数(){
功能点(x、y、连接到){
如果(connectedTo==void 0){connectedTo=[];}
这个.x=x;
这个。y=y;
this.connectedTo=connectedTo;
}
返回点;
}());
var Polygon=(函数(){
函数多边形(点、约束){
如果(constraints==void 0){constraints=[];}
这个点=点;
this.constraints=约束;
}
返回多边形;
}());
变量Sketch=(函数(){
函数草图(多边形、画布){
如果(多边形===void 0){polygons=[];}
if(canvas==void 0){canvas=document.body.appendChild(document.createElement(“canvas”);}
这个。多边形=多边形;
this.canvas=画布;
this.canvas.width=1000;
this.canvas.height=1000;
this.ctx=this.canvas.getContext(“2d”);
this.ctx.fillStyle=“#0971CE”;
this.ctx.strokeStyle=“白色”;
this.canvas.onmousedown=this.clickHandler.bind(this);
this.canvas.onmouseup=this.clickHandler.bind(this);
this.canvas.onmousemove=this.clickHandler.bind(this);
requestAnimationFrame(this.draw.bind(this));
}
Sketch.prototype.clickHandler=函数(evt){
if(evt.type==“鼠标向下”){
如果(this.selectedPoint!=void 0){
this.selectedPoint=null;
}
否则{
var得分=零;
var最佳=
public updateSideLength(edge: Position): void {
    // Get start node coordinates
    let startX = edge.start.getX();
    let startY = edge.start.getY();

    // Find index of start node;
    let index: num;
    for (let i = 0; i < this.nodes.length; i++) {
        let node: Node = this.nodes[i];
        if(node.getX() === startX && node.getY() === startY) {
            index = i;
            break;
        }
    }

    // Determine side
    let side: number;
    if (index === 0 || index === 2) {
        side = this.TOP;
    }
    else if (index === 1 || index === 3 || index === 5) {
        side = this.RIGHT;
    }
    else if (index === 4 || index === 6) {
        side = this.BOTTOM;
    }    
    else if (index === 7) {
        side = this.LEFT;
    }

    adaptSideToBoundingBox(index, side); // adapts all other edges of the side except for the one that has been modified
}

public adaptSideToBoundingBox(exceptionEdge: number, side: number) {
    // Modify all other edges
        // Example: C and G will be modified
        Move C.end Y-coord to D.start Y-coord;
        Move G.start Y-coord to D.end Y-coord;       
}