ვაღიარებ, რომ ძალიან რთული გადასაწყვეტი აღმოჩნდა.
არადა წარმოსადგენად რა მარტივია, ამოჭერი ერთი სამკუთხედიდან სურათი, გაწელე-გამოწელე და ჩასვი მეორეში.
მოკლედ, ამოცანა გადაიჭრა ასე:
1. სამკუთხედის ირგვლივ ვჭრით მართკუთხა სურათს.
2. სამკუთხედს განვიხილავთ როგორც ფუძე და წვერო, და პირველ წერტილზე ვატრიალებთ ისე, რომ ფუძე გახდეს ჰორიზონტალური.
3. ვადგენთ ფუძის ზომის ცვლილებას, წვეროს დაშორებას და ვახდენთ შესაბამის გაჭიმვა/შეკუმშვას.
4. ვადგენთ წვეროს ფარდობით წანაცვლებას და skew_transform-ით ვახდენთ ტრანსფორმაციას.
5. სამკუთხედის მიხედვით ვადგენთ clip რეგიონს.
მთლიანობაში ბევრი წვრილმანია, განსაკუთრებით ძნელი წანაცვლების გაანგარიშება იყო:
double proekciis_ganlageba_a = mandzili_a1_prj / gverdi_a; // წანაცვლების შეფარდება პირველში ფუძესთან
if ((mandzili_prj_a3 > gverdi_a) && (mandzili_prj_a3 > mandzili_a1_prj))
{ proekciis_ganlageba_a = (-1) * proekciis_ganlageba_a; }
double proekciis_ganlageba_b = mandzili_b1_prj / gverdi_b; // ---- წანაცვლების შეფარდება მეორეში ფუძესთან ----
if ((mandzili_prj_b3 > gverdi_b) && (mandzili_prj_b3 > mandzili_b1_prj))
{ proekciis_ganlageba_b = (-1) * proekciis_ganlageba_b; }
double canacvleba = proekciis_ganlageba_b - proekciis_ganlageba_a; // ---- საერთო ფარდობითი წანაცვლება
double realuri_gadaadgileba = canacvleba * gverdi_b;
double kutxeebis_sxvaoba_cveroebis_3 = (180.0 / Math.PI)*(Math.Atan(realuri_gadaadgileba / distancia_b)); // ---- ტრანსფორმაციის კუთხის გამოთვლა
იქნება ვინმეს გამოგადგეთ
» სპოილერის ნახვისთვის დააწკაპუნეთ აქ «
private Rect rect_from_triangle(Ellipse[] elipsebi)
{
double top = 0;
double botton = 0;
double left = 0;
double right = 0;
double diametri = elipsebi[0].Width;
//----------------- leftis dadgena --------------------//
if ((double)elipsebi[0].GetValue(Canvas.LeftProperty) < (double)elipsebi[1].GetValue(Canvas.LeftProperty))
{
left = (double)elipsebi[0].GetValue(Canvas.LeftProperty);
}
else
{
left = (double)elipsebi[1].GetValue(Canvas.LeftProperty);
}
if (left > (double)elipsebi[2].GetValue(Canvas.LeftProperty))
{
left = (double)elipsebi[2].GetValue(Canvas.LeftProperty);
}
//----------------- right dadgena --------------------//
if ((double)elipsebi[0].GetValue(Canvas.LeftProperty) > (double)elipsebi[1].GetValue(Canvas.LeftProperty))
{
right = (double)elipsebi[0].GetValue(Canvas.LeftProperty);
}
else
{
right = (double)elipsebi[1].GetValue(Canvas.LeftProperty);
}
if (right < (double)elipsebi[2].GetValue(Canvas.LeftProperty))
{
right = (double)elipsebi[2].GetValue(Canvas.LeftProperty);
}
//----------------- top dadgena --------------------//
if ((double)elipsebi[0].GetValue(Canvas.TopProperty) < (double)elipsebi[1].GetValue(Canvas.TopProperty))
{
top = (double)elipsebi[0].GetValue(Canvas.TopProperty);
}
else
{
top = (double)elipsebi[1].GetValue(Canvas.TopProperty);
}
if (top > (double)elipsebi[2].GetValue(Canvas.TopProperty))
{
top = (double)elipsebi[2].GetValue(Canvas.TopProperty);
}
//----------------- botton dadgena --------------------//
if ((double)elipsebi[0].GetValue(Canvas.TopProperty) > (double)elipsebi[1].GetValue(Canvas.TopProperty))
{
botton = (double)elipsebi[0].GetValue(Canvas.TopProperty);
}
else
{
botton = (double)elipsebi[1].GetValue(Canvas.TopProperty);
}
if (botton < (double)elipsebi[2].GetValue(Canvas.TopProperty))
{
botton = (double)elipsebi[2].GetValue(Canvas.TopProperty);
}
//---------------- shescoreba ---------------------------//
left = left + diametri / 2;
right = right + diametri / 2;
top = top + diametri / 2;
botton = botton + diametri / 2;
Rect recti = new Rect(left, top, right - left, botton - top);
return recti;
}
private void clip_triangle(Point[] certilebi, Image img)
{
Point p_a1 = certilebi[0];
Point p_a2 = certilebi[1];
Point p_a3 = certilebi[2];
PathFigure figure = new PathFigure();
figure.StartPoint = p_a1;
PathFigureCollection figCollection = new PathFigureCollection();
PathSegmentCollection segCollection = new PathSegmentCollection();
LineSegment pirveli = new LineSegment();
LineSegment meore = new LineSegment();
LineSegment mesame = new LineSegment();
figCollection.Add(figure);
pirveli.Point = p_a1;// new Point(10, 10);
meore.Point = p_a2;// new Point(220, 110);
mesame.Point = p_a3;// new Point(90, 150);
segCollection.Add(pirveli);
segCollection.Add(meore);
segCollection.Add(mesame);
figure.Segments = segCollection;
PathGeometry geo = new PathGeometry();
geo.Figures = figCollection;
img.Clip = geo;
}
private void gadatana(Canvas canvas_a, Canvas canvas_b, Image image_a, Image image_b, Ellipse[] ellipse_a, Ellipse[] ellipse_b)
{
// წერტილების კოოკრდინატების დადგენა
double el_s = ellipse_a[0].Width / 2;
Point p_a1 = new Point((double)ellipse_a[0].GetValue(Canvas.LeftProperty) + el_s, (double)ellipse_a[0].GetValue(Canvas.TopProperty) + el_s);
Point p_a2 = new Point((double)ellipse_a[1].GetValue(Canvas.LeftProperty) + el_s, (double)ellipse_a[1].GetValue(Canvas.TopProperty) + el_s);
Point p_a3 = new Point((double)ellipse_a[2].GetValue(Canvas.LeftProperty) + el_s, (double)ellipse_a[2].GetValue(Canvas.TopProperty) + el_s);
Point p_b1 = new Point((double)ellipse_b[0].GetValue(Canvas.LeftProperty) + el_s, (double)ellipse_b[0].GetValue(Canvas.TopProperty) + el_s);
Point p_b2 = new Point((double)ellipse_b[1].GetValue(Canvas.LeftProperty) + el_s, (double)ellipse_b[1].GetValue(Canvas.TopProperty) + el_s);
Point p_b3 = new Point((double)ellipse_b[2].GetValue(Canvas.LeftProperty) + el_s, (double)ellipse_b[2].GetValue(Canvas.TopProperty) + el_s);
double kutxe_a13 = Angle_point(p_a1, p_a3);
double kutxe_b13 = Angle_point(p_b1, p_b3);
double kutxeebis_sxvaoba_fudzeebis = kutxe_b13 - kutxe_a13; // ----- ფუძის მოტრიალების ცვლილება -----
double kutxe_a = Angle_point(p_a1, p_a3) - Angle_point(p_a1, p_a2);
double kutxe_b = Angle_point(p_b1, p_b3) - Angle_point(p_b1, p_b2);
double kutxeebis_sxvaoba_cveroebis = kutxe_b - kutxe_a; // ----- a და b საწყისი კუთხის ცვლილება ------
double gverdi_a = mandzili_point(p_a1, p_a3); // ---- ფუძის გვერდის სიგრძე -----
double gverdi_b = mandzili_point(p_b1, p_b3);
double gverdebis_sxvaoba = gverdi_b / gverdi_a; // ------ ფუძის ცვლილება რამდენჯერ ------
double distancia_a = Distance_point(p_a1, p_a2, p_a3); // ----- a წვეროს სიმაღლე ----
double distancia_b = Distance_point(p_b1, p_b2, p_b3); // ----- b წვეროს სიმაღლე ----
double distanciebis_sxvaoba = distancia_b / distancia_a; // ----- წვეროს სიმაღლის ცვლილება რამდენჯერ --------
double mandzili_a1_prj = mandzili_point(p_a1, Project_point(p_a1, p_a2, p_a3)); // ---- წვეროს პროექციის დაშორება a1-დან ---
double mandzili_prj_a3 = mandzili_point(Project_point(p_a1, p_a2, p_a3), p_a3); // ---- წვეროს პროექციის დაშორება a3-მდე ---
double mandzili_b1_prj = mandzili_point(p_b1, Project_point(p_b1, p_b2, p_b3)); // ---- წვეროს პროექციის დაშორება b1-დან ---
double mandzili_prj_b3 = mandzili_point(Project_point(p_b1, p_b2, p_b3), p_b3); // ---- წვეროს პროექციის დაშორება b3-მდე ---
double proekciis_ganlageba_a = mandzili_a1_prj / gverdi_a; // წანაცვლების შეფარდება პირველში ფუძესთან
if ((mandzili_prj_a3 > gverdi_a) && (mandzili_prj_a3 > mandzili_a1_prj))
{ proekciis_ganlageba_a = (-1) * proekciis_ganlageba_a; }
double proekciis_ganlageba_b = mandzili_b1_prj / gverdi_b; // ---- წანაცვლების შეფარდება მეორეში ფუძესთან ----
if ((mandzili_prj_b3 > gverdi_b) && (mandzili_prj_b3 > mandzili_b1_prj))
{ proekciis_ganlageba_b = (-1) * proekciis_ganlageba_b; }
double canacvleba = proekciis_ganlageba_b - proekciis_ganlageba_a; // ---- წვეროს წანაცვლება ფუძის მერამდენედით ----
// 1. ვირტუალური კანვასის შექმნა
Canvas virtualuri_canvasi = new Canvas();
virtualuri_canvasi.Width = canvas_a.Width;
virtualuri_canvasi.Height = canvas_a.Height;
// 2. სამკუთხედების ამოჭრა მართკუთხედებში
Rect recti_a = rect_from_triangle(ellipse_a);
Rect recti_b = rect_from_triangle(ellipse_b);
Image img_a = new Image();
img_a.Source = bmp_cut(image_a, recti_a);
img_a.Width = recti_a.Width;
img_a.Height = recti_a.Height;
img_a.Stretch = Stretch.Fill;
// 3. წერტილების დადგენა მართკუთხედში
Point pirveli_a1 = new Point(p_a1.X - recti_a.X, p_a1.Y - recti_a.Y);
Point pirveli_a2 = new Point(p_a2.X - recti_a.X, p_a2.Y - recti_a.Y);
Point pirveli_a3 = new Point(p_a3.X - recti_a.X, p_a3.Y - recti_a.Y);
Point pirveli_b1 = new Point(p_b1.X - recti_b.X, p_b1.Y - recti_b.Y);
Point pirveli_b2 = new Point(p_b2.X - recti_b.X, p_b2.Y - recti_b.Y);
Point pirveli_b3 = new Point(p_b3.X - recti_b.X, p_b3.Y - recti_b.Y);
// --- სურათის დამატება თავისივე ადგილზე --- //
virtualuri_canvasi.Children.Add(img_a);
Canvas.SetLeft(img_a, recti_a.X);
Canvas.SetTop(img_a, recti_a.Y);
// 0. პირველი წერტილის გადატანა
double ixxi = (recti_b.X + pirveli_b1.X) - (recti_a.X + pirveli_a1.X);
double iyyi = (recti_b.Y + pirveli_b1.Y) - (recti_a.Y + pirveli_a1.Y);
TransformGroup transformGroupi = new TransformGroup();
TranslateTransform translate_Transform = new TranslateTransform(ixxi, iyyi);
transformGroupi.Children.Add(translate_Transform);
pirveli_a1 = new Point(pirveli_a1.X + ixxi, pirveli_a1.Y + iyyi);
pirveli_a2 = new Point(pirveli_a2.X + ixxi, pirveli_a2.Y + iyyi);
pirveli_a3 = new Point(pirveli_a3.X + ixxi, pirveli_a3.Y + iyyi);
// 1. პირველ წერტილზე ჰორიზონტალურად გაჩერება/მოტრიალება 180-თან
RotateTransform rotate_transform = new RotateTransform(180 - kutxe_a13, pirveli_a1.X, pirveli_a1.Y); // სწორია
// 2. გვერდისა და წვეროს გაჭიმვა
ScaleTransform scale_transform = new ScaleTransform(gverdebis_sxvaoba, distanciebis_sxvaoba, pirveli_a1.X, pirveli_a1.Y);
//* 3. წვეროს წანაცვლება პირველი წერტილისკენ კუთხის მიხედვით
double realuri_gadaadgileba = canacvleba * gverdi_b;
double kutxeebis_sxvaoba_cveroebis_3 = (180.0 / Math.PI)*(Math.Atan(realuri_gadaadgileba / distancia_b));
// 4. წანაცვლება
SkewTransform skew_transform_3 = new SkewTransform((-kutxeebis_sxvaoba_cveroebis_3), 0, pirveli_a1.X, pirveli_a1.Y);
//* 5. პირველ წერტილზე მოტრიალება(საბოლოო)
double kutxe = kutxeebis_sxvaoba_fudzeebis - (180 - kutxe_a13);
RotateTransform rotate_transform_bolo = new RotateTransform(kutxe, pirveli_a1.X, pirveli_a1.Y);
// ------ რენდერის დაწყება ------- //
transformGroupi.Children.Add(rotate_transform);
transformGroupi.Children.Add(scale_transform);
transformGroupi.Children.Add(skew_transform_3);
transformGroupi.Children.Add(rotate_transform_bolo);
img_a.RenderTransform = transformGroupi;
var size = new Size(canvas_a.Width, canvas_a.Height);
virtualuri_canvasi.Measure(size);
virtualuri_canvasi.Arrange(new Rect(size));
RenderTargetBitmap bmp = new RenderTargetBitmap((int)canvas_a.Width, (int)canvas_a.Height, 96, 96, PixelFormats.Pbgra32);
bmp.Render(virtualuri_canvasi);
//--------------------------
DrawingVisual dv = new DrawingVisual();
using (DrawingContext dc = dv.RenderOpen())
{
dc.DrawImage(image_a.Source, new Rect(120, 120, 333, 118)); // მთლიანი სურათის ჩახატვა საწყისიდან ზომებში //
}
RenderTargetBitmap bmpi = new RenderTargetBitmap(240, 240, 96, 96, PixelFormats.Pbgra32);
bmpi.Render(dv);
image_b.Source = bmp;
Point[] pointebi = new Point[] { p_b1, p_b2, p_b3 };
clip_triangle(pointebi, image_b);
}
მიმაგრებული სურათი (გადიდებისთვის დაუწკაპუნეთ სურათზე)