Advertisement
csaki

Bezier & Hermite (kommentekkel)

Dec 18th, 2013
329
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 7.56 KB | None | 0 0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.ComponentModel;
  4. using System.Data;
  5. using System.Drawing;
  6. using System.Linq;
  7. using System.Text;
  8. using System.Threading.Tasks;
  9. using System.Windows.Forms;
  10.  
  11. namespace grafikaBeadando
  12. {
  13.     public partial class Form1 : Form
  14.     {
  15.  
  16.         /*
  17.          * BÉZIER:
  18.          * - egy lista, amiben a pontokat tároljuk
  19.          * - 7 elemig megyünk, a 4.-et és a 7.-et külön vizsgáljuk
  20.          * - minden 5. elemet legeneráljuk
  21.          * - 4.-nél görberajzolunk, majd generálunk
  22.          * - pont kirajzolás a két if között
  23.          * - 7.-nél 0-3 törlés, majd rajzolás
  24.          * - 5. pont generálása, pont kirajzolás
  25.          * - újabb 0-3 törlés, hogy ne maradjon csak a csatlakozó elem, meg a generált
  26.          * - kezdődik előről
  27.          *
  28.          * HERMITE:
  29.          * - ugyanaz a lista, 4 pontot várunk
  30.          * - ha megvan a 4 pont, egy hermitpont objektumba vesszük fel őket (első, utolsó, második, harmadik)
  31.          * - hermiterajzol fgv, benne számol fgv (-> polinom)
  32.          * - pontok kirajzoltatása (float x, float y - paraméterezés: kezd, vég, kezdirány-kezd, vég-végirány) (!!!!!!!!!)
  33.          * - egy elemet hagyunk (RemoveRange(0,3), vagy egyesével töröljük, forciklus, vagy bármi
  34.          * - innen kezdődik az egész előről
  35.          *
  36.          */
  37.  
  38.         Graphics g;
  39.         List<PointF> pontok; // kattintás- és kontrollpontok
  40.         int DB = 200; // Görbe pontjai
  41.  
  42.         // Tartomány (próbáld ki nem 0-1 határokkal. mókás dolgok születnek belőle:D)
  43.         float A = 0;
  44.         float B = 1;
  45.  
  46.         List<HermitPontok> hermitPontok; // kattintáspontok hermitgörbéhez
  47.  
  48.         public Form1()
  49.         {
  50.             InitializeComponent();
  51.             g = CreateGraphics();
  52.             g.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.AntiAlias;
  53.             pontok = new List<PointF>();
  54.             hermitPontok = new List<HermitPontok>();
  55.             MouseUp += Form1_MouseUp;
  56.         }
  57.  
  58.         void Form1_MouseUp(object sender, MouseEventArgs e)
  59.         {
  60.             if (radioBezier.Checked) //  Bézier-görbe!
  61.             {
  62.                 if (pontok.Count < 7) // 4 és 7 pontnál rajzolunk!
  63.                 {
  64.                     pontok.Add(e.Location); // listához hozzáadjuk a pontot
  65.                     if (pontok.Count == 4)
  66.                     {
  67.                         BezierGörbeRajzol(); // ezt itt már össze is kötjük
  68.                         // A 4. pontot nekünk kell kiszámolni! (Q1)
  69.                         pontok.Add(new PointF(pontok[2].X + 2 * (pontok[3].X - pontok[2].X), pontok[2].Y + 2 * (pontok[3].Y - pontok[2].Y)));
  70.                     }
  71.                     PontokRajzol(); // a pontokat minden esetben kirajzoljuk! (átláthatóság miatt)
  72.  
  73.                     if (pontok.Count == 7) // megvan a 7 pont
  74.                     {
  75.                         pontok.RemoveRange(0, 3); // meghagyunk 4 pontot
  76.                         BezierGörbeRajzol(); //...és ezeket kirajzoljuk
  77.                         pontok.Add(new PointF(pontok[2].X + 2 * (pontok[3].X - pontok[2].X), pontok[2].Y + 2 * (pontok[3].Y - pontok[2].Y)));
  78.                         PontokRajzol(); // 5. pont generálása!
  79.                         pontok.RemoveRange(0, 3); // meghagyunk 1 (vagyis 2) pontot, amiről fut tovább a görbe (csatlakozik)
  80.                     }
  81.                 }
  82.             }
  83.  
  84.             else // Hermit-görbe!
  85.             {
  86.                 pontok.Add(e.Location); // Listához hozzáadjuk
  87.                 PontokRajzol();
  88.                 if (pontok.Count == 4) // Ha megvan 4, ahogy a feladat kérte, létrehozunk egy hermitgörbe objektumot (lap alja!)
  89.                 {
  90.                     hermitPontok.Add(new HermitPontok(pontok[0], pontok[3], pontok[1], pontok[2])); //...hozzáadjuk a 4 pontot..
  91.                     // FONTOS A SORREND. első, utolsó, második, harmadik. !!
  92.                     HermitGörbeRajzol(); //...és kirajzoljuk.
  93.                     pontok.RemoveRange(0, 3); // egy elemet hagyunk, innen fog csatlakozni (nem volt kikötve csatlakozással kapcsolatban semmi, szóval jó így is)
  94.                 }
  95.             }
  96.         }
  97.  
  98.         void HermitGörbeRajzol()
  99.         {
  100.             foreach (var pont in hermitPontok) // Végig a listán...
  101.             {
  102.                 for (float u = 0; u <= 1; u += 0.01f) // A megadott határok között (jelen esetben 0 és 1)
  103.                 {
  104.                     // Az x,y koordináták kiszámítása polinomiálisan
  105.                     float x = Képlet(pont.kezd.X, pont.vég.X, pont.kezdirány.X - pont.kezd.X, pont.vég.X - pont.végirány.X, u);
  106.                     float y = Képlet(pont.kezd.Y, pont.vég.Y, pont.kezdirány.Y - pont.kezd.Y, pont.vég.Y - pont.végirány.Y, u);
  107.                     g.FillEllipse(Brushes.SeaGreen, x - 2, y - 2, 4, 4);
  108.                 }
  109.             }
  110.         }
  111.  
  112.         float Képlet(float a0, float a1, float a2, float a3, float u) // "Végeredmény" (ilyen képlet lesz megadva a dolgozatban)
  113.         {
  114.             float x = a0 * (2 * u * u * u - 3 * u * u + 1) + a1 * (-2 * u * u * u + 3 * u * u) + a2 * (u * u * u - 2 * u * u + u) + a3 * (u * u * u - u * u);
  115.             return x;
  116.         }
  117.  
  118.         void BezierGörbeRajzol()
  119.         {
  120.             float h = Math.Abs(B - A) / DB; // lépésköz
  121.             float u = A;
  122.             PointF[] görbepontjai = new PointF[DB + 1];
  123.             for (int i = 0; i < görbepontjai.Length; i++) // Ezek a pontok alkotják a görbét
  124.             {
  125.                 görbepontjai[i] = Bezier(u); // Kiszámolunk minden egyes pontot
  126.                 u += h; // növeljük az átadott értéket (u) a lépésközzel (h)
  127.             }
  128.             g.DrawLines(Pens.BlueViolet, görbepontjai.ToArray());
  129.         }
  130.  
  131.         PointF Bezier(float u)
  132.         {
  133.             int n = pontok.Count - 1;
  134.             PointF p = new PointF();
  135.             for (int i = 0; i < pontok.Count; i++)
  136.             {
  137.                 float b = Bernstein(i, n, u); // a varázslat itt történik (Bernstein-polinom)
  138.                 p.X += pontok[i].X * b; // meg kell szorozni!
  139.                 p.Y += pontok[i].Y * b; // ezt is meg kell szorozni!
  140.             }
  141.             return p; //...és elkészült egy újabb pontja a Bézier-görbének!
  142.         }
  143.  
  144.         float Bernstein(int i, int n, float u)
  145.         {
  146.             float x = (float)(N_K(n, i) * ((i == 0) ? 1 : Math.Pow(u, i)) * ((n - i == 0) ? 1 : Math.Pow(1 - u, n - i)));
  147.             return x;
  148.             // Megj.: Ez csak annyi, hogyha i=0 vagy n-i=0, akkor ne számoljon hatványt, annak az értéke 1. (? : operátor)
  149.         }
  150.  
  151.         int N_K(int n, int k)
  152.         {
  153.             int x = Fakt(n) / (Fakt(k) * Fakt(n - k));
  154.             return x;
  155.         }
  156.  
  157.         int Fakt(int n)
  158.         {
  159.             int x = 1;
  160.             for (int i = 1; i <= n; i++)
  161.             {
  162.                 x *= i;
  163.             }
  164.             return x;
  165.         }
  166.  
  167.         void PontokRajzol()
  168.         {
  169.             foreach (var p in pontok)
  170.             {
  171.                 g.FillEllipse(Brushes.Red, p.X - 3, p.Y - 3, 6, 6);
  172.             }
  173.         }
  174.  
  175.         private void radioHermite_CheckedChanged(object sender, EventArgs e)
  176.         {
  177.             // Ürítés! Törlünk mindent!
  178.             Invalidate();
  179.             Update();
  180.             pontok.Clear();
  181.             hermitPontok.Clear();
  182.         }
  183.     }
  184.  
  185.     public class HermitPontok
  186.     {
  187.         public PointF kezd, vég, kezdirány, végirány;
  188.         public HermitPontok(PointF k, PointF v, PointF ki, PointF vi)
  189.         {
  190.             kezd = k;
  191.             vég = v;
  192.             kezdirány = ki;
  193.             végirány = vi;
  194.         }
  195.     }
  196. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement