PDA

View Full Version : سوال: رسم خطی در محور مختصات با زاویه داده شده



mostafa_shaeri_tj
شنبه 11 مهر 1388, 01:40 صبح
سلام.
توی برنام ای که دارم مینویسم , یک زاویه به دست میاد که باید خطی با اون زاویه روی محور
مختصات بکشم.
مثلا اگه زاویه ای که بدست اومد 30 درجه بود. باید یک خط با زاویه ی 30 درجه نسبت به محور عمودی بکشم.
ولی نمیدونم چطور باید مختصات خط رو بدست بیارم. اگه ممکنه راهنمایی کنید.

واسه روشن شدن قضیه توی paint مثال آوردم. ضمیمه رو ببینید.

ممنون از لطفتون

Saeed.Masoumi
شنبه 11 مهر 1388, 07:07 صبح
سلام با یکم ریاضی :لبخندساده:
عکس رو ببین مثه خودت تو عکس برات توضیح میدم یک نمونه کد هم برات می زارم
θ = زاویه داده شده در نتیجه اون قسمت از شکل که با آبی پر رنگ نشون دادم میشه زاویه متمم زاویه θ یعنی
90-θ خوب حالا تو شکل دقت کن اون قسمت زرد رنگ مقدار طول از مبدا ماست(x) حالا اون قسمت بنفش عرض از مبدا ماست (y) خوب ببین من طول وتر رو هم برابر 50 پیکسل در نظر می گیرم روابط ریاضی زیر رو دقت کن:



Cos(90-θ)=x/50 =>x=50*Cos(90-θ)
Sin(90-θ)=y/50 =>y=50*Sin(90-θ)

خوب با استفاده از این روابط می تونی مختصات نقطه انتهایی برای رسم بردارت رو بدست بیاری
حالا ریاضی بس :گیج: می ریم سر کد سی شارپ:
اول این تابع رو بساز (برای تبدیل عدد دابل به درجه) البته اگه زوایت به درجه نیست



private double double2angle(double number)
{
number = 90 - number;
return (Math.PI * (number / 180.0));
}

ببین من در این کد تتا رو بوسیله textBox1 می گیرم و یک پانل به سایز 200*200 دارم با نام panel1 که اومدم وسطش رو مبدا مختصات در نظر گرفتم یعنی 100و100 و خطم رو در همون panel1 رسم می کنم خودت هر جور می خوای تعمیمش بده:



double x, y;
const double Hypotenuse = 50;// Vatare ma
double number = double.Parse(textBox1.Text);
x = Math.Cos(double2angle(number)) * Hypotenuse;
y = Math.Sin(double2angle(number)) * Hypotenuse;
x = 100 + x;
y = 100 - y;
Graphics g = panel1.CreateGraphics();
Pen p1 = new Pen(Color.Red, 1);
Pen p2 = new Pen(Color.Blue, 3);
PointF axis = new PointF(100, 100);//O axis
PointF end = new PointF((float)x, (float)y);
g.DrawLine(p2,0,100,200,100 );//X axis
g.DrawLine(p2, 100, 0, 100, 200);//Y axis
g.DrawLine(p1, axis, end);//Our Hypotenuse

نکته:محور y ها در مانیتور هیچ شباهتی به حالت واقعی نداره یعنی هرچی y بزگتر بشه به پایین کشیده تر می شه برای همین توی کد اون قسمت y رو از صد کم کردم
:اشتباه::اشتباه::اشتباه:

SMRAH1
شنبه 11 مهر 1388, 10:21 صبح
سلام

اگر بخواهی پیشرفته تر عمل کنی،خوده دات نت ابزاری برای رسم گرافیکی خوبی با استفاده از نظریه ماتریس ها در اختیار قرار می ده.
اگر اطلاع داشته باشی،هر تغییر وضعیت شی در صفحه با یک ماتریس معادل است.مثلا انتقال شی (تغییر X یا Y یا هر دو در راستای خود به اندازه های متفاوت) یا دوران (چرخش شی حول یک نقطه) یا قرینه (نسبت به خط یا نقطه) و ... هر کدام یک ماتریس دارد (بحث پست قبل هم بر همین مبنا برای ماتریس دوران حول مبدا مختصات بود).
چنانچه از این مفاهیم اطلاع داری (با جستجو در اینترنت هم می توانی مقاله های خوبی در این زمینه پیدا کنی)،راه کار زیر را توصیه می کنم.
فرض کن می خواهی مربعی رسم کنی که اول یک بزرگ نمایی 2 به 1 در راستای X داشته باشد (راستای Y ثابت است) سپس 90 درچه حول محور مختصات بچرخد و در نهایت مبدا مختصات به نقطه (50و250) منتقل شود.هر کدام از این رفتار ها یک ماتریس دارد که به شکل زیر معرفی می شود:


