Librairie BGRABitmap

Future version à tester

Librairie BGRABitmap

Messagepar circular » 20 Juin 2011 17:53

Bonjour,

Que pensez-vous d'utiliser BGRABitmap pour le rendu dans l'interface du logiciel ? C'est une bibliothèque mLGPL que j'ai faite pour Lazarus.

J'ai fait une propriété CanvasBGRA qui fonctionne comme le Canvas standard mais avec l'antialiasing et la correction gamma. Dans la dernière version (4.2), il y a aussi une propriété Canvas2D qui propose les mêmes fonctions que l'objet Canvas HTML, c'est-à-dire le clipping et les transformations affines.

Si par ailleurs vous avez des suggestions pour améliorer BGRABitmap, elles sont la bienvenue.

Note : la librairie est téléchargeable sur sourceforge dans le projet LazPaint ( http://sourceforge.net/projects/lazpaint/files/src/ )

Cordialement
circular
 
Messages: 24
Inscription: 20 Juin 2011 16:24

Re: Librairie BGRABitmap

Messagepar P.Fradin » 20 Juin 2011 18:29

Bonjour,

Merci pour cette proposition, je vais pouvoir la regarder de près avec les vacances qui seront bientôt là. J'avais essayé l'année dernière la bibliothèque AggPas mais j'ai été un peu déçu par l'antialiasing d'une part et surtout par l'absence du mode NotXor que j'utilise pour déplacer des objets graphiques à la souris, je crois qu'il y avait aussi un problème avec les modes de remplissage des polygones (un seul mode), il manquait le mode "even odd".
L'objectif initial de TeXgraph est d'exporter des graphiques mathématiques vers différents langages vectoriels utilisant notamment le langage TeX, l'interface graphique du logiciel montre seulement une esquisse du dessin pour aider à sa conception, le dessin est construit à partir d'un langage de commandes, il existe même une version de TeXgraph en ligne de commande (sans interface). Ceci dit, s'il est possible d'avoir un beau rendu directement dans l'interface graphique avec un export bitmap (ce dernier point ne posant pas de problème), cela peut être une évolution intéressante.
P.Fradin
Avatar de l’utilisateur
P.Fradin
Administrateur du site
 
Messages: 1902
Inscription: 29 Oct 2008 15:04

Re: Librairie BGRABitmap

Messagepar circular » 20 Juin 2011 22:06

Je suis étonné. L'antialiasing de AggPas me parait parfait. Pour le reste, je ne sais pas, AggPas est trop compliqué pour moi.

J'ai bien compris que l'interface est secondaire. Cela dit, avec la propriété CanvasBGRA, il n'y a pas, ou presque pas de modification de code à faire. Il est possible de définir le mode de remplissage odd-even ou bien winding. Pour le NotXor, je ne sais pas si vous aurez ce dont vous avez besoin. Si jamais, je vous invite à faire part de votre besoin sur un fil de discussion du forum Lazarus (celui que vous venez de créer par exemple ou bien un fil consacré à BGRABitmap). Il se peut que vous ayez besoin de la classe TBGRAMultishapeFiller de l'unité BGRAPolygon pour dessiner des polygones adjacents avec antialiasing.

Pour l'exportation, il est possible de sauvegarder directement avec SaveToFile avec les writer de FreePascal.

Il se peut qu'il y ait des questions de rapidités dans certaines situations. Si vous pouvez m'aider à accélérer la bibliothèque, cela sera la bienvenue.
circular
 
Messages: 24
Inscription: 20 Juin 2011 16:24

Re: Librairie BGRABitmap

Messagepar P.Fradin » 20 Juin 2011 22:15

C'est promis, je me pencherai la-dessus quand les vacances arriveront!
PS: pour l'antialiasing de Agg, disons que ça marchait bien à partir d'une certaine épaisseur de trait.
P.Fradin
Avatar de l’utilisateur
P.Fradin
Administrateur du site
 
Messages: 1902
Inscription: 29 Oct 2008 15:04

Re: Librairie BGRABitmap

Messagepar circular » 20 Juin 2011 22:23

Oh bah y a rien qui presse.

A bientôt alors.
circular
 
Messages: 24
Inscription: 20 Juin 2011 16:24

Re: Librairie BGRABitmap

Messagepar circular » 22 Juil 2011 17:34

Alors, quoi de neuf ?
circular
 
Messages: 24
Inscription: 20 Juin 2011 16:24

Re: Librairie BGRABitmap

Messagepar P.Fradin » 04 Août 2018 09:36

Bonjour,

Cela fait plusieurs années maintenant qui sont passées, mais je n'ai pas oublié ce post !
J'ai (enfin) pris le temps d'essayer d'utiliser la librairie BGRABitmap dans TeXgraph, et je dois avouer que je suis très agréablement surpris ! J'ai eu un peu de mal au départ jusqu'au moment où je me suis rendu compte qu'il valait mieux que j'utilise polylineF (avec le canvasBGRA) plutôt que polyline, maintenant le rendu des courbes est parfait. Maintenant, pour le rendu des chemins (path), j'essaie d'utiliser le canvas2D qui me semble fait pour ça. J'en profite pour signaler deux points :

1) une erreur dans le fichier BGRACanvas2D.pas, dans le corps de la procédure TBGRACanvas2D.FillStrokePoly, on trouve l'intruction
Code: Tout sélectionner
multi.FillMode :=  fmWinding;

