3

三角形の内側に収まるように、対角線で分割された長方形の半分を作成しようとしています。回転は適切に機能し、長方形のサイズ変更も同様です。しかし、それを歪めようとすると、すべてが台無しになります。基本的に、3D サーフェスをシミュレートしたいと考えています。

つまり、b が中心点である abc の角度を見つける必要があります。そして、この角度を長方形に傾斜として適用します。しかし、何らかの理由で意図したとおりに機能しません。

これが私が達成したいことの簡単な図です:

ここに画像の説明を入力

フィドルを見れば、おそらくもっと理解できるでしょ : http://jsfiddle.net/p7g7Y/11/

確認する必要があるコードは 63 行目から 95 行目です。変換をコメント アウトしてみてください。回転とサイズが適切に機能することがわかります。

function triangle(a, b, c){

context.save();

//Draw the triangle
context.beginPath();
context.moveTo(a[0], a[1]);
context.lineTo(b[0], b[1]);
context.lineTo(c[0], c[1]);
context.lineTo(a[0], a[1]);
context.closePath();
context.stroke();

//Lets find the distance between a and b to set height of the image
var imgHeight = lineDistance(a, b);

//And the width b to c
var imgWidth = lineDistance(b, c);

//Now we gotta skew it acording to the rad between ba and bc
var skewAngle = find_angle(a,c,b); //Find angle and make it rad

//Find the angle of b to a line
var theta = Math.atan2(a[1] - b[1], a[0] - b[0]);
context.translate(a[0], a[1]); //Set origin of rotation
context.rotate(theta + 1.57079633); //Had to rotate it some more 1.57079633 = 90deg
context.transform(1, skewAngle, 0, 1, 0, 0);

context.rect( 0, 0, imgHeight, imgWidth);
context.stroke();

context.restore();
}

不明な点があれば質問してください!これについて何か助けていただければ幸いです。

4

2 に答える 2

1

より一般的に問題を解決すると、より簡単にaなります。bcdef

  // (x0, y0) maps to (x_0, y_0)
  a*x0 + b*y0 + c = x_0
  d*x0 + e*y0 + f = y_0

  // (x1, y1) maps to (x_1, y_1)
  a*x1 + b*y1 + c = x_1
  d*x1 + e*y1 + f = y_1

  // (x2, y2) maps to (x_2, y_2)
  a*x2 + b*y2 + c = x_2
  d*x2 + e*y2 + f = y_2

この 6x6 線形システムは、2 つの独立した 3x3 線形システムで構成されています。

  a*x0 + b*y0 + c = x_0
  a*x1 + b*y1 + c = x_1
  a*x2 + b*y2 + c = x_2

  d*x0 + e*y0 + f = y_0
  d*x1 + e*y1 + f = y_1
  d*x2 + e*y2 + f = y_2

setTransformそれらを解くと、任意の 3 点を他の 3 点にマッピングするために渡す 6 つの数値が得られます。

delta = x0*y1 + y0*x2 + x1*y2 - y1*x2 - y0*x1 - x0*y2

delta_a = x_0*y1 + y0*x_2 + x_1*y2 - y1*x_2 - y0*x_1 - x_0*y2
delta_b = x0*x_1 + x_0*x2 + x1*x_2 - x_1*x2 - x_0*x1 - x0*x_2
delta_c = x0*y1*x_2 + y0*x_1*x2 + x_0*x1*y2 - x_0*y1*x2 - y0*x1*x_2 - x0*x_1*y2

delta_d = y_0*y1 + y0*y_2 + y_1*y2 - y1*y_2 - y0*y_1 - y_0*y2
delta_e = x0*y_1 + y_0*x2 + x1*y_2 - y_1*x2 - y_0*x1 - x0*y_2
delta_f = x0*y1*y_2 + y0*y_1*x2 + y_0*x1*y2 - y_0*y1*x2 - y0*x1*y_2 - x0*y_1*y2

a = delta_a / delta
b = delta_b / delta
c = delta_c / delta
d = delta_d / delta
e = delta_e / delta
f = delta_f / delta

2D キャンバス コンテキストを使用した 3D テクスチャ マッピングの完全な説明については、このより詳細な回答を参照してください。

于 2013-08-10T13:46:36.773 に答える
1

長方形を三角形に合わせるために必要な変換を計算する方法は次のとおりです。

  • 三角形の「ピボット ポイント」である点 B に変換します。
  • 辺BCの角度分回転します。
  • 角 B の角度分、X 方向に傾斜させます。

ここに画像の説明を入力

したがって、最初に翻訳します。

        // transform translate = pt2

        var translate = pt2;