Matrix myMatrix1 = new Matrix(2.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f); // Scale
Matrix myMatrix2 = new Matrix(0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f); // Rotate 90,
Matrix myMatrix3 = new Matrix(1.0f, 0.0f, 0.0f, 1.0f, 250.0f, 50.0f); // Translate

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


/*-----------------------------------------
* Use function Of MSDN.
* For find it,search program of enter each function.
* Note: Name of function may be changed.
------------------------------------------*/
private void MultiplyExample_SRT(PaintEventArgs e)
{
Pen myPen = new Pen(Color.Blue, 1);
Pen myPen2 = new Pen(Color.Red, 1);
// Set up the matrices.
Matrix myMatrix1 = new Matrix(2.0f, 0.0f, 0.0f, 1.0f, 0.0f, 0.0f); // Scale
Matrix myMatrix2 = new Matrix(0.0f, 1.0f, -1.0f, 0.0f, 0.0f, 0.0f); // Rotate 90,
Matrix myMatrix3 = new Matrix(1.0f, 0.0f, 0.0f, 1.0f, 250.0f, 50.0f); // Translate
// Display the elements of the starting matrix.
ListMatrixElements_SRT(e, myMatrix1, "Beginning Matrix", 3, 30);
// Multiply Matrix1 by Matrix 2.
myMatrix1.Multiply(myMatrix2, MatrixOrder.Append);
// Display the result of the multiplication of Matrix1 and
// Matrix2.
ListMatrixElements_SRT(e, myMatrix1, "Matrix After 1st Multiplication", 3, 50);
// Multiply the result from the pervious multiplication by
// Matrix3.
myMatrix1.Multiply(myMatrix3, MatrixOrder.Append);
// Display the result of the previous multiplication
// multiplied by Matrix3.
ListMatrixElements_SRT(e, myMatrix1, "Matrix After 2nd Multiplication", 3, 70);
// Draw the rectangle prior to transformation.
e.Graphics.DrawRectangle(myPen, 20, 20, 40, 40);
// Make the transformation.
e.Graphics.Transform = myMatrix1;
// Draw the rectangle after transformation.
e.Graphics.DrawRectangle(myPen2, 20, 20, 40, 40);

myPen.Dispose();
myPen2.Dispose();
}
//-------------------------------------------------------
// The following function is a helper function to
// list the contents of a matrix.
//-------------------------------------------------------
private void ListMatrixElements_SRT(PaintEventArgs e, Matrix matrix, string matrixName, int numElements, int y)
{
// Set up variables for drawing the array
// of points to the screen.
int i;
float x = 10, X = 200;
Font myFont = new Font("Arial", 10);
SolidBrush myBrush = new SolidBrush(Color.Black);
// Draw the matrix name to the screen.
e.Graphics.DrawString(matrixName + ": ", myFont, myBrush, x, y);
// Draw the set of path points and types to the screen.
for (i = 0; i < numElements; i++)
{
e.Graphics.DrawString(
matrix.Elements[i].ToString() + ", ",
myFont, myBrush, X, y);
X += 30;
}

myFont.Dispose();
myBrush.Dispose();
}

در واقع باید از خصوصیات Transform در شی Graphics برای انجام این عمل استفاده کنی.در شکل زیر هر دو مستطیل با یک دستور رسم شده اند.ولی مستطیل اول (آبی) به شکل معمولی و مستطیل قرمز (دوم) با اعمال ماتریس بالا رسم شده است.
برای اطلاعات بیشتر به MSDN مراجعه کن.

موفق باشی

اَرژنگ
شنبه 11 مهر 1388, 12:02 عصر
من طول وتر رو هم برابر 50 پیکسل در نظر می گیرم روابط ریاضی زیر رو دقت کن:



Cos(90-θ)=x/50 =>x=50*Cos(90-θ)
Sin(90-θ)=y/50 =>y=50*Sin(90-θ)