ce qui fait que le mode fmAlternate est systématiquement ignoré, j'a modifié cette instruction en :
Code: Tout sélectionner
multi.FillMode := fillmode;

ce qui règle le problème.

2) Toujours avec le canvas2D, je ne sais pas comment faire un remplissage d'un path avec par exemple des hachures (pas de soucis avec un remplissage plein). Pour le moment, je contourne la difficulté ainsi : je crée un bitmap de la taille de mon graphique, je peint ce bitmap avec les hachures de mon choix, puis j'utilise ce bitmap comme pattern (avec la fonction createpattern et l'option 'no-repeat') et je définis ainsi un FillStyle, puis je déclare le path que je veux dessiner comme clip pour enfin faire le dessin ! Est-ce qu'il n'y aurait pas plus simple ? D'autant que cette méthode ne permet pas le remplissage avec le mode Alternate me semble-t'il.

Voici un exemple de rendu dans l'interface graphique de TeXgraph (c'était un petit défi qui avait été lancé en 2009, dessiner des anneaux entrelacés, en ne dessinant que des cercles):
anneaux.png
anneaux.png (35.4 Kio) Consulté 53418 fois


Il y a encore beaucoup d'adaptations à faire dans TeXgraph, mais c'est en bonne voie, et encore bravo pour cette librairie !
P.Fradin
Avatar de l’utilisateur
P.Fradin
Administrateur du site
 
Messages: 1902
Inscription: 29 Oct 2008 15:04

Re: Librairie BGRABitmap

Messagepar Alphonse Capriani » 04 Août 2018 16:24

On pourrait avoir un aperçu de ce à quoi pourrait ressembler TeXgraph avec cette nouvelle interface ? ;)
Ya Ba Da Ba Dooo!!!
Avatar de l’utilisateur
Alphonse Capriani
 
Messages: 576
Inscription: 18 Juil 2009 19:10
Localisation: East Harlem - NY

Re: Librairie BGRABitmap

Messagepar P.Fradin » 04 Août 2018 16:58

Salut Alphonse,

L'interface de TeXgraph en elle-même n'a pas changé ! C'est en interne que la librairie est utilisée. Par contre le dessin dans la fenêtre habituelle est antialiasé et la transparence est correctement rendue comme tu peux le voir :
TeXgraph1_99.png
TeXgraph1_99.png (91.15 Kio) Consulté 53416 fois
P.Fradin
Avatar de l’utilisateur
P.Fradin
Administrateur du site
 
Messages: 1902
Inscription: 29 Oct 2008 15:04

Re: Librairie BGRABitmap

Messagepar Alphonse Capriani » 04 Août 2018 17:55

Aahhh : ça donne un petit coup de jeune à TeXgraph, ça me plait ça.

Pour info, la semaine prochaine, je suis peinard donc je pense avancer et terminer (excepté peut-être la doc) sur le fichier de macros sur lequel je bosse depuis quelques jours.
A la semaine prochaine ;)
Ya Ba Da Ba Dooo!!!
Avatar de l’utilisateur
Alphonse Capriani
 
Messages: 576
Inscription: 18 Juil 2009 19:10
Localisation: East Harlem - NY

Re: Librairie BGRABitmap

Messagepar circular » 06 Août 2018 19:50

Bonjour,

Je suis content de voir ces jolis graphismes avec ma bibliothèque. 8-)

Au sujet du FillMode, je vais regarder cela plus en détail. Cela est peut-être plus compliqué qu'il n'y parait parce que lorsque l'on dessine le contour du polygone, s'il revient sur lui-même on ne veut pas a priori que ce soit alterné. Est-ce que cela conviendrait d'avoir fmWinding pour le contour et la valeur fillmode pour le remplissage ?

Au sujet des hachures, il y a une fonction CreateBrushTexture qui est disponbile dans la classe TBGRABitmap ou bien dans l'unité BGRAPen. Elle s'accomode bien du mode répétition.

Sinon effectivement CanvasBGRA est pour faciliter une transition depuis Canvas mais utilise des coordonnées entières. Effectivement Canvas2D a plus de possibilités. Sinon pour les chemins, s'il y en a plusieurs à manipuler en même temps, la classe TBGRAPath de l'unité BGRAPath pourrait vous être utile.

Cordialement
circular
 
Messages: 24
Inscription: 20 Juin 2011 16:24

Re: Librairie BGRABitmap

Messagepar P.Fradin » 07 Août 2018 09:19

Bonjour,

circular a écrit:Au sujet du FillMode, je vais regarder cela plus en détail. Cela est peut-être plus compliqué qu'il n'y parait parce que lorsque l'on dessine le contour du polygone, s'il revient sur lui-même on ne veut pas a priori que ce soit alterné. Est-ce que cela conviendrait d'avoir fmWinding pour le contour et la valeur fillmode pour le remplissage ?

Oui c'est exactement ça, fillmode pour le remplissage et fmWinding pour le contour sinon on obtient des trucs comme ceci :
testAlternate.png
testAlternate.png (8.87 Kio) Consulté 53408 fois

Je peux aussi contourner le problème en séparant remplissage et contour au lieu d'utiliser StrokeOverFill.

Au sujet des hachures, il y a une fonction CreateBrushTexture qui est disponbile dans la classe TBGRABitmap ou bien dans l'unité BGRAPen. Elle s'accomode bien du mode répétition.

Mais je n'ai pas vraiment réussi à m'en servir pour peindre un chemin (je peins un rectangle englobant en clippant avec le path à remplir mais cela ne donne pas le bon résultat en mode fmAlternate) :oops:
P.Fradin
Avatar de l’utilisateur
P.Fradin
Administrateur du site
 
Messages: 1902
Inscription: 29 Oct 2008 15:04

Re: Librairie BGRABitmap

Messagepar circular » 07 Août 2018 12:31

Oui effectivement, tu peux faire d'abord remplir puis dessiner le contour. Tant que les couleurs sont opaques cela ne fait pas de différence. Avec des couleurs transparentes, cela donne un résultat différent. Cela dépend de ce que tu veux obtenir.

Sinon, avec fmWinding tu peux faire un trou en dessinant un polygone dans le sens horaire et l'autre dans le sens anti-horaire.

Hmm est-ce que tu veux remplir le trait avec une hachure ?

Code: Tout sélectionner
procedure TForm1.FormPaint(Sender: TObject);
var
  p: TBGRAPath;
  bmp: TBGRABitmap;
  b: TBGRACustomBitmap;
begin
  p := TBGRAPath.Create;
  p.moveTo(40,180);
  p.lineTo(200,20);
  p.arc(200,180, 160, -Pi/2, 0, false);
  p.closePath;
  p.moveTo(200,150);
  p.lineTo(330,120);
  p.lineTo(200,50);
  p.closePath;

  bmp := TBGRABitmap.Create(ClientWidth,ClientHeight, BGRAWhite);

  bmp.HorizLine(0,100,400, CSSSilver, dmSet);

  b := bmp.CreateBrushTexture(bsFDiagonal, BGRABlack, BGRAPixelTransparent);
  with bmp.Canvas2d do
  begin
    path(p);
    strokeStyle(b);
    fillStyle(CSSCyan);
    lineWidth := 10;
    strokeOverFill;
  end;
  b.Free;

  bmp.Draw(Canvas,0,0);
  bmp.Free;
end;
Pièces jointes
strokeOverFill.png
strokeOverFill.png (10.53 Kio) Consulté 53406 fois
circular
 
