PDA

View Full Version : آموزش: پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا



Saber_Fatholahi
چهارشنبه 18 بهمن 1391, 11:59 صبح
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 1# (http://www.dotnettips.info/post/1195/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 2# (http://www.dotnettips.info/post/1208/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 3# (http://www.dotnettips.info/post/1209/)
(http://www.dotnettips.info/post/1209/)پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 4# (http://www.dotnettips.info/post/1214/)

قصد داریم در طی چند پست متوالی، یک پروژه Paint را به صورت شی گرا پیاده سازی کنیم. خوب، پروژه ای که می‌خواهیم پیاده سازی کنیم باید دارای این امکانات باشه که مرحله به مرحله پیش میریم و پروزه کامل در نهایت در قسمت پروژه‌ها (http://www.dotnettips.info/projects) ی سایت مهندس وحید نصیری (http://www.dotnettips.info) قرار خواهد گرفت. (البته این سایت هم قدیما یک بخش پروژه داشت هرچی گشتم پیداش نکردم)



قابلیت ترسیم اشیا روی بوم گرافیکی دلخواه
قابلیت جابجایی اشیا
قابلیت تغییر رنگ اشیا
ترسیم اشیا توپر و تو خالی
تعیین پهنای خط شی ترسیم شده
تعیین رنگ پس زمینه در صورت تو پر بودن شی
قابلیت پیش نمایش رسم شکل در زمان ترسیم اشیا
توانایی انتخاب اشیا
تعیین عمق شی روی بوم گرافیکی مورد نظر
ترسیم اشیایی مانند خط، دایره، بیضی، مربع، مستطیل، لوزی، مثلث
قابلیت تغییر اندازه اشیا ترسیم شده

خوب برای شروع ابتدا یک پروژه از نوع Windows Application ایجاد می‌کنیم (البته برای این قسمت می‌توانیم یک پروژه Class Library ایجاد کنیم)
سپس یک پوشه به نام Models به پروزه اضافه نمایید.
خوب در این پروژه یک کلاس پایه به نام Shape در نظر می‌گیریم.
همه اشیا ما دارای نقطه شروع، نقطه پایان، رنگ قلم، حالت انتخاب، رنگ پس زمینه، نوع شی، .... می‌باشند که بعضی از خصوصیات را توسط خصوصیات دیگر محاسبه می‌کنیم. مثلا خاصیت Width و Height و X و Y توسط خصوصیات نقطه شروع و پایان می‌توانند محاسبه شوند.
ساختار کلاس‌های پروزه ما به صورت زیر است که مرحله به مرحله کلاس‌ها پیاده سازی خواهند شد.


http://barnamenevis.org/www.dotnettips.info/file/image?name=OOP1.pnghttp://www.dotnettips.info/file/image?name=OOP1.png

با توجه به تصویر بالا (البته این تجزیه تحلیل شخصی من بوده و دوستان به سلیقه خود ممکن است این ساختار را تغییر دهند)
نوع شمارشی ShapeType: در این نوع شمارشی انواع شی‌های موجود در پروژه معرفی شده است
محتوای این نوع به صورت زیر تعریف شده است:


namespace PWS.ObjectOrientedPaint.Models
{
/// <summary>
/// Shape Type in Paint
/// </summary>
public enum ShapeType
{
/// <summary>
/// هیچ
/// </summary>
None = 0,
/// <summary>
/// خط
/// </summary>
Line = 1,
/// <summary>
/// مربع
/// </summary>
Square = 2,
/// <summary>
/// مستطیل
/// </summary>
Rectangle = 3,
/// <summary>
/// بیضی
/// </summary>
Ellipse = 4,
/// <summary>
/// دایره
/// </summary>
Circle = 5,
/// <summary>
/// لوزی
/// </summary>
Diamond = 6,
/// <summary>
/// مثلث
/// </summary>
Triangle = 7,
}
}


انشاالله در پست‌های بعدی ما بقی کلاس‌ها به مرور پیاده سازی خواهند شد.
ادرس پست اصلی (http://http://www.dotnettips.info/post/1195/)

Saber_Fatholahi
چهارشنبه 18 بهمن 1391, 12:01 عصر
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 1# (http://www.dotnettips.info/post/1195/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 2# (http://www.dotnettips.info/post/1208/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 3# (http://www.dotnettips.info/post/1209/)
(http://www.dotnettips.info/post/1209/)پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 4# (http://www.dotnettips.info/post/1214/)

در ادامه مطلب پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 1# (http://www.dotnettips.info/post/1195/) به تشریح مابقی کلاس‌های برنامه می‌پردازیم.

با توجه به تجزیه و تحلیل انجام شده تمامی اشیا از کلاس پایه به نام Shape ارث بری دارند حال به توضیح کد‌های این کلاس می‌پردازیم. (به دلیل اینکه توضیحات این کلاس در دو پست نوشته خواهد شد برای این کلاس‌ها از partial class استفاده شده است)
using System;
using System.Drawing;

namespace PWS.ObjectOrientedPaint.Models
{
public abstract partial class Shape
{
#region Properties (16)

/// <summary>
/// Gets or sets the color of the background.
/// </summary>
/// <value>
/// The color of the background.
/// </value>
public Color BackgroundColor { get; set; }

/// <summary>
/// Gets or sets the brush.
/// </summary>
/// <value>
/// The brush.
/// </value>
public SolidBrush Brush
{
get
{
return new SolidBrush(BackgroundColor);
}
}

/// <summary>
/// Gets or sets the end point.
/// </summary>
/// <value>
/// The end point.
/// </value>
public PointF EndPoint { get; set; }

/// <summary>
/// Gets or sets the color of the fore.
/// </summary>
/// <value>
/// The color of the fore.
/// </value>
public Color ForeColor { get; set; }

/// <summary>
/// Gets or sets the height.
/// </summary>
/// <value>
/// The height.
/// </value>
public float Height
{
get
{
return Math.Abs(StartPoint.Y - EndPoint.Y);
}
set
{
if (value > 0)
EndPoint = new PointF(EndPoint.X, StartPoint.Y + value);
}
}

/// <summary>
/// Gets or sets a value indicating whether this instance is fill.
/// </summary>
/// <value>
/// <c>true</c> if this instance is fill; otherwise, <c>false</c>.
/// </value>
public bool IsFill { get; set; }

/// <summary>
/// Gets or sets a value indicating whether this instance is selected.
/// </summary>
/// <value>
/// <c>true</c> if this instance is selected; otherwise, <c>false</c>.
/// </value>
public bool IsSelected { get; set; }

/// <summary>
/// Gets or sets my pen.
/// </summary>
/// <value>
/// My pen.
/// </value>
public Pen Pen
{
get
{
return new Pen(ForeColor, Thickness);
}
}

/// <summary>
/// Gets or sets the type of the shape.
/// </summary>
/// <value>
/// The type of the shape.
/// </value>
public ShapeType ShapeType { get; protected set; }

/// <summary>
/// Gets the size.
/// </summary>
/// <value>
/// The size.
/// </value>
public SizeF Size
{
get
{
return new SizeF(Width, Height);
}
}

/// <summary>
/// Gets or sets the start point.
/// </summary>
/// <value>
/// The start point.
/// </value>
public PointF StartPoint { get; set; }

/// <summary>
/// Gets or sets the thickness.
/// </summary>
/// <value>
/// The thickness.
/// </value>
public byte Thickness { get; set; }

/// <summary>
/// Gets or sets the width.
/// </summary>
/// <value>
/// The width.
/// </value>
public float Width
{
get
{
return Math.Abs(StartPoint.X - EndPoint.X);
}
set
{
if (value > 0)
EndPoint = new PointF(StartPoint.X + value, EndPoint.Y);
}
}

/// <summary>
/// Gets or sets the X.
/// </summary>
/// <value>
/// The X.
/// </value>
public float X
{
get
{
return StartPoint.X;
}
set
{
if (value > 0)
StartPoint = new PointF(value, StartPoint.Y);
}
}

/// <summary>
/// Gets or sets the Y.
/// </summary>
/// <value>
/// The Y.
/// </value>
public float Y
{
get
{
return StartPoint.Y;
}
set
{
if (value > 0)
StartPoint = new PointF(StartPoint.X, value);
}
}

/// <summary>
/// Gets or sets the index of the Z.
/// </summary>
/// <value>
/// The index of the Z.
/// </value>
public int Zindex { get; set; }

#endregion Properties
}
}



ابتدا به تشریح خصوصیات کلاس می‌پردازیم:
خصوصیات:


BackgroundColor: در صورتی که شی مورد نظر به صورت توپررسم شود، این خاصیت رنگ پس زمینه شی را مشخص می‌کند.
Brush: یک خاصیت فقط خواندنی بوده که با توجه به خاصیت BackgroundColor یک الگوی توپر برای پر کردن زمینه شی می‌سازد (البته می‌توانستیم تعریف نکنیم)
StartPoint: نقطه شروع شی را در خود نگهداری می‌کند.
EndPoint: نقطه انتهای شی را در خود نگهداری می‌کند. (قبلا گفته شد که هر شی را در صورتی که در یک مستطیل فرض کنیم یک نقطه شروع و یک نقطه پایان دارد)
ForeColor: رنگ قلم ترسیم شی مورد نظر را تعیین می‌کند.
Height: ارتفاع شی مورد نظر را تعیین می‌کند ( این خصوصیت اختلاف عمودی StartPoint.Y و EndPoint.Y را محاسبه می‌کند و در زمان مقدار دهی EndPoint جدیدی ایجاد می‌کند).
Width: عرض شی مورد نظر را تعیین می‌کند ( این خصوصیت اختلاف افقیStartPoint.X و EndPoint.X را محاسبه می‌کند و در زمان مقدار دهی EndPoint جدیدی ایجاد می‌کند).
IsFill: این خصوصیت تعیین کننده توپر و یا توخالی بودن شی است.
IsSelected: این خاصیت تعیین می‌کند که آیا شی انتخاب شده است یا خیر (در زمان انتخاب شی چهار مربع کوچک روی شی رسم می‌شود).
Pen: قلم خط ترسیم شی را مشخص می‌کند. (قلم با ضخامت دلخواه)
ShapeType: این خصوصیت نوع شی را مشخص می‌کند (این خاصیت بیشتر برای زمان پیش نمایش ترسیم شی در زمان اجراست البته به نظر خودم اضافه هست اما راه بهتری به ذهنم نرسید)
Size: با استفاده از خصوصیات Height و Width ایجاد شده و تعیین کننده Size شی است.
Thickness: ضخامت خط ترسیمی شی را مشخص می‌کند، این خاصیت در خصوصیت Pen استفاده شده است.
X: مقدار افقی نقطه شروع شی را تعیین می‌کند در واقع StartPoint.X را برمی‌گرداند (این خاصیت اضافی بوده و جهت راحتی کار استفاده شده می‌توان آن را ننوشت).
Y: مقدار عمودی نقطه شروع شی را تعیین می‌کند در واقع StartPoint.Y را برمی‌گرداند (این خاصیت اضافی بوده و جهت راحتی کار استفاده شده می‌توان آن را ننوشت).
Zindex: در زمان ترسیم اشیا ممکن است اشیا روی هم ترسیم شوند، در واقع Zindex تعیین کننده عمق شی روی بوم گرافیکی است.



در پست بعدی به توضیح متدهای این کلاس می‌پردازیم.

ادرس پست اصلی (http://www.dotnettips.info/post/1208/)

Saber_Fatholahi
چهارشنبه 18 بهمن 1391, 12:05 عصر
در ادامه مطالب قبل
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 1# (http://www.dotnettips.info/post/1195/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 2# (http://www.dotnettips.info/post/1208/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 3# (http://www.dotnettips.info/post/1209/)
(http://www.dotnettips.info/post/1209/)پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 4# (http://www.dotnettips.info/post/1214/)


قبل از شروع توضیحات متد‌های کلاس Shape در ادامه پست‌های قبل در ^ (http://www.dotnettips.info/post/1195/) و ^ (http://www.dotnettips.info/post/1208/) ابتدا به تشریح یک تصویر می‌پردازیم.
http://www.dotnettips.info/file/image?name=001-35263b09d3d8466182d6a99d43bd6833.png
خوب همانگونه که در تصویر بالا مشاده می‌نمایید، برای رسم یک شی چهار حالت متفاوت ممکن است پیش بیاید. (دقت کنید که ربع اول محور مختصات روی بوم گرافیکی قرار گرفته است، در واقع گوشه بالا و سمت چپ بوم گرافیکی نقطه (0 و 0) محور مختصات است و عرض بوم گرافیکی محور X‌ها و ارتفاع بوم گرافیکی محور Y‌ها را نشان می‌دهد)



در این حالت StartPoint.X < EndPoint.X و StartPoint.Y < EndPoint.Y خواهد بود. (StartPoint نقطه ای است که ابتدا ماوس شروع به ترسیم می‌کند، و EndPoint زمانی است که ماوس رها شده و پایان ترسیم را مشخص می‌کند.)
در این حالت StartPoint.X > EndPoint.X و StartPoint.Y > EndPoint.Y خواهد بود.
در این حالت StartPoint.X > EndPoint.X و StartPoint.Y > EndPoint.Y خواهد بود.
در این حالت StartPoint.X < EndPoint.X و StartPoint.Y > EndPoint.Y خواهد بود.

در ادامه پست‌های قبل ادامه کد کلاس Shape را تشریح می‌کنیم.

using System;
using System.Drawing;

namespace PWS.ObjectOrientedPaint.Models
{
/// <summary>
/// Shape (Base Class)
/// </summary>
public abstract partial class Shape
{
#region Constructors (2)

/// <summary>
/// Initializes a new instance of the <see cref="Shape" /> class.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="zIndex">Index of the z.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="isFill">if set to <c>true</c> [is fill].</param>
/// <param name="backgroundColor">Color of the background.</param>
protected Shape(PointF startPoint, PointF endPoint, int zIndex, Color foreColor, byte thickness, bool isFill, Color backgroundColor)
{
CalulateLocationAndSize(startPoint, endPoint);
Zindex = zIndex;
ForeColor = foreColor;
Thickness = thickness;
IsFill = isFill;
BackgroundColor = backgroundColor;
}

/// <summary>
/// Initializes a new instance of the <see cref="Shape" /> class.
/// </summary>
protected Shape() { }

#endregion Constructors

#region Methods (9)

// Public Methods (8)

/// <summary>
/// Draws the specified g.
/// </summary>
/// <param name="g">The g.</param>
public virtual void Draw(Graphics g)
{
if (!IsSelected) return;
float diff = Thickness + 4;
Color myColor = Color.DarkSeaGreen;
g.DrawString(String.Format("({0},{1})", StartPoint.X, StartPoint.Y), new Font(new FontFamily("Tahoma"), 10), new SolidBrush(myColor), StartPoint.X - 20, StartPoint.Y - 25);
g.DrawString(String.Format("({0},{1})", EndPoint.X, EndPoint.Y), new Font(new FontFamily("Tahoma"), 10), new SolidBrush(myColor), EndPoint.X - 20, EndPoint.Y + 5);
if (ShapeType != ShapeType.Line)
{
g.DrawRectangle(new Pen(myColor), X, Y, Width, Height);

// 1 2 3
// 8 4
// 7 6 5
var point1 = new PointF(StartPoint.X - diff / 2, StartPoint.Y - diff / 2);
var point2 = new PointF((StartPoint.X - diff / 2 + EndPoint.X) / 2, StartPoint.Y - diff / 2);
var point3 = new PointF(EndPoint.X - diff / 2, StartPoint.Y - diff / 2);
var point4 = new PointF(EndPoint.X - diff / 2, (EndPoint.Y + StartPoint.Y) / 2 - diff / 2);
var point5 = new PointF(EndPoint.X - diff / 2, EndPoint.Y - diff / 2);
var point6 = new PointF((StartPoint.X - diff / 2 + EndPoint.X) / 2, EndPoint.Y - diff / 2);
var point7 = new PointF(StartPoint.X - diff / 2, EndPoint.Y - diff / 2);
var point8 = new PointF(StartPoint.X - diff / 2, (EndPoint.Y + StartPoint.Y) / 2 - diff / 2);


g.FillRectangle(new SolidBrush(myColor), point1.X, point1.Y, diff, diff);
g.FillRectangle(new SolidBrush(myColor), point2.X, point2.Y, diff, diff);
g.FillRectangle(new SolidBrush(myColor), point3.X, point3.Y, diff, diff);
g.FillRectangle(new SolidBrush(myColor), point4.X, point4.Y, diff, diff);
g.FillRectangle(new SolidBrush(myColor), point5.X, point5.Y, diff, diff);
g.FillRectangle(new SolidBrush(myColor), point6.X, point6.Y, diff, diff);
g.FillRectangle(new SolidBrush(myColor), point7.X, point7.Y, diff, diff);
g.FillRectangle(new SolidBrush(myColor), point8.X, point8.Y, diff, diff);
}
else
{
var point1 = new PointF(StartPoint.X - diff / 2, StartPoint.Y - diff / 2);
var point2 = new PointF(EndPoint.X - diff / 2, EndPoint.Y - diff / 2);
g.FillRectangle(new SolidBrush(myColor), point1.X, point1.Y, diff, diff);
g.FillRectangle(new SolidBrush(myColor), point2.X, point2.Y, diff, diff);
}
}

/// <summary>
/// Draws the preview.
/// </summary>
/// <param name="g">The g.</param>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="foreColor">Color of the fore.</param>
public void DrawPreview(Graphics g, PointF startPoint, PointF endPoint, Color foreColor)
{
DrawPreview(g, startPoint, endPoint, foreColor, Thickness, IsFill, BackgroundColor, ShapeType);
}

/// <summary>
/// Draws the preview.
/// </summary>
/// <param name="g">The g.</param>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="isFill">if set to <c>true</c> [is fill].</param>
/// <param name="backgroundColor">Color of the background.</param>
/// <param name="shapeType">Type of the shape.</param>
public static void DrawPreview(Graphics g, PointF startPoint, PointF endPoint, Color foreColor, byte thickness, bool isFill, Color backgroundColor, ShapeType shapeType)
{
float x = 0, y = 0;
float width = Math.Abs(endPoint.X - startPoint.X);
float height = Math.Abs(endPoint.Y - startPoint.Y);
if (startPoint.X <= endPoint.X && startPoint.Y <= endPoint.Y)
{
x = startPoint.X;
y = startPoint.Y;
}
else if (startPoint.X >= endPoint.X && startPoint.Y >= endPoint.Y)
{
x = endPoint.X;
y = endPoint.Y;
}
else if (startPoint.X >= endPoint.X && startPoint.Y <= endPoint.Y)
{
x = endPoint.X;
y = startPoint.Y;
}
else if (startPoint.X <= endPoint.X && startPoint.Y >= endPoint.Y)
{
x = startPoint.X;
y = endPoint.Y;
}

switch (shapeType)
{
case ShapeType.Ellipse:
if (isFill)
g.FillEllipse(new SolidBrush(backgroundColor), x, y, width, height);
//else
g.DrawEllipse(new Pen(foreColor, thickness), x, y, width, height);
break;
case ShapeType.Rectangle:
if (isFill)
g.FillRectangle(new SolidBrush(backgroundColor), x, y, width, height);
//else
g.DrawRectangle(new Pen(foreColor, thickness), x, y, width, height);
break;
case ShapeType.Circle:
float raduis = Math.Max(width, height);

if (isFill)
g.FillEllipse(new SolidBrush(backgroundColor), x, y, raduis, raduis);
//else
g.DrawEllipse(new Pen(foreColor, thickness), x, y, raduis, raduis);
break;
case ShapeType.Square:
float side = Math.Max(width, height);

if (isFill)
g.FillRectangle(new SolidBrush(backgroundColor), x, y, side, side);
//else
g.DrawRectangle(new Pen(foreColor, thickness), x, y, side, side);
break;
case ShapeType.Line:
g.DrawLine(new Pen(foreColor, thickness), startPoint, endPoint);
break;
case ShapeType.Diamond:
var points = new PointF[4];
points[0] = new PointF(x + width / 2, y);
points[1] = new PointF(x + width, y + height / 2);
points[2] = new PointF(x + width / 2, y + height);
points[3] = new PointF(x, y + height / 2);
if (isFill)
g.FillPolygon(new SolidBrush(backgroundColor), points);
//else
g.DrawPolygon(new Pen(foreColor, thickness), points);
break;
case ShapeType.Triangle:
var tPoints = new PointF[3];
tPoints[0] = new PointF(x + width / 2, y);
tPoints[1] = new PointF(x + width, y + height);
tPoints[2] = new PointF(x, y + height);
if (isFill)
g.FillPolygon(new SolidBrush(backgroundColor), tPoints);
//else
g.DrawPolygon(new Pen(foreColor, thickness), tPoints);
break;
}
if (shapeType != ShapeType.Line)
{
g.DrawString(String.Format("({0},{1})", x, y), new Font(new FontFamily("Tahoma"), 10), new SolidBrush(foreColor), x - 20, y - 25);
g.DrawString(String.Format("({0},{1})", x + width, y + height), new Font(new FontFamily("Tahoma"), 10), new SolidBrush(foreColor), x + width - 20, y + height + 5);
}
else
{
g.DrawString(String.Format("({0},{1})", startPoint.X, startPoint.Y), new Font(new FontFamily("Tahoma"), 10), new SolidBrush(foreColor), startPoint.X - 20, startPoint.Y - 25);
g.DrawString(String.Format("({0},{1})", endPoint.X, endPoint.Y), new Font(new FontFamily("Tahoma"), 10), new SolidBrush(foreColor), endPoint.X - 20, endPoint.Y + 5);
}

}

/// <summary>
/// Points the in sahpe.
/// </summary>
/// <param name="point">The point.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns>
/// <c>true</c> if [has point in sahpe] [the specified point]; otherwise, <c>false</c>.
/// </returns>
public virtual bool HasPointInSahpe(PointF point, byte tolerance = 5)
{
return point.X > (StartPoint.X - tolerance) && point.X < (EndPoint.X + tolerance) && point.Y > (StartPoint.Y - tolerance) && point.Y < (EndPoint.Y + tolerance);
}

/// <summary>
/// Moves the specified location.
/// </summary>
/// <param name="location">The location.</param>
/// <returns></returns>
public virtual PointF Move(Point location)
{
StartPoint = new PointF(location.X, location.Y);
EndPoint = new PointF(location.X + Width, location.Y + Height);
return StartPoint;
}

/// <summary>
/// Moves the specified dx.
/// </summary>
/// <param name="dx">The dx.</param>
/// <param name="dy">The dy.</param>
/// <returns></returns>
public virtual PointF Move(int dx, int dy)
{
StartPoint = new PointF(StartPoint.X + dx, StartPoint.Y + dy);
EndPoint = new PointF(EndPoint.X + dx, EndPoint.Y + dy);
return StartPoint;
}

/// <summary>
/// Resizes the specified dx.
/// </summary>
/// <param name="dx">The dx.</param>
/// <param name="dy">The dy.</param>
/// <returns></returns>
public virtual SizeF Resize(int dx, int dy)
{
EndPoint = new PointF(EndPoint.X + dx, EndPoint.Y + dy);
return new SizeF(Width, Height);
}

/// <summary>
/// Resizes the specified start point.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="currentPoint">The current point.</param>
public virtual void Resize(PointF startPoint, PointF currentPoint)
{
var dx = (int)(currentPoint.X - startPoint.X);
var dy = (int)(currentPoint.Y - startPoint.Y);
if (startPoint.X >= X - 5 && startPoint.X <= X + 5)
{
StartPoint = new PointF(currentPoint.X, StartPoint.Y);
if (ShapeType == ShapeType.Circle || ShapeType == ShapeType.Square)
{
Height = Width;
}
}
else if (startPoint.X >= EndPoint.X - 5 && startPoint.X <= EndPoint.X + 5)
{
Width += dx;
if (ShapeType == ShapeType.Circle || ShapeType == ShapeType.Square)
{
Height = Width;
}
}
else if (startPoint.Y >= Y - 5 && startPoint.Y <= Y + 5)
{
Y = currentPoint.Y;
if (ShapeType == ShapeType.Circle || ShapeType == ShapeType.Square)
{
Width = Height;
}
}
else if (startPoint.Y >= EndPoint.Y - 5 && startPoint.Y <= EndPoint.Y + 5)
{
Height += dy;
if (ShapeType == ShapeType.Circle || ShapeType == ShapeType.Square)
{
Width = Height;
}
}
}
// Private Methods (1)

/// <summary>
/// Calulates the size of the location and.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
private void CalulateLocationAndSize(PointF startPoint, PointF endPoint)
{
float x = 0, y = 0;
float width = Math.Abs(endPoint.X - startPoint.X);
float height = Math.Abs(endPoint.Y - startPoint.Y);
if (startPoint.X <= endPoint.X && startPoint.Y <= endPoint.Y)
{
x = startPoint.X;
y = startPoint.Y;
}
else if (startPoint.X >= endPoint.X && startPoint.Y >= endPoint.Y)
{
x = endPoint.X;
y = endPoint.Y;
}
else if (startPoint.X >= endPoint.X && startPoint.Y <= endPoint.Y)
{
x = endPoint.X;
y = startPoint.Y;
}
else if (startPoint.X <= endPoint.X && startPoint.Y >= endPoint.Y)
{
x = startPoint.X;
y = endPoint.Y;
}
StartPoint = new PointF(x, y);
EndPoint = new PointF(X + width, Y + height);
}

#endregion Methods
}
}



حال به تشریح سازنده کلاس می‌پردازیم:


Shape: پارامترهای این سازنده به ترتیب عبارتند از نقطه شروع، نقطه پایان، عمق شی، رنگ قلم، ضخامت خط، آیا شی توپر باشد؟، و رنگ پر کردن شی، در این سازنده ابتدا توسط متدی به نام CalulateLocationAndSize(startPoint, endPoint); b نقاط ابتدا و انتهای شی مورد نظر تنظیم می‌شود، در متد مذکور بررسی می‌شود در صورتی که نقاط شروع و پایان یکی از حالت‌های 1 ، 2، 3، 4 از تصویر ابتدا پست باشد همگی تبدیل به حالت 1 خواهد شد.

سپس به تشریح متدهای کلاس Shape می‌پردازیم:


Draw: این متد دارای یک پارامتر ورودی است که بوم گرافیکی مورد نظر می‌باشد، در واقع شی مورد نظر خود را بروی این بوم گرافیکی ترسیم می‌کند. در کلاس پایه کار این متد زیاد پیچیده نیست، در صورتی که شی در حالت انتخاب باشد (IsSelected = true) بروی شی مورد نظر 8 مربع کوچک ترسیم می‌شود و اگر شی مورد نظر خط باشد دو مربع کوچک در طرفین خط رسم می‌شود که نشان دهنده انتخاب شدن شی مورد نظر است. این متد به صورت virtual تعریف شده است یعنی کلاس هایی که از Shape ارث میبرند می‌توانند این متد را برای خود از نو بازنویسی کرده (override کنند) و تغییر رفتار دهند.
DrawPreview : این متد یک متد عمومی بود و مختص هر شی است، وظیفه این متد ترسیم پیش نمایش شی مورد نظر در زمان جابجایی و ترسیم می‌باشد، پارامترهای آن عبارتند از : بوم گرافیکی، نقطه شروع، نقطه پایان و رنگ قلم ترسیم پیش نمایش شی، خود این متد در بدنه خود متد static بعدی با همین نام را فراخوانی خواهد کرد.
DrawPreview : کار این متد دقیقا مانند متد قبلی می‌باشد (در واقع اصل کار را برای پیش نمایش همین متد انجام می‌دهد)، پارامترهای آن عبارتند از : بوم گرافیکی، نقطه شروع، نقطه پایان و رنگ قلم ترسیم پیش نمایش شی، ضخامت خط، آیا شی توپر باشد؟، رنگ پس زمینه شی ، و نوع شی ترسیمی می‌باشد. (البته خیلی تلاش کردم این دو متد را با Func و Action پیاده سازی کنم اما نشد اگر دوستان نظری دارن خوشحال می‌شم پیشنهاد بدن)؛ خوب اما کار این متد به این صورت است ابتدا نقاط شروه و پایان را بررسی کرده و آنها را اصلاح می‌کند؛ سپس با توجه به نوع شی مورد نظر آنر ترسیم می‌کند، البته با نمایش مقادیر نقطه شروع و پایان.

HasPointInSahpe : این متد نیز به صورت virtual تعریف شده است دارای خروجی بولین می‌باشد. پارامتر‌های این متد عبارتند از یک نقطه و یک عدد که نشان دهنده تلرانش نقطه بر حسب پیکسل می‌باشد. کار این متد این است که یک نقطه را گرفته و بررسی می‌کند که آیا نقطه مورد نظر با تلرانس وارد شده آیا در داخل شی واقع شده است یا خیر (مثلا وجود نقطه در مستطیل یا وجود نقطه در دایره فرمول‌های متفاوتی دارند که در اینجا پیش فرض برای تمامی اشیا حالت مستطیل در نظر گرفته شده که می‌توانید آنها را بازنویسی (override) کنید).
Move: این متد به عنوان پارامتر یک نقطه را گرفته و شی مورد نظر را به آن نقطه منتقل می‌کند در واقع نقطه شروع و پایان ترسیم شی را تغییر می‌دهد.
Move: این متد نیز برای جابجایی شی به کار می‌رود، این متد دارای پارامترهای جابجابی در راستای محور Xها , جابجایی در راستای محور Yها؛ و شی مورد نظر را به آن نقطه منتقل می‌کند در واقع نقطه شروع و پایان ترسیم شی را با توجه به پارامترهای ورودی تغییر می‌دهد.
Resize: این متد نیز برای تغییر اندازه شی به کار می‌رود، این متد دارای پارامترهای تغییر اندازه در راستای محور Xها , تغییر اندازه در راستای محور Yها می‌باشد و نقطه پایان شی مورد نظر را تغییر می‌دهد اما نقطه شروع تغییری نمی‌کند.
Resize: این متد نیز برای تغییر اندازه شی به کار می‌رود، در زمان تغییر اندازه شی با ماوس ابتدا یک نقطه شروع وجود دارد که ماوس در آن نقطه کلیک شده و شروع به درگ کردن شی جهت تغییر اندازه می‌کند (پارامتر اول این متد نقطه شروع درگ کردن جهت تغییر اندازه را مشخص می‌کند startPoint)، سپس در یک نقطه ای درگ کردن تمام می‌شود در این نقطه باید شی تغییر اندازه پیدا کرده و ترسیم شود ( پارامتر دوم این متد نقطه مذکور می‌باشد currentLocation). سپس با توجه با این دو نقطه بررسی می‌شود که تغییر اندازه در کدام جهت صورت گرفته است و اعداد جهت تغییرات نقاط شروع و پایان شی مورد نظر محاسبه می‌شوند. (مثلا تغییر اندازه در مستطیل از ضلع بالا به طرفین، یا از ضلع سمت راست به طرفین و ....). البته برای مربع و دایره باید کاری کنیم که طول و عرض تغییر اندازه یکسان باشد.
CalulateLocationAndSize: این متد که در سازنده کلاس استفاده شده در واقع دو نقطه شروع و پایان را گرفته و با توجه به تصویر ابتدای پست حالت‌های 1 و 2 و3 و 4 را به حالت 1 تبدیل کرده و StartPoint و EndPoint را اصلاح می‌کند.

تذکر: متد‌های Move، Resize و HasPointInShape به صورت virtual تعریف شده تا کلاس‌های مشتق شده در صورت نیاز خود کد رفتار مورد نظر خود را override کرده یا از همین رفتار استفاده نمایند.
خوشحال می‌شم در صورتی که در Refactoring کد نوشته شده با من همکاری کنید.

در پست‌های آینده به بررسی و پیاده سازی دیگر کلاس‌ها خواهیم پرداخت.

آدرس پست اصلی (http://www.dotnettips.info/post/1209/)

Saber_Fatholahi
جمعه 20 بهمن 1391, 23:54 عصر
ظاهرا کسی حال نداره این پروژه پیگیری بشه

fakhravari
شنبه 21 بهمن 1391, 00:22 صبح
داش صابر بیشتر دوستان مشتاق سمپل برنامه هستن:لبخند:

Shahram_12
شنبه 21 بهمن 1391, 03:57 صبح
اگر محبت کنی و ادامه بدین ممنون میشیم

masoud_z_65
شنبه 21 بهمن 1391, 09:49 صبح
آقای فتح الهی من از سایت دات نت تیپس دارم پیگیری میکنم....بازم ممنون

wolf_majid
شنبه 21 بهمن 1391, 11:20 صبح
شما ادامه بدید
مطمئنا" بعد از مدتی طرفداراش رو پیدا میکنه

website.expert
شنبه 21 بهمن 1391, 14:50 عصر
ظاهرا کسی حال نداره این پروژه پیگیری بشه

با سلام،
اول از همه ممنون بابت زحمتی که کشیدید.
من تازه تاپیک رو دیدم، و خیلی هم برای پیگیری پروژه مشتاقم.
Please continue:قلب:

Saber_Fatholahi
یک شنبه 22 بهمن 1391, 23:06 عصر
در ادامه مطالب قبل:
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 1# (http://www.dotnettips.info/post/1195/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 2# (http://www.dotnettips.info/post/1208/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 3# (http://www.dotnettips.info/post/1209/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 4# (http://www.dotnettips.info/post/1214/)

در این پست به بررسی کلاس Triangle جهت رسم مثلث و کلاس Diamond جهت رسم لوزی می‌پردازیم.

using System.Drawing;

namespace PWS.ObjectOrientedPaint.Models
{
/// <summary>
/// Triangle
/// </summary>
public class Triangle : Shape
{
#region Constructors (2)

/// <summary>
/// Initializes a new instance of the <see cref="Triangle" /> class.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="zIndex">Index of the z.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="isFill">if set to <c>true</c> [is fill].</param>
/// <param name="backgroundColor">Color of the background.</param>
public Triangle(PointF startPoint, PointF endPoint, int zIndex, Color foreColor, byte thickness, bool isFill, Color backgroundColor)
: base(startPoint, endPoint, zIndex, foreColor, thickness, isFill, backgroundColor)
{
ShapeType = ShapeType.Triangle;
}


/// <summary>
/// Initializes a new instance of the <see cref="Triangle" /> class.
/// </summary>
public Triangle()
{
ShapeType = ShapeType.Triangle;
}

#endregion Constructors

#region Methods (1)

// Public Methods (1)

/// <summary>
/// Draws the specified g.
/// </summary>
/// <param name="g">The g.</param>
public override void Draw(Graphics g)
{
var points = new PointF[3];
points[0] = new PointF(X + Width / 2, Y);
points[1] = new PointF(X + Width, Y + Height);
points[2] = new PointF(X, Y + Height);
if (IsFill)
g.FillPolygon(BackgroundBrush, points);
g.DrawPolygon(new Pen(ForeColor, Thickness), points);
base.Draw(g);
}

#endregion Methods
}
}




همانگونه که مشاهده می‌کنید کلاس مثلث از کلاس Shape ارث برده و تشکیل شده از یک سازنده و بازنویسی (override) متد Draw می‌باشد، البته متد HasPointInSahpe در کلاس پایه قاعدتا باید بازنویسی شود، برای تشخیص وجود نقطه در شکل مثلث، (اگر دوستان فرمولش می‌دونن ممنون می‌شم در اختیار بذارن). در متد Draw سه نقطه مثلث در نظر گرفته شده که بر طبق آن با استفاده از متدهای رسم منحنی اقدام به رسم مثلث توپر یا تو خالی نموده‌ایم.

کلاس لوزی نیز دقیقا مانند کلاس مثلث عمل می‌کند.


using System.Drawing;

namespace PWS.ObjectOrientedPaint.Models
{
/// <summary>
/// Diamond
/// </summary>
public class Diamond : Shape
{
#region Constructors (2)

/// <summary>
/// Initializes a new instance of the <see cref="Diamond" /> class.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="zIndex">Index of the z.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="isFill">if set to <c>true</c> [is fill].</param>
/// <param name="backgroundColor">Color of the background.</param>
public Diamond(PointF startPoint, PointF endPoint, int zIndex, Color foreColor, byte thickness, bool isFill, Color backgroundColor)
: base(startPoint, endPoint, zIndex, foreColor, thickness, isFill, backgroundColor)
{
ShapeType = ShapeType.Diamond;
}

/// <summary>
/// Initializes a new instance of the <see cref="Diamond" /> class.
/// </summary>
public Diamond()
{
ShapeType = ShapeType.Diamond;
}

#endregion Constructors

#region Methods (1)

// Public Methods (1)

/// <summary>
/// Draws the specified g.
/// </summary>
/// <param name="g">The g.</param>
public override void Draw(Graphics g)
{
var points = new PointF[4];
points[0] = new PointF(X + Width / 2, Y);
points[1] = new PointF(X + Width, Y + Height / 2);
points[2] = new PointF(X + Width / 2, Y + Height);
points[3] = new PointF(X, Y + Height / 2);
if (IsFill)
g.FillPolygon(BackgroundBrush, points);
g.DrawPolygon(new Pen(ForeColor, Thickness), points);
base.Draw(g);
}

#endregion Methods
}
}


این کلاس نیز از کلاس Shape ارث برده و دارای یک سازنده بوده و متد Draw را ازنو بازنویسی می‌کند، این متد نیز با استفاده از چهار نقطه و استفاده از متد رسم منحنی در دات نت اقدام به طراحی لوزی توپر یا تو خالی می‌کند، متد HasPointInSahpe در کلاس پایه قاعدتا باید بازنویسی شود، برای تشخیص وجود نقطه در شکل لوزی، برای رسم لوزی توپر نیز خصوصیت BackgroundBrush استفاده کرده و شی توپر را رسم می‌کند.

مباحث رسم مستطیل و مربع، دایره و بیضی در پست‌های بعد بررسی خواهند شد.

موفق وموید باشید.

آدرس پست اصلی (http://www.dotnettips.info/post/1214/)

Saber_Fatholahi
پنج شنبه 03 اسفند 1391, 00:17 صبح
در ادامه مطلب پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 4# (http://www.dotnettips.info/post/1214/) به تشریح مابقی کلاس‌های برنامه می‌پردازیم.

در این پست به شرح کلاس Rectangle جهت رسم مستطیل و Square جهت رسم مربع می‌پردازیم
using System.Drawing;

namespace PWS.ObjectOrientedPaint.Models
{
/// <summary>
/// Rectangle
/// </summary>
public class Rectangle : Shape
{
#region Constructors (2)

/// <summary>
/// Initializes a new instance of the <see cref="Rectangle" /> class.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="zIndex">Index of the z.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="isFill">if set to <c>true</c> [is fill].</param>
/// <param name="backgroundColor">Color of the background.</param>
public Rectangle(PointF startPoint, PointF endPoint, int zIndex, Color foreColor, byte thickness, bool isFill, Color backgroundColor)
: base(startPoint, endPoint, zIndex, foreColor, thickness, isFill, backgroundColor)
{
ShapeType = ShapeType.Rectangle;
}

/// <summary>
/// Initializes a new instance of the <see cref="Rectangle" /> class.
/// </summary>
public Rectangle()
{
ShapeType = ShapeType.Rectangle;
}

#endregion Constructors

#region Methods (1)

// Public Methods (1)

/// <summary>
/// Draws the specified g.
/// </summary>
/// <param name="g">The g.</param>
public override void Draw(Graphics g)
{
if (IsFill)
g.FillRectangle(BackgroundBrush, StartPoint.X, StartPoint.Y, Width, Height);
g.DrawRectangle(Pen, StartPoint.X, StartPoint.Y, Width, Height);
base.Draw(g);
}

#endregion Methods
}
}


کلاس Rectangle از کلاس پایه طراحی شده در ^ (http://www.dotnettips.info/post/1208/) ارث بری دارد. این کلاس ساده بوده و تنها شامل یک سازنده و متد ترسیم شی مستطیل می‌باشد.

کلاس بعدی کلاس Square می‌باشد، که از کلاس بالا (Rectangle) ارث بری داشته است، کد‌های این کلاس را در زیر مشاهده می‌کنید.
using System;
using System.Drawing;

namespace PWS.ObjectOrientedPaint.Models
{
/// <summary>
/// Square
/// </summary>
public class Square : Rectangle
{
#region Constructors (2)

/// <summary>
/// Initializes a new instance of the <see cref="Square" /> class.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="zIndex">Index of the z.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="isFill">if set to <c>true</c> [is fill].</param>
/// <param name="backgroundColor">Color of the background.</param>
public Square(PointF startPoint, PointF endPoint, int zIndex, Color foreColor, byte thickness, bool isFill, Color backgroundColor)
{
float x = 0, y = 0;
float width = Math.Abs(endPoint.X - startPoint.X);
float height = Math.Abs(endPoint.Y - startPoint.Y);
if (startPoint.X <= endPoint.X && startPoint.Y <= endPoint.Y)
{
x = startPoint.X;
y = startPoint.Y;
}
else if (startPoint.X >= endPoint.X && startPoint.Y >= endPoint.Y)
{
x = endPoint.X;
y = endPoint.Y;
}
else if (startPoint.X >= endPoint.X && startPoint.Y <= endPoint.Y)
{
x = endPoint.X;
y = startPoint.Y;
}
else if (startPoint.X <= endPoint.X && startPoint.Y >= endPoint.Y)
{
x = startPoint.X;
y = endPoint.Y;
}
StartPoint = new PointF(x, y);
var side = Math.Max(width, height);
EndPoint = new PointF(x+side, y+side);
ShapeType = ShapeType.Square;
Zindex = zIndex;
ForeColor = foreColor;
Thickness = thickness;
BackgroundColor = backgroundColor;
IsFill = isFill;
}

/// <summary>
/// Initializes a new instance of the <see cref="Square" /> class.
/// </summary>
public Square()
{
ShapeType = ShapeType.Square;
}

#endregion Constructors
}
}


این کلاس شامل دو سازنده می‌باشد که سازنده دوم فقط نوع شی را تعیین می‌کند و بقیه کارهای آن مانند مستطیل است، در واقع می‌توان از یک دیدگاه گفت که مربع یک مستطیل است که اندازه طول و عرض آن یکسان است. در سازنده اول (نحوه ترسیم شکل (http://www.dotnettips.info/post/1209/)) ابتدا نقاط ابتدا و انتهای رسم شکل تعیین شده و سپس با توجه به پارامترهای محاسبه شده نوع شی جهت ترسیم و دیگر خصوصیات کلاس مقدار دهی می‌شود، با این تفاوت که در نقطه EndPoint طول و عرض مربع برابر با بزرگترین مقدار طول و عرض وارد شده در سازنده کلاس تعیین شده و مربع شکل می‌گیرد. مابقی متدهای ترسیم و ... طبق کلاس پایه مستطیل و Shape تعیین می‌شود.

آدرس پست اصلی (http://www.dotnettips.info/post/1232/)

مطالب قبل:
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 1# (http://www.dotnettips.info/post/1195/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 2# (http://www.dotnettips.info/post/1208/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 3# (http://www.dotnettips.info/post/1209/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 4# (http://www.dotnettips.info/post/1214/)

Saber_Fatholahi
یک شنبه 06 اسفند 1391, 14:00 عصر
در ادامه پست پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 5# (http://www.dotnettips.info/post/1232/) ، در این پست به تشریح کلاس دایره و بیضی می‌پردازیم.

ابتدا به تشریح کلاس ترسیم بیضی (Ellipse) می‌پردازیم.

using System.Drawing;

namespace PWS.ObjectOrientedPaint.Models
{
/// <summary>
/// Ellipse Draw
/// </summary>
public class Ellipse : Shape
{
#region Constructors (2)

/// <summary>
/// Initializes a new instance of the <see cref="Ellipse" /> class.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="zIndex">Index of the z.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="isFill">if set to <c>true</c> [is fill].</param>
/// <param name="backgroundColor">Color of the background.</param>
public Ellipse(PointF startPoint, PointF endPoint, int zIndex, Color foreColor, byte thickness, bool isFill, Color backgroundColor)
: base(startPoint, endPoint, zIndex, foreColor, thickness, isFill, backgroundColor)
{
ShapeType = ShapeType.Ellipse;
}

/// <summary>
/// Initializes a new instance of the <see cref="Ellipse" /> class.
/// </summary>
public Ellipse()
{
ShapeType = ShapeType.Ellipse;
}

#endregion Constructors

#region Methods (1)

// Public Methods (1)

/// <summary>
/// Draws the specified g.
/// </summary>
/// <param name="g">The g.</param>
public override void Draw(Graphics g)
{
if (IsFill)
g.FillEllipse(BackgroundBrush, StartPoint.X, StartPoint.Y, Width, Height);
g.DrawEllipse(Pen, StartPoint.X, StartPoint.Y, Width, Height);
base.Draw(g);
}

#endregion Methods
}
}



این کلاس از شی Shape ارث برده و دارای دو سازنده ساده می‌باشد که نوع شی ترسیمی را مشخص می‌کنند، در متد Draw نیز با توجه به توپر یا توخالی بودن شی ترسیم آن انجام میشود، در این کلاس باید متد HasPointInShape بازنویسی (override) شود، در این متد باید تعیین شود که یک نقطه در داخل بیضی قرار گرفته است یا خیر که متاسفانه فرمول بیضی خاطرم نبود. البته به صورت پیش فرض نقطه با توجه به چهارگوشی که بیضی را احاطه می‌کند سنجیده می‌شود.

کلاس دایره (Circle) از کلاس بالا (Ellipse) ارث بری دارد که کد آن را در زیر مشاهده می‌نمایید.

using System;
using System.Drawing;

namespace PWS.ObjectOrientedPaint.Models
{
/// <summary>
/// Circle
/// </summary>
public class Circle : Ellipse
{
#region Constructors (2)

/// <summary>
/// Initializes a new instance of the <see cref="Circle" /> class.
/// </summary>
/// <param name="startPoint">The start point.</param>
/// <param name="endPoint">The end point.</param>
/// <param name="zIndex">Index of the z.</param>
/// <param name="foreColor">Color of the fore.</param>
/// <param name="thickness">The thickness.</param>
/// <param name="isFill">if set to <c>true</c> [is fill].</param>
/// <param name="backgroundColor">Color of the background.</param>
public Circle(PointF startPoint, PointF endPoint, int zIndex, Color foreColor, byte thickness, bool isFill, Color backgroundColor)
{
float x = 0, y = 0;
float width = Math.Abs(endPoint.X - startPoint.X);
float height = Math.Abs(endPoint.Y - startPoint.Y);
if (startPoint.X <= endPoint.X && startPoint.Y <= endPoint.Y)
{
x = startPoint.X;
y = startPoint.Y;
}
else if (startPoint.X >= endPoint.X && startPoint.Y >= endPoint.Y)
{
x = endPoint.X;
y = endPoint.Y;
}
else if (startPoint.X >= endPoint.X && startPoint.Y <= endPoint.Y)
{
x = endPoint.X;
y = startPoint.Y;
}
else if (startPoint.X <= endPoint.X && startPoint.Y >= endPoint.Y)
{
x = startPoint.X;
y = endPoint.Y;
}
StartPoint = new PointF(x, y);
var side = Math.Max(width, height);
EndPoint = new PointF(x + side, y + side);
ShapeType = ShapeType.Circle;
Zindex = zIndex;
ForeColor = foreColor;
Thickness = thickness;
BackgroundColor = backgroundColor;
IsFill = isFill;
}

/// <summary>
/// Initializes a new instance of the <see cref="Circle" /> class.
/// </summary>
public Circle()
{
ShapeType = ShapeType.Circle;
}

#endregion Constructors

#region Methods (1)

// Public Methods (1)

/// <summary>
/// Points the in sahpe.
/// </summary>
/// <param name="point">The point.</param>
/// <param name="tolerance">The tolerance.</param>
/// <returns>
/// <c>true</c> if [has point in sahpe] [the specified point]; otherwise, <c>false</c>.
/// </returns>
public override bool HasPointInSahpe(PointF point, byte tolerance = 5)
{
float width = Math.Abs(EndPoint.X+tolerance - StartPoint.X-tolerance);
float height = Math.Abs(EndPoint.Y+tolerance - StartPoint.Y-tolerance);
float diagonal = Math.Max(height, width);
float raduis = diagonal / 2;
float dx = Math.Abs(point.X - (X + Width / 2));
float dy = Math.Abs(point.Y - (Y + height / 2));
return (dx + dy <= raduis);
}

#endregion Methods
}
}



این کلاس شامل دو سازنده می‌باشد، که در سازنده اول با توجه به نقاط ایتدا و انتهای ترسیم شکل مقدار طول و عرض مستطیل احاطه کننده دایره محاسبه شده و باتوجه به آنها بزرگترین ضلع به عنوان قطر دایره در نظر گرفته می‌شود و EndPoint شکل مورد نظر تعیین می‌شود.

در متد HasPointInShape با استفاده از فرمول دایره تعیین می‌شود که آیا نقطه پارامتر ورودی متد در داخل دایره واقع شده است یا خیر (جهت انتخاب شکل برای جابجایی یا تغییر اندازه).
در پست‌های بعد به پیاده سازی اینترفیس نرم افزار خواهیم پرداخت.

موفق و موید باشید

در ادامه مطالب قبل:
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 1# (http://www.dotnettips.info/post/1195/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 2# (http://www.dotnettips.info/post/1208/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 3# (http://www.dotnettips.info/post/1209/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 4# (http://www.dotnettips.info/post/1214/)
پیاده سازی پروژه نقاشی (Paint) به صورت شی گرا 5# (http://www.dotnettips.info/post/1232/)

mahlake
جمعه 30 فروردین 1392, 14:21 عصر
آقا تورو خدا ادامه بدید من واقعا مشتاق هستم این برنامه رو تا انتها دنبال کنم خیلی موضوع خوبی رو انتخاب کرده اید...