چرا عدد میزارید؟خوب پیش رفتید، در برنامه نویسی و ریاضیات قدرت واقعی در این است که یک حالت خاص را در نظر نگریم و جامعی کار کنیم، در آخرین لحظه میشه برایه حالت خاص عدد بزاریم. به جایه ۵۰ بهش بگو r .
به جایه ۹۰ درجه با رادیان کار کنیم، از همان اول بهتره (درجه یک چیزه من درآوردی در ریاضیات مفهومی ندارد فقط آدمها ازش استفاده میکنند)، به جایه ۹۰ از π/2
(با تشکر از جناب معصومی که اشتباهم درستش را گفتند، π/۲ میشه ۹۰ درجه نه π/۴!)
استفاده کنیم.


Cos(π/2 -θ)=x/r =>x=r*Cos(π/2-θ)
Sin(π/2-θ)=y/r =>y=r*Sin(π/2-θ)


حالا ریاضی بس :گیج: می ریم سر کد سی شارپ:
اول این تابع رو بساز (برای تبدیل عدد دابل به درجه) البته اگه زوایت به درجه نیست




private double double2angle(double number)
{
number = 90 - number;
return (Math.PI * (number / 180.0));
}


نه هنوز، نباید ریاضی را تمام کنیم، از همان اول بهتر است که با رادیان کار کنیم. درجه به رادیان این نصبت را دارند:
درجه π = ۱۸۰ ،
پس برایه تبدیل x درجه به رادیان میشه: x/180 رادیان. اسمه متد را میشه بهتر انتخواب کرد:

private double DegreeToRadian(double angle)
{
return Math.PI * angle / 180.0;
}





ببین من در این کد تتا رو بوسیله textBox1 می گیرم و یک پانل به سایز 200*200 دارم با نام panel1 که اومدم وسطش رو مبدا مختصات در نظر گرفتم یعنی 100و100 و خطم رو در همون panel1 رسم می کنم خودت هر جور می خوای تعمیمش بده:
.
.
.






تا جایی که میتونید جامع فکر کنید، روشتان درست است، ولی دارید با اضافه کردن تکست باکست، پانل، ۱۰۰ در ۱۰۰ بودن سایز پانل، راه حلتان را محدود میکنید. برایه مثال وسط پانل را داینامیک حساب کنید: panel1.Width/2 , panel1.Height/2 و غیره و ذالک..
یک نکته کوچک، بعد از استفاده از pen و Graphic باید Disposeاشان کنید: http://msdn.microsoft.com/en-us/library/aa287522(VS.71).aspx (http://msdn.microsoft.com/en-us/library/aa287522%28VS.71%29.aspx)







نکته:محور y ها در مانیتور هیچ شباهتی به حالت واقعی نداره یعنی هرچی y بزگتر بشه به پایین کشیده تر می شه برای همین توی کد اون قسمت y رو از صد کم کردم
:اشتباه::اشتباه::اشتباه:



من طول وتر رو هم برابر 50 پیکسل در نظر می گیرم روابط ریاضی زیر رو دقت کن:



Cos(90-θ)=x/50 =>x=50*Cos(90-θ)
Sin(90-θ)=y/50 =>y=50*Sin(90-θ)




چرا عدد میزارید؟خوب پیش رفتید، در برنامه نویسی و ریاضیات قدرت واقعی در این است که یک حالت خاص را در نظر نگریم و جامعی کار کنیم، در آخرین لحظه میشه برایه حالت خاص عدد بزاریم. به جایه ۵۰ بهش بگو r .
به جایه ۹۰ درجه با رادیان کار کنیم، از همان اول بهتره (درجه یک چیزه من درآوردی در ریاضیات مفهومی ندارد فقط آدمها ازش استفاده میکنند)، به جایه ۹۰ از π/4 استفاده کنیم.


Cos(π/4 -θ)=x/r =>x=r*Cos(π/4-θ)
Sin(π/4-θ)=y/r =>y=r*Sin(π/4-θ)


حالا ریاضی بس :گیج: می ریم سر کد سی شارپ:
اول این تابع رو بساز (برای تبدیل عدد دابل به درجه) البته اگه زوایت به درجه نیست




private double double2angle(double number)
{
number = 90 - number;
return (Math.PI * (number / 180.0));
}