Messages: 24
Inscription: 20 Juin 2011 16:24

Re: Librairie BGRABitmap

Messagepar P.Fradin » 07 Août 2018 12:51

Merci pour cet exemple.
Mais en fait, c'est l'intérieur que je veux hachurer et non le trait.
P.Fradin
Avatar de l’utilisateur
P.Fradin
Administrateur du site
 
Messages: 1902
Inscription: 29 Oct 2008 15:04

Re: Librairie BGRABitmap

Messagepar circular » 07 Août 2018 14:03

Ah alors en intervertissant :
Code: Tout sélectionner
    strokeStyle(CSSCyan);
    fillStyle(b);
Pièces jointes
strokeOverFill2.png
strokeOverFill2.png (11.1 Kio) Consulté 53405 fois
circular
 
Messages: 24
Inscription: 20 Juin 2011 16:24

Re: Librairie BGRABitmap

Messagepar P.Fradin » 07 Août 2018 14:48

Oui bien sûr, j'avais répondu trop vite, avant même d'essayer !
Merci en tout cas pour cet exemple qui m'a permis de résoudre plusieurs de mes soucis. Je pense que là j'obtiens ce que je voulais. La prochaine étape va être d'intégrer les remplissages avec gradients. J'ai toujours cette contrainte que les rendus dans les différents exports (pdf, svg, eps, pstricks, pgf) doivent être identiques (le plus possible en tout cas), et maintenant, grâce à ta librairie, je cherche aussi à ce que le dessin (provisoire) dans TeXgraph soit lui aussi identique !

PS : en lisant un peu le code, j'ai eu l'impression (je me trompe peut-être) que pour le calcul des courbes de Bézier tu n'utilises pas l'algorithme de Hörner (pour évaluer les expressions polynomiales) ?
P.Fradin
Avatar de l’utilisateur
P.Fradin
Administrateur du site
 
Messages: 1902
Inscription: 29 Oct 2008 15:04

Re: Librairie BGRABitmap

Messagepar circular » 07 Août 2018 15:22

P.Fradin a écrit:Oui bien sûr, j'avais répondu trop vite, avant même d'essayer !
Merci en tout cas pour cet exemple qui m'a permis de résoudre plusieurs de mes soucis. Je pense que là j'obtiens ce que je voulais. La prochaine étape va être d'intégrer les remplissages avec gradients. J'ai toujours cette contrainte que les rendus dans les différents exports (pdf, svg, eps, pstricks, pgf) doivent être identiques (le plus possible en tout cas), et maintenant, grâce à ta librairie, je cherche aussi à ce que le dessin (provisoire) dans TeXgraph soit lui aussi identique !

Cool.

Il me semble que les gradients dans les Pdf et Svg sont généralement en sRGB, c'est-à-dire sans correction gamma. Donc s'il y a un paramètre comme cela, probablement le mettre à False est le mieux.

PS : en lisant un peu le code, j'ai eu l'impression (je me trompe peut-être) que pour le calcul des courbes de Bézier tu n'utilises pas l'algorithme de Hörner (pour évaluer les expressions polynomiales) ?

Hmm, d'habitude j'utilise cela. Mais peut-être quelque chose m'a échappé. Peux-tu m'indiquer la portion de code où tu penses que c'est le cas ?
circular
 
Messages: 24
Inscription: 20 Juin 2011 16:24

Re: Librairie BGRABitmap

Messagepar P.Fradin » 07 Août 2018 15:56

Dans cette fonction (geometrytypes.inc):
Code: Tout sélectionner
function TCubicBezierCurve.ComputePointAt(t: single): TPointF;
var
  f1,f2,f3,f4: single;
begin
  f1 := (1-t);
  f2 := f1*f1;
  f1 *= f2;
  f2 *= t*3;
  f4 := t*t;
  f3 := f4*(1-t)*3;
  f4 *= t;

  result.x := f1*p1.x + f2*c1.x +
              f3*c2.x + f4*p2.x;
  result.y := f1*p1.y + f2*c1.y +
              f3*c2.y + f4*p2.y;
end;

