/// <summary> /// Използва се в методът ChangeBorderWidth за промяна на ширината на контура, ако селектираният елемент е част от група. /// </summary> /// <param name="group"></param> /// <param name="width"></param> private void ChangeCascadeBorderWidth(Shape group, int width) { foreach (Shape item in ((Grouping)group).GroupedElements) { if (item.isGroup == true) { ChangeCascadeBorderWidth(item, width); } else { item.BorderWidth = width; } } }
/// <summary> /// Използва се в методът ChangeFillColor за промяна на цвета на запълване на селектиран елемент, ако той е част от група от елементи. /// </summary> /// <param name="group"></param> /// <param name="color"></param> private void ChangeCascadeFillColor(Shape group, Color color) { foreach (Shape item in ((Grouping)group).GroupedElements) { if (item.isGroup == true) { ChangeCascadeFillColor(item, color); } else { item.FillColor = color; } } }
/* * рекурсивното транслиране на всички елементи на подадена група */ private void RecursiveScaleTranslate(int type, RectangleF initialBounds, RectangleF curBounds, Shape item) { if (item.isGroup) { Grouping groupe = (Grouping)item; foreach (Shape element in groupe.GroupedElements) { RecursiveScaleTranslate(type,initialBounds,curBounds,element); } } else { this.SelectedItem.TMatrix.TransformationMatrix = item.TMatrix.TransformationMatrix; base.TranslateScaledItem(type, initialBounds, curBounds, item); } }
/* *Рекурсивен метод за транслиране на всички елемнти на група един по един * **/ private void RecursiveTranslate(Shape element,PointF point) { if (element.isGroup) { Grouping groupe = (Grouping)element; foreach (Shape item in groupe.GroupedElements) { RecursiveTranslate(item,point); } } else { this.SelectedItem.TMatrix.TransformationMatrix = element.TMatrix.TransformationMatrix; base.TranslateElementTo(point); element.TMatrix.TransformationMatrix = this.SelectedItem.TMatrix.TransformationMatrix; } }
/* * Рекурсивен метод, който натрупва ротацията върху матриците на трансформация * на всички поделементи на групата * използва центъра на групата (около него се въртят сички елементи) */ private void RecursiveRotate(Shape element, PointF mLocation,PointF center) { if (element.isGroup) { Grouping groupe = (Grouping)element; foreach (Shape item in groupe.GroupedElements) { RecursiveRotate(item, mLocation,center); } } else { // същинската ротация на елемент // приравнявам матрицата на групата с тази на елемента защото // методът Rotate работи с матрицата на групата // и после запазвам промените в матрицата на елемента this.SelectedItem.TMatrix.TransformationMatrix = element.TMatrix.TransformationMatrix; base.Rotate(mLocation,center); element.TMatrix.TransformationMatrix = this.SelectedItem.TMatrix.TransformationMatrix; } }
/* * рекурсивното скалиране на всички елементи на подадена група */ private void RecursiveScale(PointF point, int type, RectangleF initialBounds, Shape item, PointF iniLocation) { if (item.isGroup) { Grouping groupe = (Grouping)item; foreach (Shape item2 in groupe.GroupedElements) { RecursiveScale(point,type, initialBounds,item2,iniLocation); } } else { this.SelectedItem.TMatrix.TransformationMatrix = item.TMatrix.TransformationMatrix; base.ScaleItem(point, type, initialBounds, item, iniLocation); } }
public void MouseUp(Point mlocation) { switch (Event) { case "DrawPointShape-go": { Point initial = (Point)sDots.ToArray()[0]; Point current = mlocation; ((PointShape)itemPointer).SetLocation = new RectangleF(Math.Min(initial.X, current.X) - 1, Math.Min(initial.Y, current.Y) - 1, Math.Max(initial.X, current.X) - Math.Min(initial.X, current.X), Math.Max(initial.Y, current.Y) - Math.Min(initial.Y, current.Y)); Event = ""; itemPointer = null; }break; case "DrawLineShape-go": { Event = ""; itemPointer = null; } break; case "DrawCurveShape-go": { Event = ""; itemPointer = null; } break; case "DrawClosedCurveShape-go": { Event = ""; itemPointer = null; } break; case "DrawSquareShape-go": { Event = ""; itemPointer = null; }break; case "DrawRectangleShape-go": { Event = ""; itemPointer = null; } break; case "DrawEllipseShape-go": { Event = ""; itemPointer = null; } break; case "DrawCircleShape-go": { Event = ""; itemPointer = null; }break; case "DrawEllipseLineIntersectionShape-go": { Event = ""; itemPointer = null; } break; case "DrawConnectedEllipses-go": { Event = ""; itemPointer = null; } break; case "DrawPolygonShape-go": { if (sDots.Count == 4) { diProcessor.ObjectsDrawn.Add(new PolygonShape(sDots)); Event = ""; diProcessor.controlPolygon.Clear(); } itemPointer = null; } break; case "DrawBezierShape-go": { if (sDots.Count == 4) { itemPointer = new BezierCurveShape(); ((BezierCurveShape)itemPointer).pointOne = (Point)sDots.ToArray()[0]; ((BezierCurveShape)itemPointer).pointTwo = (Point)sDots.ToArray()[1]; ((BezierCurveShape)itemPointer).pointTree = (Point)sDots.ToArray()[2]; ((BezierCurveShape)itemPointer).pointFour = (Point)sDots.ToArray()[3]; diProcessor.ObjectsDrawn.Add(itemPointer); itemPointer = null; Event = ""; diProcessor.controlPolygon.Clear(); } itemPointer = null; } break; case "DrawTriangleShape-go": { if (sDots.Count == 3) { diProcessor.ObjectsDrawn.Add(new PolygonShape(sDots)); Event = ""; diProcessor.controlPolygon.Clear(); } itemPointer = null; } break; default: { if (diProcessor.IsDraging) { diProcessor.IsDraging = false; diProcessor.InitialLocation = mlocation; MainWindow.ActiveForm.Cursor = System.Windows.Forms.Cursors.Default; } else { if (diProcessor.multySelect) { diProcessor.HandleMultySelecting(); MainWindow.ActiveForm.Cursor = System.Windows.Forms.Cursors.Default; diProcessor.multySelect = false; } } } break; } }
/* * Секция Скалиране * тук има 2 рекурсивни метода, защото скалирането на групи се свежда до скалиране(което се извършва спрямо * центъра на координатната система и след това транслиране, за да противодейства на възникналите промени. * Методът предефинира предщественика си с цел подържане на скалиране на групи. */ protected override void Action(PointF point, int type, RectangleF initialBounds, Shape item, PointF iniLocation) { //ако елемента не е група ползва метода на предшественика си if (item.isGroup != true) { base.Action(point, type, initialBounds, item, iniLocation); } else { // ако е група първо скалира всички поелемти на групата RecursiveScale(point, type, initialBounds, item, iniLocation); // след това един по един ги транслира RecursiveScaleTranslate(type, initialBounds, item.ReturnBounds(), item); } }
/*транслиране на скалиран елемент*/ protected virtual void TranslateScaledItem(int type, RectangleF initialBounds, RectangleF curBounds, Shape item) { //има само 4 различни вида другите са им производни float tY=1, tX=1; if ( type == 7) { type = 0; } if ( type == 2) { type = 1; } if ( type == 4 || type == 6) { type = 3; } switch (type) { case 0: { tX = (initialBounds.X + initialBounds.Width) - (curBounds.X + curBounds.Width); tY = (initialBounds.Y + initialBounds.Height) - (curBounds.Y + curBounds.Height); }; break; case 1: { tX = initialBounds.X - curBounds.X; tY = (initialBounds.Y + initialBounds.Height) - (curBounds.Y + curBounds.Height); }; break; case 3: { tX = (initialBounds.Location.X - curBounds.Location.X); tY = (initialBounds.Location.Y - curBounds.Location.Y); } break; case 5: { tX = (initialBounds.X + initialBounds.Width) - (curBounds.X + curBounds.Width); tY = initialBounds.Y - curBounds.Y; }; break; } item.TMatrix.Translate(tX, tY); }
/// <summary> /// При кликване в пространството за рисуване приeма координатите. /// </summary> /// <param name="mLocation"></param> public void MouseDown(Point mLocation) { switch(Event) { case "DrawPointShape": { Event = "DrawPointShape-go"; itemPointer = new PointShape(); diProcessor.ObjectsDrawn.Add(itemPointer); sDots.Clear(); sDots.Add(mLocation); }break; case "DrawLineShape": { Event = "DrawLineShape-go"; itemPointer = new LineShape(new Point(-1, -1), new Point(-1, -1)); diProcessor.ObjectsDrawn.Add(itemPointer); sDots.Clear(); sDots.Add(mLocation); } break; case "DrawSquareShape": { Event = "DrawSquareShape-go"; itemPointer = new SquareShape(); diProcessor.ObjectsDrawn.Add(itemPointer); sDots.Clear(); sDots.Add(mLocation); }break; case "DrawRectangleShape": { Event = "DrawRectangleShape-go"; itemPointer = new RectangleShape(); diProcessor.ObjectsDrawn.Add(itemPointer); sDots.Clear(); sDots.Add(mLocation); } break; case "DrawEllipseShape": { Event = "DrawEllipseShape-go"; itemPointer = new EllipseShape(); diProcessor.ObjectsDrawn.Add(itemPointer); sDots.Clear(); sDots.Add(mLocation); } break; case "DrawEllipseLineIntersectionShape": { Event = "DrawEllipseLineIntersectionShape-go"; itemPointer = new EllipseLineIntersectionShape(); diProcessor.ObjectsDrawn.Add(itemPointer); sDots.Clear(); sDots.Add(mLocation); } break; case "DrawConnectedEllipses": { Event = "DrawConnectedEllipses-go"; itemPointer = new ConnectedEllipses(); diProcessor.ObjectsDrawn.Add(itemPointer); sDots.Clear(); sDots.Add(mLocation); } break; case "DrawCircleShape": { Event = "DrawCircleShape-go"; itemPointer = new CircleShape(); diProcessor.ObjectsDrawn.Add(itemPointer); sDots.Clear(); sDots.Add(mLocation); }break; case "DrawCurveShape": { sDots = new ArrayList(); sDots.Add(mLocation); Event = "DrawCurveShape-go"; itemPointer = new CurveShape(sDots); diProcessor.ObjectsDrawn.Add(itemPointer); } break; case "DrawClosedCurveShape": { sDots = new ArrayList(); sDots.Add(mLocation); Event = "DrawClosedCurveShape-go"; itemPointer = new ClosedCurveShape(sDots); diProcessor.ObjectsDrawn.Add(itemPointer); } break; case "DrawPolygonShape": { Event = "DrawPolygonShape-go"; diProcessor.controlPolygon.Add(new LineShape(mLocation, mLocation)); sDots.Clear(); sDots.Add(mLocation); } break; case "DrawBezierShape": { Event = "DrawBezierShape-go"; sDots.Clear(); sDots.Add(mLocation); diProcessor.controlPolygon.Add(new LineShape(mLocation, mLocation)); } break; case "DrawTriangleShape": { Event = "DrawTriangleShape-go"; sDots.Clear(); sDots.Add(mLocation); diProcessor.controlPolygon.Add(new LineShape(mLocation, mLocation)); } break; case "DrawTriangleShape-go": { sDots.Add(mLocation); diProcessor.controlPolygon.Add(new LineShape(mLocation, mLocation)); } break; case "DrawPolygonShape-go": { sDots.Add(mLocation); diProcessor.controlPolygon.Add(new LineShape(mLocation, mLocation)); } break; case "DrawBezierShape-go": { sDots.Add(mLocation); diProcessor.controlPolygon.Add(new LineShape(mLocation, mLocation)); } break; default: { // проверка дали е кликнато в някоя фигура diProcessor.ContainsPoint(mLocation); //ако е if (diProcessor.SelectedItem != null) { diProcessor.messageToStrip = diProcessor.SelectedItem.Name; //ако е кликнато на бутон от селектора if (diProcessor.SelectedItem.selectionUnit.ContainsPoint(mLocation) > -1) { //задаваме действие оразмеряване this.Event = "Scale"; //елемента може да се влачи diProcessor.IsDraging = true; //записваме индекса на операцията в процесора diProcessor.selectionUnitIndex = diProcessor.SelectedItem.selectionUnit.ContainsPoint(mLocation); // определяме типа на курсора на мишката switch (diProcessor.selectionUnitIndex) { case 0: // горен десен { MainWindow.ActiveForm.Cursor = Cursors.SizeNWSE; } break; case 1: // горен ляв { MainWindow.ActiveForm.Cursor = Cursors.SizeNESW; } break; case 2: // горе център { MainWindow.ActiveForm.Cursor = Cursors.SizeNS; }break; case 3: // десен център { MainWindow.ActiveForm.Cursor = Cursors.SizeWE; }break; case 4: // долен десен { MainWindow.ActiveForm.Cursor = Cursors.SizeNWSE; }break; case 5: // долен ляв { MainWindow.ActiveForm.Cursor = Cursors.SizeNESW; }break; case 6: // горен десен { MainWindow.ActiveForm.Cursor = Cursors.SizeNS; }break; case 7: // ляв център { MainWindow.ActiveForm.Cursor = Cursors.SizeWE; }break; case 8: // тук ѝ задавaме действие ротация { MainWindow.ActiveForm.Cursor = RotationCursor; this.Event = "RotateAt"; }break; } } else { //в случай, че сме кликнали в някой елемент го подготвяме за транслация diProcessor.IsDraging = true; this.Event = "TranslateElementTo"; // Променяме и курсора MainWindow.ActiveForm.Cursor = Cursors.SizeAll; } } else { diProcessor.multySelect = true; MainWindow.ActiveForm.Cursor = Cursors.Cross; } // задаваме начална позиция diProcessor.InitialLocation = mLocation; diProcessor.mCurentLocation = mLocation; } break; } }
/*склаиране на елемент*/ protected virtual void ScaleItem(PointF point, int type, RectangleF initialBounds, Shape item, PointF iniLocation) { // взема границите на фигурата Matrix tempMatrix = new Matrix(); float X, Y; X = point.X - iniLocation.X; Y = point.Y - iniLocation.Y; // спрямо бутона(случая) определяме вида на скалирането switch (type) { case 0: { X = initialBounds.Width / (X + initialBounds.Width); Y = initialBounds.Height / (Y + initialBounds.Height); }; break; case 1: { X = (X + initialBounds.Width) / initialBounds.Width; Y = initialBounds.Height / (Y + initialBounds.Height); }; break; case 2: { X = 1; Y = initialBounds.Height / (Y + initialBounds.Height); }; break; case 3: { X = (initialBounds.Width + X) / (initialBounds.Size.Width); Y = 1; } break; case 4: { X = (initialBounds.Width + X) / (initialBounds.Size.Width); Y = (initialBounds.Height + Y) / (initialBounds.Size.Height); } break; case 5: { X = initialBounds.Width / (X + initialBounds.Width); Y = (Y + initialBounds.Height) / initialBounds.Height; }; break; case 6: { X = 1; Y = (initialBounds.Height + Y) / (initialBounds.Size.Height); } break; case 7: { X = initialBounds.Width / (X + initialBounds.Width); Y = 1; }; break; } item.TMatrix.Scale(X, Y); //слага в полето с колко е скалиран обекта по ширина и височина message = "Оразмеряване: " + "X: " + X + "%; Y: " + Y + "%;"; return; }
/* КАК РАБОТИ СКАЛИРАНЕТО!!! * този коментар е обхваща функционалността на 3 функции * 1)MatchType * 2)ScaleItem * 3)TranslateScaledItem * * Написаното тук е валидно за всички 7 случая (коментара де не кода)! * 1) * Първо проверяваме дали (ширината на обекта - разтоянието) е положително число. * Правим същото и за височината. * Сравнявам с 2 понеже всичките ми координати са float (с цел мащабиране*), * ако се вземе по малка стойност има опасност в даден случай да получиме * initialBounds.Width/(X - initialBounds.Width), * където initialBounds.Width е число >0 а (X - initialBounds.Width) да клони към 0 * или x/n при n клонящо към 0 - демек неопределеност. * 2) * След това се изчисляват Х и Y , които всъщност указват изменеието на размера * спрямо текущия размер. * Правим си матрица и записваме Х и Y,скалираме е и след това е умноваваме по * матрицата на трансформация на обекта. * 3) * Приравняваме получената матрица на матрицата на трансформация на обекта. * Накрая изчисляваме координатите, на които да транслираме обекта- * това го правиме за да не се мести фигурата при склаирането. * има 7 случая - по 1 за всяко квадратче от указващия четириъгъллник. * **/ /* * По подадения тип на скалиране определя дали е възможно чрез серия от проверки * и ако е извиква метода Action, който всъщност извиква методите за скалиране и транслиране. * Направено е с толкоз много методи, не за кеф, а понеже при следващия клас, който наследява този * и добая скалиране на групи се предифинра само 1 малък метод, а не се пренаписва сичко * **/ protected virtual void MatchType(PointF point, int type, RectangleF initialBounds ,Shape item,PointF iniLocation) { float X ,Y; //изчисляваме разтоянието м/у началната позиция и текущата X = point.X - iniLocation.X; Y = point.Y - iniLocation.Y; bool flag=false; // спрямо бутона(случая) определяме вида на скалирането switch (type) { case 0: { if (((initialBounds.Width - X) > 2) && ((initialBounds.Height - Y) > 2)) { flag = true; } }; break; case 1: { if (((initialBounds.Width + X) > 2) && ((initialBounds.Height -Y) > 2)) { flag = true; } }; break; case 2: { if ( ((initialBounds.Height - Y) > 2)) { flag = true; } }; break; case 3: { if ((initialBounds.Width + X) > 2) { flag = true; } } break; case 4: { if (((initialBounds.Width + X) > 2) && (initialBounds.Height+ Y) > 2) { flag = true; } } break; case 5: { if (((initialBounds.Width - X) > 2) && ((initialBounds.Height + Y) > 2)) { flag = true; } }; break; case 6: { if ((initialBounds.Height + Y) > 2) { flag = true; } } break; case 7: { if (((initialBounds.Width - X) > 2)) { flag = true; } }; break; } if (flag == true) { this.Action(point, type, initialBounds, item, iniLocation); } //слага в полето с колко е скалиран обекта по ширина и височина message = "Оразмеряване: " + "X: " + X + "%; Y: " + Y + "%;"; return; }
/*функцията се извиква от MatchType и извиква ScaleItem и TranslateScaledItem*/ protected virtual void Action(PointF point, int type, RectangleF initialBounds, Shape item, PointF iniLocation) { this.ScaleItem(point, type, initialBounds, item, iniLocation); this.TranslateScaledItem(type, initialBounds, item.ReturnBounds(), item);//tuka 6te imam qdove }
// селектирания елемент -null aко няма такъв /* проверява дали дадена точка е във фигурата * извиква си метода на фигурата - независи от класа на фигурата */ public void ContainsPoint(Point point) { // прави всички фигури неселектирани ResetDrawnObjects(); //цикъл за обхождане - в обратен ред понеже последните фигури,които са // изчертани са най-отгоре for (int i = ObjectsDrawn.Count - 1; i >= 0; i--) { if (ObjectsDrawn[i].ContainsPoint(point)) { SelectedItem = ObjectsDrawn[i]; // селектирания обект е този с точката selectedItem.Selected = true; return ; } } // изчистваме селектирания елемент иначе използва последния селектиран selectedItem = null; return ; }
/* * Иавиква метода самоизчертаване на фигурата * **/ protected virtual void DrawElement(Shape Element, Graphics Grafics) { Element.DrawYourSelf(Grafics); }