نه هنوز، نباید ریاضی را تمام کنیم، از همان اول بهتر است که با رادیان کار کنیم. درجه به رادیان این نصبت را دارند:
درجه π = ۱۸۰ ،
پس برایه تبدیل x درجه به رادیان میشه: x/180 رادیان. اسمه متد را میشه بهتر انتخواب کرد:

private double DegreeToRadian(double angle)
{
return Math.PI * angle / 180.0;
}





ببین من در این کد تتا رو بوسیله textBox1 می گیرم و یک پانل به سایز 200*200 دارم با نام panel1 که اومدم وسطش رو مبدا مختصات در نظر گرفتم یعنی 100و100 و خطم رو در همون panel1 رسم می کنم خودت هر جور می خوای تعمیمش بده:
.
.
.






تا جایی که میتونید جامع فکر کنید، روشتان درست است، ولی دارید با اضافه کردن تکست باکست، پانل، ۱۰۰ در ۱۰۰ بودن سایز پانل، راه حلتان را محدود میکنید. برایه مثال وسط پانل را داینامیک حساب کنید: panel1.Width/2 , panel1.Height/2 و غیره و ذالک..
یک نکته کوچک، بعد از استفاده از pen و Graphic باید Disposeاشان کنید: http://msdn.microsoft.com/en-us/library/aa287522(VS.71).aspx (http://msdn.microsoft.com/en-us/library/aa287522%28VS.71%29.aspx)







نکته:محور y ها در مانیتور هیچ شباهتی به حالت واقعی نداره یعنی هرچی y بزگتر بشه به پایین کشیده تر می شه برای همین توی کد اون قسمت y رو از صد کم کردم
:اشتباه::اشتباه::اشتباه:







محور y در مونیتور از بالا دست چپ شروع میشه و منفی محور y در ریاضیات که بهش عادت داریم، براینه همین به جایه اینکه 100/2 + y را استفاده کنید، 100/2+y- را استفاده کردید.

در پست اسمراه، این روش با استفاده از ترانسفورم کردن به وسیله یک ماتریکس حل شده.
تنها چیزی که که بفکر من میرسه این است که آیا میشه با یک اینترفیس Graphic کار کنیم، و یک خط را به هر چی که این اینترفیس را ساپورت کنه بکشیم؟

mostafa_shaeri_tj
شنبه 11 مهر 1388, 13:20 عصر
با تشکر از همه شما.

من راه حل آقای معصومی رو البته با تغییراتی که آقای آرژنگ گفتن تو برنامم به کار بستم و کاملا جواب داد.
البته من همون تابع تبدیل به درجه ی آقای معصومی رو استفاده کردم و جواب هم داد.:تشویق:
پاسخ دوستمون آقای اسمراه هم عملی هست ولی خیلی سخت میشه. به نظر من بهترین روش همون روش آقای معصومی بود.:لبخندساده:

Saeed.Masoumi
شنبه 11 مهر 1388, 21:39 عصر
سلام مرسی از توجهتون آقای ارژنگ باعث افتخاره
یه چند تا نکته بگم شاید تو پست اول نیازی به این نبود ولی الان می گم
1- من به شخصه اگه قرار بود همیچین برنامه ای بنویسم با همون روش ماتریسی و روش معروف SRT استفاده می کردم ولی به قول دوستمون یکم سخته برای شروع برای همین برای آموزش برای شروع یکم زیادیه
2- آقای آرژنگ من وتر رو محدود نکردم به عنوان یک متغیر اون بالا تعریفش کردم که هر مقداری خواستند خودشان اعمال کنند
3- یک مثال سریع برای ساعت 6 صبح بود اون موقع خواب آلودگی باعث یک سری اعمال می شه :لبخند:
4-در ضمن اون تیکه که اومدو زاویه متمم رو حساب کردم می شد از راه نسبتهای متمم نیسز استفاده کرد تا اون قضیه منهای نود از بین بره
5-آقای آرژنگ آره حرف شما رو کاملا قبول دارم راجه به زاویه و رادیان یا حتی گراد ولی ما ایرانی ها چون ریاضی مون مال همون زمان گاوس و دکارت برا همین یکم سخته بخوایم تو یک مثال آموزشی راجه به تفاوت های گراد و رادیان و... صحبت کنیم
6- Nothing :قلب:
7-مرسی بابت اون نکته دیسپوز من آخه دستورات گرافیک رو همینجوری و بدون قوانین یاد گرفتم ممنون راجع به یاد آوریتون
8- ممنون راجع به یاد آوری اسم اون متد (همون مسئله خواب آلودگی و .... شما ببخشید)
در کل مرسی آقای آرژنگ