Tu calcules $(1-t)^3p_1+3t(1-t)^2c_1+3t^2(1-t)c_2+t^3p_2$ en faisant 16 multiplications par valeur de t. En développant cela fait le polynôme $t^3(p_2-p_1+3c_1-3c_2)+t^2(3p_1+3c_2-6c_1)+t(3c_1-3p_1)+p_1$ (sauf erreur), en nommant $A, B, C, D$ les coefficients de t (qui sont des points 2d), et en précalculant ceux-ci avant le calcul de la liste des points, il alors suffit de calculer pour chaque valeur de $t$ l'expression $D+t(C+t(B+tA))$, ce qui réduit à 6 multiplications (3 par coordonnées). Mais je ne sais pas si la différence serait très sensible.
P.Fradin
Avatar de l’utilisateur
P.Fradin
Administrateur du site
 
Messages: 1902
Inscription: 29 Oct 2008 15:04

Re: Librairie BGRABitmap

Messagepar circular » 08 Août 2018 16:41

Ah j'ai compris. Oui effectivement, si on suppose que les points sont constants, on peut enlever plein de multiplications.

Je suppose qu'on pourrait ajouter un booléen privé "FCoefComputed" et s'il est à False, calculer les coefficients.

Et si on change les points, remettre le booléen à False. En principe on utiliserait des propriétés dans ce cas, ce qui fait que p1, p2, c1, c2 ne seraient plus des variables directement accessibles. Cela empêche d'écrire par exemple
Code: Tout sélectionner
bezier.p1.x := nouveau.x

Cela dit cela a dû arriver rarement puisque a priori, si on change le point, on le change complètement avec
Code: Tout sélectionner
bezier.p1 := PointF(x,y)

C'est-à-dire que cela n'est pas rétrocompatible mais bon qu'il y a peu de chance pour qu'un programme ait à être mise à jour.

Sinon, cela fait grossir la structure en mémoire de 50% mais bon, je pense que c'est ok pour une courbe de Bézier qui en soit représente déjà toute une courbe.

Donc il y a des avantages et des inconvénients. Je serais plutôt favorable à ton idée parce que cela ira potentiellement 3 fois plus vite.

Est-ce que tu as envie de le faire ? Si c'est le cas, tu peux modifier le code, voir si ça marche bien. Je suppose que tu aies besoin d'accès en écriture au dépôt git, puisque tu peux me transmettre un copier-coller du code.

Cordialement
circular
 
Messages: 24
Inscription: 20 Juin 2011 16:24

Re: Librairie BGRABitmap

Messagepar P.Fradin » 08 Août 2018 17:16

À mon avis, il n'y a rien à ajouter, j'ai testé cette fonction:
Code: Tout sélectionner
function TCubicBezierCurve.SimpleComputePoints(AAcceptedDeviation: single;
  AIncludeFirstPoint: boolean = true): ArrayOfTPointF;
var
  t,step: single;
  i,nb: Integer;
  a,b,c: TpointF; //<- ajout pour les coefficients
begin
  nb := ComputeBezierCurvePrecision(p1,c1,c2,p2, AAcceptedDeviation/2);
  if nb <= 1 then nb := 2;
  a:=p2-p1+3*(c1-c2);
  b:=3*(p1+c2)-6*c1;
  c:=3*(c1-p1);
  if AIncludeFirstPoint then
  begin
    setlength(result,nb);
    result[0] := p1;
    result[nb-1] := p2;
    step := 1/(nb-1);
    t := 0;
    for i := 1 to nb-2 do
    begin
      t += step;
      result[i] := p1+t*(c+t*(b+t*a)) // <- plus beson de ComputePointAt(t);
    end;
  end else
  begin
    setlength(result,nb-1);
    result[nb-2] := p2;
    step := 1/(nb-1);
    t := 0;
    for i := 0 to nb-3 do
    begin
      t += step;
      result[i] := p1+t*(c+t*(b+t*a)) // <- plus beson de ComputePointAt(t);
    end;
  end;
end;     

Cela fonctionne chez moi, maintenant tu es mieux placé que moi pour savoir si cette modification est portable.
P.Fradin
Avatar de l’utilisateur
P.Fradin
Administrateur du site
 
Messages: 1902
Inscription: 29 Oct 2008 15:04

Re: Librairie BGRABitmap

Messagepar circular » 09 Août 2018 14:04

Ok oui, effectivement changer la fonction qui calcule toute la courbe est une autre approche qui est rétrocompatible.

Merci pour cette contribution. J'ai essayé de mon côté aussi et cela m'a l'air joli comme il faut. J'ai appliqué le changement sur la branche dev. :)
circular
 
