Autor Beitrag
nike
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 48

Win 2K, Win XP
D5 Ent.
BeitragVerfasst: Di 16.11.04 14:00 
Hallo!

Verwende GDI-PolyBezier zum Zeichnen. Der Benutzer soll beim Kurven-Editor jedoch Curve-Punkte angeben (d.h. die angegebenen Punkte liegen auf der gezeichneten Kurve und sind nicht nur "Magneten").

Habe auch ne ansehliche Annäherung der Curve-Kontrollpunkte in Bezierpunkte, hänge aber mom. bei der Rückverwandlung zu Bezier-Kontrollpunkten, da ich auch vorhandene Bezier-Daten integrieren muß, die nicht von meinen Routinen berechnet wurden.

In der Literatur habe ich auch immer nur den One-Way gefunden, d.h. von Curve-Punkten zu Bezier-Punkten, nicht aber umgekehrt.

Kennt jemand eine (ggfs. auch mathematische Erklärung) allgemeine Rückverwandlungsmethode?

GDI+ ist für meine Zwecke zu langsam, und ist zudem nicht auf allen Zielrechnern vorhanden.

Vielen Dank im voraus,
nike

P.S.: Im Anhang mal meine Curve2Bezier Umwandlung, falls es jemanden interessiert. Verwende dabei für jede 2 Curve-Punkte ein eigenes AlphaX.

ausblenden volle Höhe Delphi-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
41:
42:
43:
44:
45:
46:
47:
48:
49:
50:
51:
52:
53:
54:
55:
56:
57:
58:
59:
60:
61:
62:
63:
64:
65:
66:
67:
68:
69:
70:
71:
72:
73:
74:
75:
76:
77:
78:
79:
80:
81:
82:
83:
84:
85:
86:
87:
88:
89:
90:
91:
92:
93:
94:
95:
96:
97:
98:
99:
100:
101:
102:
103:
104:
105:
106:
107:
108:
109:
110:
111:
112:
113:
114:
115:
116:
117:
118:
119:
120:
121:
122:
123:
124:
125:
126:
127:
128:
129:
130:
131:
132:
133:
134:
135:
136:
137:
138:
139:
140:
141:
142:
143:
144:
145:
146:
147:
148:
149:
150:
151:
152:
153:
154:
155:
156:
157:
158:
159:
160:
161:
162:
163:
164:
165:
166:
167:
168:
169:
170:
171:
procedure TForm1.CalcBezierPunkte;
var
  i,j   : integer;
  dx,dy : integer;
  m   : double;
  alphax  : double;
  ydelta : integer;
  DeltaAktX : integer;
  f       : System.Text;
