ورود

View Full Version : گفتگو: محاسبه زاویه بین دو خط در canvas html5



shahrzad87
یک شنبه 22 دی 1392, 10:45 صبح
سلام
من برای محاسبه زاویه بین دو خط که با کلیک و کشیدن موس کشیده میشن از کد زیر استفاده کردم و همیشه مقدار زاویه رو درست حساب نمی کنه.


var theta1 = Math.atan2((firstYPoints - firstY2Points), (firstXPoints - firstX2Points));
var theta2 = Math.atan2((secondYPoints - firstY2Points),
(secondXPoints - firstX2Points));
var theta = (theta2 - theta1) * 180 / Math.PI;
if (theta >= 0) {
theta = (theta + 360) % 360;
}
else
theta = -theta;

Javidhb
دوشنبه 23 دی 1392, 02:38 صبح
var theta1 = Math.atan2((firstY2Points - firstYPoints), (firstX2Points - firstXPoints));
var theta2 = Math.atan2((secondY2Points - firstY2Points), (secondX2Points - firstXPoints));
var theta = (theta2 - theta1) * 180 / Math.PI;
if (theta >= 0) {
theta = (theta + 360) % 360;
}
else theta = -theta;


باید نقطه انتهایی منهای نقطه ابتدایی بشه (بترتیب برای y و بعد x)

shahrzad87
دوشنبه 23 دی 1392, 08:35 صبح
بله ممنون این رو هم قبلاً امتحان کردم اما جواب نمیده. گاهی زاویه که بیشتر از 290 یا 210 میشه ، زاویه در جهت مخالف رو حساب می کنه. یعنی ترتیب خاصی نداره این عدد متغیر هست (290، 210، ... ). بستگی به جهت خط ها داره. نمی دونم احتمالا الگوریتمی که استفاده کردم درست نیست :|

115305

در این حالت ها که خط تغییر می کنه زاویه طرف مقابل (200 به بالا) رو نشون می ده تا زمانی که به زاویه 180 برسه. باید برای موقعیت خط اول و دوم نسبت به هم شرط بنویسم اما نمی دونم دقیقا چی میشه.

Javidhb
دوشنبه 23 دی 1392, 14:06 عصر
کد پست دوم، کم ترین زاویه رو نشون میده. حالا ممکنه در جهت عقربه های ساعت باشه یا مخالف.

اما اگه درست متوجه منظورتون شده باشم... شما میخاید زوایه خط اول نسب به خط دوم رو فقط توی یه جهت (مثلا cw) محاسبه کنید:

دمــو (http://jsfiddle.net/4PLmw/)

توی این مثال برای محاسبه زاویه از خط اول (قرمز) شروع میکنه و در جهت خلاف عقربه های ساعت حرکت میکنه و تا به خط دوم (سبز) برسه.


<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>

canvas{
border:1px solid black;
}
</style>
</head>
<body>

<canvas id="myCnvs"></canvas>

<p id="center"></p>
<h3 id="result">result:</h3>

<div>
<p style="color:red;">line 1:</p>
x2: <input id="l1xCor" ype="text">
y2: <input id="l1yCor" ype="text">
<hr>
<p style="color:green;">line 2:</p>
x2: <input id="l2xCor" type="text">
y2: <input id="l2yCor" ype="text">
<button id="drawLine">Calculate</button>
</div>

<script type="text/javascript">
var btn = document.getElementById('drawLine'),
l1X = document.getElementById('l1xCor'),
l1Y = document.getElementById('l1yCor'),
l2X = document.getElementById('l2xCor'),
l2Y = document.getElementById('l2yCor'),
centerP = document.getElementById('center'),
result = document.getElementById('result'),
Canvas = document.getElementById('myCnvs'),
ctx = Canvas.getContext('2d');

var center = {
x1 : Canvas.width/2,
y1 : Canvas.height/2,
};

var line1 = {
x2 : center.x1 + 50,
y2 : center.y1
};

var line2 = {
x2 : center.x1,
y2 : center.y1 - 50
};

defaultValues();

function defaultValues(){
centerP.innerHTML = 'Center\'s Coordinates: ( '+center.x1+ ', ' +center.y1+ ' )';

l1X.value = line1.x2;
l1Y.value = line1.y2;

l2X.value = line2.x2;
l2Y.value = line2.y2;

drawLine(line1, 'red');
drawLine(line2, 'green');
};

btn.onclick = function(){
ctx.clearRect(0,0, Canvas.width, Canvas.height);

line1.x2 = l1X.value;
line1.y2 = l1Y.value;
line2.x2 = l2X.value;
line2.y2 = l2Y.value;

drawLine(line1, 'red');
drawLine(line2, 'green');

result.innerHTML = calculateDegree() +" deg";

drawCircle();
}


function calculateDegree(){
var angle1 = Math.atan2(line1.y2 - center.y1, line1.x2 - center.x1);
var angle2 = Math.atan2(line2.y2 - center.y1, line2.x2 - center.x1);

var def = (angle1 - angle2) * 180 / Math.PI;

if(def<0) def = (def + 360) % 360;

return def;
}

//draw a line
function drawLine(line, lineColor){
ctx.beginPath();
ctx.strokeStyle = lineColor;
ctx.moveTo(center.x1, center.y1);
ctx.lineTo(line.x2, line.y2);
ctx.stroke();
}

function drawCircle(){
var pi = Math.PI;
var startPoint = Math.atan2(line1.y2 - center.y1, line1.x2 - center.x1);
var endPoint = Math.atan2(line2.y2 - center.y1, line2.x2 - center.x1);

ctx.beginPath();
ctx.strokeStyle = 'orange';
ctx.arc(center.x1, center.y1, 10, startPoint, endPoint, true);
ctx.stroke();
}

</script>
</body>
</html>

shahrzad87
دوشنبه 23 دی 1392, 14:35 عصر
خیلی ممنون از راهنماییتون.
مشکل من این هست که موقعیت خط ها ثابت نیست و با کلیک و حرکت موس کشیده میشن. چیزی شبیه به نقاله در این برنامه دمو dicom viewer demo (http://demo.leadtools.com/MedicalViewer/members/WebViewer.aspx) که وقتی زاویه به 180 میرسه و بیشتر میشه زاویه در جهت مخالف رو نشون بده که کمتر از 180 هست.

Javidhb
سه شنبه 24 دی 1392, 00:07 صبح
منظورتون همچین چیزیه:
دمــو (http://jsfiddle.net/bn62B/1/)



<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
canvas{
border:1px solid black;
}
</style>

</head>
<body>

<canvas id="cnv"></canvas>
<p><span id="dgree">click</span> deg</p>


<script type="text/javascript">

var dgree = document.getElementById('dgree');
var CANVAS = document.getElementById('cnv');
var ctx = CANVAS.getContext('2d');
var steps = 0; //برای شمارش تعداد کلیک ها و رسم خطها

//این نقطه میشه دومین کلیک موس
var center = {
x1 : 0,
y1 : 0,
};

//اولین کلیک موس
var line1 = {
x2 : 0,
y2 : 0
};

//آخرین کلیک موس و انتهای خط دوم
var line2 = {
x2 : 0,
y2 : 0
};

CANVAS.onclick = function(e){
steps++;

switch(steps)
{
case 1:
//first point
line1.x2 = e.pageX - this.offsetLeft;
line1.y2 = e.pageY - this.offsetTop;
break;
case 2:
//second point
center.x1 = e.pageX - this.offsetLeft;
center.y1 = e.pageY - this.offsetTop;
drawLine(line1, 'red');
break;
case 4:
ctx.clearRect(0, 0, CANVAS.width, CANVAS.height);
steps = 0;
break;
}

};

//محاسبه زاویه با حرکت موس
CANVAS.onmousemove = function(e){
if(steps == 3)
{
ctx.clearRect(0, 0, CANVAS.width, CANVAS.height);
drawLine(line1, 'red');

line2.x2 = e.pageX - this.offsetLeft;
line2.y2 = e.pageY - this.offsetTop;
drawLine(line2, 'green');

dgree.innerHTML = findAngle();//محاسبه و نمایش زاویه
drawCircle();
}
};


//محاسبه زاویه
function findAngle(){
var angle1 = Math.atan2(line1.y2 - center.y1, line1.x2 - center.x1);
var angle2 = Math.atan2(line2.y2 - center.y1, line2.x2 - center.x1);

var def = (angle1 - angle2) * 180 / Math.PI;

if(def<0) def = (def + 360) % 360;

if(def > 180) def = 360 - def; //زاویه از 180 بیشتر نشه

return def;
}


//draw a line
function drawLine(line, lineColor){
ctx.beginPath();
ctx.strokeStyle = lineColor;
ctx.moveTo(center.x1, center.y1);
ctx.lineTo(line.x2, line.y2);
ctx.stroke();
}

//رسم دایره برای نشون دادن زاویه که اندازه اش محسابه میشه
function drawCircle(){
var startPoint = Math.atan2(line1.y2 - center.y1, line1.x2 - center.x1);
var endPoint = Math.atan2(line2.y2 - center.y1, line2.x2 - center.x1);

ctx.beginPath();
ctx.strokeStyle = 'orange';

if(endPoint < 0) ctx.arc(center.x1, center.y1, 20, startPoint, endPoint, false);
else ctx.arc(center.x1, center.y1, 20, startPoint, endPoint, true);

ctx.stroke();
}

</script>
</body>
</html>

shahrzad87
سه شنبه 24 دی 1392, 08:12 صبح
ممنون خیلی لطف کردید. بله دقیقا همین رو می خواستم که زاویه ای که نمایش میده بیشتر از 180 نشه. :لبخندساده:

فقط در وضعیتی که برای من زاویه بیشتر از 180 رو نشون میداد در دمو هم Arc رو در جهت مخالف نشون میده اما اندازه زاویه مربوط به جهت مخالفش هست و درسته. برای درست نشون دادن arc باید چه شرطی نوشت؟

115351

Javidhb
سه شنبه 24 دی 1392, 13:21 عصر
اشتباه از من بود... درست حسابی تستش نکردم..

تابع رسم آرک باید به این شکل تغییر کنه:

//رسم دایره برای نشون دادن زاویه که اندازه اش محسابه میشه
function drawCircle(){
var cw = true; //جهت حرکت آرک
var startArc, endArc; //نقطه شروع و پایان آرک

var startPoint = Math.atan2(line1.y2 - center.y1, line1.x2 - center.x1);
var endPoint = Math.atan2(line2.y2 - center.y1, line2.x2 - center.x1);
var def = (startPoint - endPoint) / Math.PI;

startArc = startPoint;
endArc = endPoint;

//محاسبه نقطه شروع و پایان و جهت آرک
if( ( def < 0 && def > -1 ) || def > 1){
cw = false;
}
else if(def < -1){
cw = false;
startArc = endPoint;
endArc = startPoint;
}
else{
cw = true;
}

ctx.beginPath();
ctx.strokeStyle = 'orange';
ctx.arc(center.x1, center.y1, 20, startArc, endArc, cw);
ctx.stroke();
}