Messages: 24
Inscription: 20 Juin 2011 16:24

Re: Librairie BGRABitmap

Messagepar P.Fradin » 09 Août 2018 14:24

Oui c'est plus simple comme ça.
On peut faire la même chose pour les quadratiques, mais je te ferais peut-être une autre proposition pour les courbe de Bézier quadratiques, faire plutôt des Béziers quadratiques rationnelles, cela ressemble beaucoup mais c'est plus puissant. Une courbe de Bézier quadratique est toujours un arc de parabole, les quadratiques rationnelles donnent un arc de conique propre : arc de parabole, d'ellipse ou d'hyperbole en fonction d'un paramètre, ce paramètre est un poids que l'on met sur le point de contrôle, lorsqu'il vaut 1 c'est la courbe de Bézier classique (parabole), ce pourrait être la valeur par défaut. Ce type de courbe peut être utilisé pour modéliser de manière exacte des arc de cercle ou d'ellipse avec l'avantage que son image par une transformation affine est la courbe de Bézier constituée des images de trois points de construction et avec le même paramètre.

Mais il faut que j'y réfléchisse encore avant de te proposer un code, faudrait-il créer un nouveau type ?
P.Fradin
Avatar de l’utilisateur
P.Fradin
Administrateur du site
 
Messages: 1902
Inscription: 29 Oct 2008 15:04

Re: Librairie BGRABitmap

Messagepar circular » 09 Août 2018 18:30

Intéressant. Dis-moi si j'ai bien compris, une courbe de Bézier quadratique rationnelle peut faire une courbe de Bézier quadratique normale avec le paramètre = 1 et sinon peut être une autre conique ?

C'est fascinant qu'on puisse faire cela. Je cherchais à un moment comment dessiner des ellipses avec rotation ou transformation affine. Je suppose que ces courbes rationnelles permettent de dessiner une ellipse en utilisant les paramètres 0,5 et -0,5 ?

Alors nouveau type ou pas, bonne question. J'aimerais bien qu'on puisse fusionner les deux mais pour plusieurs raisons cela n'est pas faisable :
- le paramètre supplémentaire ne sera pas nécessairement initialisé à 1 : on pourrait utiliser un booléen pour activer le paramètre mais cela un peu confus
- les fonctions qui prennent pour argument une TQuadraticBezierCurve ne s'attendent pas à ce que cela n'en soit pas une et ignoreront la valeur du paramètre : donc il faut leur ajouter du code pour gérer ce cas (c'est une sorte d'incompatibilité)

Donc je dirais nouveau type. Ce serait bien d'avoir les mêmes fonctions ToPoints, Split, ComputeLength et GetBounds. Si l'une d'entre elle pose problème, on peut voir comment résoudre ou contourner le problème.

Après il faudra rajouter les fonctions pour gérer ce nouveau type dans le Canvas2d et TBGRAPath pour que ce soit facile pour l'utilisateur. Je pourrai m'en occuper.

Cordialement
circular
 
Messages: 24
Inscription: 20 Juin 2011 16:24

Re: Librairie BGRABitmap

Messagepar P.Fradin » 11 Août 2018 16:33

Voici une ébauche pour ce nouveau type :
Partie déclarations :
Code: Tout sélectionner
 {Courbe de Bézier rationnelle quadratique quasi standard}
     TRQuadraticBezierCurve = object(TQuadraticBezierCurve)
     {** Weight of control point }
     weight : single;
     private
     function SimpleComputePoints(AAcceptedDeviation: single = 0.1; AIncludeFirstPoint: boolean = true): ArrayOfTPointF;
     public
     function ComputePointAt(t: single): TPointF;
     function ToPoints(AAcceptedDeviation: single = 0.1; AIncludeFirstPoint: boolean = true): ArrayOfTPointF;
     end;

     function BezierCurve(origin, control, destination: TPointF; Aweight:single) : TRQuadraticBezierCurve; overload;


Partie implémentation :
Code: Tout sélectionner
function BezierCurve(origin, control, destination: TPointF; Aweight:single) : TRQuadraticBezierCurve;
 begin
      result.p1 := origin;
      result.c := control;
      result.p2 := destination;
      result.weight := Aweight;
 end;