begin
  AssignFile(f, 'C:\Debug.txt');
  Rewrite(f);
  WriteLn(f, Format('n: %d', [n]));
  case n of
    0,1,2 : i := 0;
    else i := 4 + 3*(n-2);
  end;
  SetLength(fBezierPunkte, i);

  if n>2 then
  begin
    //Erste beide und letzen beiden gesondert

    fBezierPunkte[0] := FPunkte[0];
    dx := FPunkte[1].x-FPunkte[0].x;
    dy := FPunkte[1].y-FPunkte[0].y; //Annäherung an direkte Gerade

    if dx=0 then
    begin
      //Erster Kontrollpunkt , Parallele zu y
      alphax := 0;  //da nix da
      ydelta := Round(dy/fAlpha);  //2. Berechnungsmöglichkeit
      fBezierPunkte[1].x := FPunkte[0].x;
      fBezierPunkte[1].y := FPunkte[0].y+ydelta;
    end
    else begin
      m := dy/dx;
        //Erster Kontrollpunkt
      alphax := dx/fAlpha;
      ydelta := Round(alphax*m);
      fBezierPunkte[1].x := FPunkte[0].x+Round(alphax);
      fBezierPunkte[1].y := FPunkte[0].y+ydelta;
    end;

    j := 2;
    for i := 1 to n-2 do  //einzelne Punkte mit zugehörigen Kontrollpunkten
    begin
      dx := FPunkte[i+1].x-FPunkte[i-1].x;
      dy := FPunkte[i+1].y-FPunkte[i-1].y;

      DeltaAktX := FPunkte[i+1].x-FPunkte[i].x;
      //Für linken Kontrollpunkt, alphax bereits aus Iteration
      if (dx=0then     //Dass muß in alle 3 Einzelfällen unterschieden werden
      begin
        //Jetzt Verschiebung für Schnittpunkte mit
        //Links
        ydelta := Round((FPunkte[i].y-FPunkte[i-1].y)/fAlpha);
        fBezierPunkte[j].x := FPunkte[i].x;
        fBezierPunkte[j].y := FPunkte[i].y-ydelta;
        Inc(j);

        //Punkte selber
        fBezierPunkte[j] := FPunkte[i];
        Inc(j);

        //Rechts
        alphax := (DeltaAktX)/fAlpha;
        ydelta := Round((FPunkte[i+1].y-FPunkte[i].y)/fAlpha);
        fBezierPunkte[j].x := FPunkte[i].x;
        fBezierPunkte[j].y := FPunkte[i].y+ydelta;
        Inc(j);
      end
      else begin
        if Abs(dx)<Abs(FPunkte[i].x-FPunkte[i-1].x) then //Absolute Längen vergleichen ein Wendepunkt, ähnlich wie 0-Steigung!
          if Abs(dy)>Abs(FPunkte[i].y-FPunkte[i-1].y) then
          begin
            m := dy/dx;  //Interval 0-dx
            //Jetzt Verschiebung für Schnittpunkte mit
            //Links
            ydelta := Round((FPunkte[i].y-FPunkte[i-1].y)/fAlpha);
            fBezierPunkte[j].x := FPunkte[i].x;
            fBezierPunkte[j].y := FPunkte[i].y-ydelta;
            Inc(j);

            //Punkte selber
            fBezierPunkte[j] := FPunkte[i];
            Inc(j);

            //Rechts
            alphax := (DeltaAktX)/fAlpha;
            ydelta := Round((FPunkte[i].y-FPunkte[i+1].y)/fAlpha);
            fBezierPunkte[j].x := FPunkte[i].x;
            fBezierPunkte[j].y := FPunkte[i].y-ydelta;
            Inc(j);
          end
          else begin
            m := dy/dx;  //Interval 0-dx
            //Jetzt Verschiebung für Schnittpunkte mit
            //Links
            ydelta := Round((FPunkte[i].y-FPunkte[i-1].y)/fAlpha);
            fBezierPunkte[j].x := FPunkte[i].x;
            fBezierPunkte[j].y := FPunkte[i].y-ydelta;
            Inc(j);

            //Punkte selber
            fBezierPunkte[j] := FPunkte[i];
            Inc(j);

            //Rechts
            alphax := (DeltaAktX)/fAlpha;
            ydelta := Round((FPunkte[i].y-FPunkte[i+1].y)/fAlpha);
            fBezierPunkte[j].x := FPunkte[i].x;
            fBezierPunkte[j].y := FPunkte[i].y+ydelta;
            Inc(j);
          end
        else begin  //Standard
          m := dy/dx;  //Interval 0-dx
          //Jetzt Verschiebung für Schnittpunkte mit
          //Links
          ydelta := Round(alphax*m);
          fBezierPunkte[j].x := Round(FPunkte[i].x-alphax);
          fBezierPunkte[j].y := FPunkte[i].y-ydelta;
          Inc(j);

          //Punkte selber
          fBezierPunkte[j] := FPunkte[i];
          Inc(j);

          //Rechts
          alphax := (DeltaAktX)/fAlpha;
          ydelta := Round(alphax*m);
          fBezierPunkte[j].x := Round(FPunkte[i].x+alphax);
          fBezierPunkte[j].y := FPunkte[i].y+ydelta;
          Inc(j);
        end;
      end;
{
      if dx>dy then  //Möglichst kleine Steigung, ggfs. 90° gedreht
      begin
}

    end;


    dx := FPunkte[n-1].x-FPunkte[n-2].x;
    dy := FPunkte[n-1].y-FPunkte[n-2].y;

    if dx=0 then
    begin
      ydelta := Round(dy/fAlpha);

      fBezierPunkte[j].x := FPunkte[n-1].x;
      fBezierPunkte[j].y := FPunkte[n-1].y-ydelta;

      Inc(j);
      fBezierPunkte[j] := FPunkte[n-1];
    end
    else begin
      m := dy/dx;

      alphax := dx/fAlpha;
      ydelta := Round(alphax*m);

      fBezierPunkte[j].x := Round(FPunkte[n-1].x-alphax);
      fBezierPunkte[j].y := FPunkte[n-1].y-ydelta;

      Inc(j);
      fBezierPunkte[j] := FPunkte[n-1];
    end;
  end;
  CloseFile(f);
end;