次に回転します。

        // transform rotation = angleBC (based on slope of BC)

        var rotation = Math.atan2((pt3.y-pt2.y),(pt3.x-pt2.x));

最後にskewX:

        // transform skewX, based on angleB 

        var skewX = Math.tan(angleB-Math.PI/2);

以下は、skewX で使用する angleB を取得する方法です。

        // calculate segment lengths

        var AB = Math.sqrt(Math.pow(pt2.x-pt1.x,2)+ Math.pow(pt2.y-pt1.y,2));    
        var BC = Math.sqrt(Math.pow(pt2.x-pt3.x,2)+ Math.pow(pt2.y-pt3.y,2)); 
        var AC = Math.sqrt(Math.pow(pt3.x-pt1.x,2)+ Math.pow(pt3.y-pt1.y,2));

        // calculate angleB using law of cosines

        var angleB = Math.acos((BC*BC+AB*AB-AC*AC)/(2*BC*AB));

描画する長方形の幅と高さも必要です。

        // rectangle height = triangle altitude

        var rectHeight = AB * Math.sin(angleB);

        // rectangle width = triangle BC

        var rectWidth = BC;

ちょっとした「落とし穴」:

移動ポイントは B ですが、長方形は左上から描画されます。

これは、長方形を rectHeight だけ垂直方向にオフセットする必要があることを意味します。

        ctx.rect(0,  -rectHeight,  rectWidth,  rectHeight);

また、実際には「落とし穴」ではありませんが、より自然な制限があります。

コーナー B の角度は <180 でなければなりません。

したがって、三角形が「反転」する場合は、ポイント A と C を反転して補正する必要があります。

あなたが持っている興味深いプロジェクト!

終わったら少し分けてくれませんか?

ここにコードとフィドルがあります: http://jsfiddle.net/m1erickson/KKELu/

<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>

<style>
    body{ background-color: ivory; }
    #canvas{border:1px solid red;}
</style>

<script>
$(function(){

    var canvas=document.getElementById("canvas");
    var ctx=canvas.getContext("2d");

    var pt1={x:100,y:100};
    var pt2={x:150,y:225};
    var pt3={x:250,y:150};


    drawTriangle();

    drawRectangle();


    function drawRectangle(){

        // calc transform info
        var info=analyzeTriangle();

        ctx.save();
        ctx.translate(info.translate.x,info.translate.y);
        ctx.rotate(info.rotation);
        ctx.transform(1,0,info.skewX,1,0,0);
        ctx.beginPath();
        // since rects origin is top left, must offset y by -height
        ctx.rect(0,-info.rectHeight,info.rectWidth,info.rectHeight);
        ctx.strokeStyle="purple";
        ctx.stroke();
        ctx.restore();
    }


    function drawTriangle(){
        ctx.beginPath();
        ctx.strokeStyle="blue";
        ctx.moveTo(pt1.x,pt1.y);
        ctx.lineTo(pt2.x,pt2.y);
        ctx.lineTo(pt3.x,pt3.y);
        ctx.closePath();
        ctx.stroke();
        ctx.fillStyle="rgba(255,255,0,0.10)";
        ctx.fill();
    }


    function analyzeTriangle(){

        // segment lengths
        var AB = Math.sqrt(Math.pow(pt2.x-pt1.x,2)+ Math.pow(pt2.y-pt1.y,2));    
        var BC = Math.sqrt(Math.pow(pt2.x-pt3.x,2)+ Math.pow(pt2.y-pt3.y,2)); 
        var AC = Math.sqrt(Math.pow(pt3.x-pt1.x,2)+ Math.pow(pt3.y-pt1.y,2));

        // angleB = using law of cosines
        var angleB = Math.acos((BC*BC+AB*AB-AC*AC)/(2*BC*AB));

        // transform translate = pt2
        var translate = pt2;

        // transform rotation = angleBC (based on slope of BC)
        var rotation = Math.atan2((pt3.y-pt2.y),(pt3.x-pt2.x));

        // transform skewX, based on angleB 
        var skewX = Math.tan(angleB-Math.PI/2);

        // rectangle height = triangle altitude
        var rectHeight = AB * Math.sin(angleB);

        // rectangle width = triangle BC
        var rectWidth = BC;

        return({
            translate:translate,
            rotation:rotation,
            skewX:skewX,
            rectHeight:rectHeight,
            rectWidth:rectWidth
        });

    }

}); // end $(function(){});
</script>

</head>

<body>
    <canvas id="canvas" width=350 height=350></canvas>
</body>
</html>
于 2013-08-12T17:32:46.363 に答える