function TRQuadraticBezierCurve.SimpleComputePoints(AAcceptedDeviation: single;
  AIncludeFirstPoint: boolean = true): ArrayOfTPointF;
const precision = 1e-5;
var
  t,step,len,den: single;
  i,nb: Integer;
  pA,pB,pC,c2 : TpointF;
  a1,b1,c1:single;
begin
  len := sqr(p1.x - c.x) + sqr(p1.y - c.y);
  len := max(len, sqr(c.x - p2.x) + sqr(c.y - p2.y));
  nb := round(sqrt(sqrt(len)/ AAcceptedDeviation));
  //nb := ComputeBezierCurvePrecision(p1,c,c,p2, AAcceptedDeviation);
  if nb <= 1 then nb := 2;
  if AIncludeFirstPoint then
  begin
    setlength(result,nb);
    result[0] := p1;
    result[nb-1] := p2;
    step := 1/(nb-1);
    t := 0;
    c1:=2*weight; c2:=c1*c;
    pA:=p2+p1-c2; pB:=-2*p1+c2;
    a1:=2-c1; b1:=-a1;
    for i := 1 to nb-2 do
    begin
      t += step;
      den := (1+t*(b1+t*a1));
      if abs(den)>=precision then
         result[i] := (p1+t*(pB+t*pA))*(1/den)
      else
         result[i] := EmptyPointF
    end;
  end else
  begin
    setlength(result,nb-1);
    result[nb-2] := p2;
    step := 1/(nb-1);
    t := 0;
    for i := 0 to nb-3 do
    begin
      t += step;
      den := (1+t*(b1+t*a1));
      if abs(den)>=precision then
         result[i] := (p1+t*(pB+t*pA))*(1/den)
      else
         result[i] := EmptyPointF
    end;
  end;
end;

function TRQuadraticBezierCurve.ComputePointAt(t: single): TPointF;
const precision = 1e-5;
var
  rev_t,f2,t2,den: single;
begin
  rev_t := (1-t);
  f2 := weight*rev_t*t*2;//le poids est sur le point de contrôle
  rev_t *= rev_t;
  t2 := t*t;
  den := rev_t+f2+t2;
  if abs(den)>=precision then
     begin
          result.x := (rev_t*p1.x + f2*c.x + t2*p2.x)/den;
          result.y := (rev_t*p1.y + f2*c.y + t2*p2.y)/den;
     end
     else
     result := EmptyPointF
end;

function TRQuadraticBezierCurve.ToPoints(AAcceptedDeviation: single;
  AIncludeFirstPoint: boolean = true): ArrayOfTPointF;
begin
  if weight=1 then
     result := TQuadraticBezierCurve.ToPoints(AAcceptedDeviation, AIncludeFirstPoint)
  else
     result := SimpleComputePoints(AAcceptedDeviation, AIncludeFirstPoint)
end;


Au départ je n'avais pas redéfini la procédure ToPoints() car je pensais qu'avec l'héritage elle appellerait toute seule la bonne fonction SimpleComputePoints (en utilisant la directive virtual, c'est ce que je fais dans TeXgraph avec la hiérarchie des obets graphiques), mais là j'obtiens un violation Access :oops: En redéfinissant cette procédure j'ai pu faire quelques des tests.
Je n'ai pas encore regardé les autres fonctions.
P.Fradin
Avatar de l’utilisateur
P.Fradin
Administrateur du site
 
Messages: 1902
Inscription: 29 Oct 2008 15:04

Re: Librairie BGRABitmap

Messagepar circular » 11 Août 2018 18:54

Cela ne m'étonne pas que tu aies un access violation. Ce sont des objets, pas des classes. Il me semble qu'ils n'ont pas de table de fonctions virtuelles du tout puisque le polymorphisme ne s'applique pas. C'est plutôt comme des record avec des fonctions. Je suggère de ne pas utiliser l'héritage du tout. De toutes façons, presque tout est différent.

Pour ComputeLength et GetBounds, s'il n'y a pas de formule, on peut calculer la courbe en polyligne et ensuite déterminer la longueur de la polyligne. Mais ce serait mieux d'avoir une formule bien sûr.
circular
 
Messages: 24
Inscription: 20 Juin 2011 16:24

Suivant

Revenir vers Version intermédiaire

Qui est en ligne ?

Utilisateurs parcourant ce forum : Aucun utilisateur inscrit et 1 invité