اَرژنگ
شنبه 11 مهر 1388, 22:27 عصر
سلام مرسی از توجهتون آقای ارژنگ باعث افتخاره
یه چند تا نکته بگم شاید تو پست اول نیازی به این نبود ولی الان می گم
1- من به شخصه اگه قرار بود همیچین برنامه ای بنویسم با همون روش ماتریسی و روش معروف SRT استفاده می کردم ولی به قول دوستمون یکم سخته برای شروع برای همین برای آموزش برای شروع یکم زیادیه
2- آقای آرژنگ من وتر رو محدود نکردم به عنوان یک متغیر اون بالا تعریفش کردم که هر مقداری خواستند خودشان اعمال کنند
3- یک مثال سریع برای ساعت 6 صبح بود اون موقع خواب آلودگی باعث یک سری اعمال می شه :لبخند:
4-در ضمن اون تیکه که اومدو زاویه متمم رو حساب کردم می شد از راه نسبتهای متمم نیسز استفاده کرد تا اون قضیه منهای نود از بین بره
5-آقای آرژنگ آره حرف شما رو کاملا قبول دارم راجه به زاویه و رادیان یا حتی گراد ولی ما ایرانی ها چون ریاضی مون مال همون زمان گاوس و دکارت برا همین یکم سخته بخوایم تو یک مثال آموزشی راجه به تفاوت های گراد و رادیان و... صحبت کنیم
6- یک غلط تایپی هم دارید پای دوم میشه 90 درجه.
7-مرسی بابت اون نکته دیسپوز من آخه دستورات گرافیک رو همینجوری و بدون قوانین یاد گرفتم ممنون راجع به یاد آوریتون
8- ممنون راجع به یاد آوری اسم اون متد (همون مسئله خواب آلودگی و .... شما ببخشید)
در کل مرسی آقای آرژنگ
شما هم شبها خوابتان نمیره!
درست میگید، ولی اشتباهم تایپی نبود، یادم رفته بود که پی بر دو میشه ۹۰، تو ذهنم فکر میکردم که پی تقسیم بر چهار میشه ۹۰! پیری و معرکه گیری همینه.
آنالیزتان تمیز ، درست و از لحاظ آموزشی هیچ چی کم نداشت.
به ندرتا میشه پستی مثل پست شما دید، پست من اشکال گیری نبود، فقط میخواستم به مفهومات از یک شکل دیگر نگاه انداخته بشه، و نظرات شما و یا هرکسی را در مورد طرز تفکرم جویا بشم.(که یکچیزی هم دوباره درستش یادم افتاد).
جدیدترین فرم برنامه نویسی، برنامه نویسی اکستریم هستش، که دونفر مداوم با هم جاشون را عوض میکنند، یکی کد میکنه و دیگری میتونه به کد از یک سطح دیگر نگاه کنه.
در ریاضیات هم باید بشه که باهم کار کرد، یکی یک کاری را انجام میده، میده به یکی دیگر که ادامه بده، بینشان همینطوری اشکالات و نقاتی را تنهایی هیچ وقت ممکن نبود پیدا کنند، تندتر پیدا میکنند.
با بررسی جواب شما، قابل شدم که در یک سطح دیگر به مسئله نگاه بندازم، ایده استفاده کردن از اینترفیس برایه کشیدن خط هم از همانجا امد.
در خارج تیمهایه حل کردن مسئله‌هایه ریاضی وجود دارد، که با هم به همین شکل کار میکنند.
بررسی پست شما برام جالب بود، ولی دلم نیومد که فکرم را بازگو نکنم، به این شکل من هم یک چیزی یاد گرفتم ، از اینکه اشتباهم را رفع کردید متشکرم.

sepidehfathali
دوشنبه 17 اردیبهشت 1397, 12:51 عصر
سلام دوستان. ممنون از راهنمایی های شما. استفاده کردیم. در این خصوص اگر بخواهیم برنامه ای به ازای بتا (اندازه زاویه ای که به راس نقطه x و y در محور مختصات است ) زاویه ای رسم کند و آلفا فاصله نیمساز بتا با محور شمال باشد و هیچ چیز هارد کر نباشد چه باید کرد؟ در واقع باید کمان رسم کند و اگر بتا 360 بود دایره بکشد.