Questo sito utilizza cookies, anche di terze parti, per mostrare pubblicità e servizi in linea con il tuo account. Leggi l'informativa sui cookies.
Username: Password: oppure
C/C++ - Da percorso SVG a GraphicsPath di Gdi+
Forum - C/C++ - Da percorso SVG a GraphicsPath di Gdi+

Pagine: [ 1 2 3 4 ] Precedente | Prossimo
Avatar
AldoBaldo (Member)
Expert


Messaggi: 533
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 16:47
Mercoledì, 24/06/2020
Buongiorno, compari.

Ho da porre un quesito per portare a termine un progettino dei miei, che è ormai quasi concluso tranne che per un... ehm... "dettaglio" che non riesco ad affrontare -- le mie conoscenze di geometria del liceo sono ormai sepolte sotto quarant'anni di oblio, e si sono fatte MOLTO opache.

Il progettino in questione si ripromette di mettere a disposizione una funzione che riceva una stringa di dati nel formato tipico dei percorsi SVG, e la "traduca" in un oggetto di tipo GraphicsPath di Gdi+: Svg2GraphicsPath().

Quando scrivo "una stringa nel formato dei percorsi SVG" intendo quel che è compreso nell'attributo d di un tag di tipo path. Una cosa come questa, nel caso specifico generata da Inkscape:

Codice sorgente - presumibilmente Plain Text

  1. <path d="m 18.9,54.7 c 0,0 6.1,-35.2 23.1,-26.4 17,8.7 9.4,30.2 9.4,30.2 l
  2.          -20,26.8 c 0,0 16.3,-24.2 7.2,-32.5 -9,-8.3 -19.7,1.9 -19.7,1.9 z" />



Svg2GraphicsPath() è al momento operativa per tutti i comandi del formato, sia nella loro versione con spostamenti relativi, sia nella loro versione con spostamenti assoluti. Tutti, tranne i due pestiferi comandi 'a' e 'A', che fanno capo agli archi ellittici (EllipticalArc). Al punto in cui si trova, la funzione Svg2GraphicsPath() "sputa" un errore, schifata, se incontra un comando 'a' o 'A' (almeno posso già usarla con tutti gli altri comandi).

Il problema nasce dal fatto che SVG e Gdi+ hanno moltissimi punti in comune, ma per gli archi ellittici impiegano due metodi completamente diversi, e io non sono in grado di convertire l'uno nell'altro. Non è che ho bisogno un consiglio, è che proprio non so da che parte cominciare e avrei bisogno di qualche anima intrepida che raccogliesse la sfida e si facesse carico di risolvere il problema al posto mio, passandomi un procedimento e delle formule abbastanza semplificati da permettermi di tradurli nel codice corrispondente. Insomma, non è un problema di programmazione, è un problema di geometria!

Ho già predisposto il codice che estrae dalla stringa in formato SVG i parametri degli archi ellittici, trasformandoli in PointF e in REAL di Gdi+. Belli da vedere, ma non so che farmene...

Se qualche cuor di leone si fa avanti, posso mettere a disposizione la documentazione da W3C e da Microsoft della quale dispongo. Tempo fa, Lumo provò molto gentilmente ad aiutarmi, ma non riuscii a stargli dietro e abbandonai l'idea per surriscaldamento cerebrale.

Ultima modifica effettuata da AldoBaldo il 24/06/2020 alle 16:48
PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 645
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 10:22
Giovedì, 25/06/2020
Bella impresa, in SVG sai disegnare? (io no)
Come viene rappresentato un arco in SVG?

Se in C# GDI scrivo:

Codice sorgente - presumibilmente C++

  1. private void Form1_Paint(object sender, System.Windows.Forms.PaintEventArgs e)
  2. {
  3.         GraphicsPath Percorso = new GraphicsPath();
  4.         Percorso.StartFigure();
  5.         Percorso.AddLine(new Point(100, 100), new Point(100, 200));
  6.         Percorso.AddArc(new Rectangle(Convert.ToInt32(Percorso.GetLastPoint().X), Convert.ToInt32(Percorso.GetLastPoint().Y), 350, 100), 180, -100);
  7.         Percorso.AddLine(Percorso.GetLastPoint(), new Point(350, Convert.ToInt32(Percorso.GetLastPoint().Y)));
  8.  
  9.         e.Graphics.DrawPath(new Pen(Color.Red, 2), Percorso);
  10. }



Come sarebbe in SVG?
Non penso che devi rispolverare la trigonometria, i calcoli li fa il linguaggio, in GDI si definisce un rettangolo che inscrive l'arco, poi si definiscono i due angoli di partenza e fine per disegnare solo la porzione che interessa, ma questo credo che lo sai.
Se in SVG l'approcio è completamente diverso e devi ricalcolarti gli angoli di partenza e fine arco, la trigonometria serve!:asd:

Ti ho allegato un file .SVG, non contiene archi, il tuo programma lo convertirebbe in una serie di GraphicsPath? Sono andato troppo oltre?



Carlo ha allegato un file: Philips_PM5544.zip (7347 bytes)
Clicca qui per scaricare il file

Ultima modifica effettuata da Carlo il 25/06/2020 alle 11:22


in programmazione tutto è permesso
PM Quote
Avatar
AldoBaldo (Member)
Expert


Messaggi: 533
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 11:22
Giovedì, 25/06/2020
E' un casino, perché GDI e SVG usano due sistemi completamente diversi. Cito...

===> GDI+ <============================
Description:
The AddArc method adds an elliptical arc to the current figure of this path.

Prototype:
Status AddArc( const Rect& rect, REAL startAngle, REAL sweepAngle );

Parameters:
rect
[in] Reference to a rectangle that bounds the ellipse that contains the arc.
startAngle
[in] Real number that specifies the clockwise angle, in degrees, between the horizontal axis of the ellipse and the starting point of the arc.
sweepAngle
[in] Real number that specifies the clockwise angle, in degrees, between the starting point (startAngle) and the ending point of the arc.
=======================================


===> SVG <=============================
Command: A (absolute), a (relative)
Name: elliptical arc
Parameters: (rx ry x-axis-rotation large-arc-flag sweep-flag x y)+
Description: Draws an elliptical arc from the current point to (x, y). The size and orientation of the ellipse are defined by two radii (rx, ry) and an x-axis-rotation, which indicates how the ellipse as a whole is rotated relative to the current coordinate system. The center (cx, cy) of the ellipse is calculated automatically to satisfy the constraints imposed by the other parameters. large-arc-flag and sweep-flag contribute to the automatic calculations and help determine how the arc is drawn.
=======================================

Ieri sera ho trovato alcune pagine web nelle quali ci sono spiegazioni che probabilmente forniscono INDIZI su come risolvere la questione, e pure intere funzioni che PROBABILMENTE assolvono compiti SIMILI a quelli che servirebbero a me, ma non ci ho capito NULLA. Alla lettera, perché mi mancano proprio le basi. Se pensi di potermi (e di volermi) aiutare, posso segnalarti i collegamenti a quelle pagine. Già il fatto che ti sei preso la briga di rispondermi è incoraggiante.


AldoBaldo ha allegato un file: SVG_EllipticalArcs.gif (209808 bytes)
Clicca qui per guardare l'immagine

Ultima modifica effettuata da AldoBaldo il 25/06/2020 alle 11:23
PM Quote
Avatar
AldoBaldo (Member)
Expert


Messaggi: 533
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 12:24
Giovedì, 25/06/2020
Lo scopo di quel che sto tentando di fare è molto più limitato. Il file che mi hai proposto è un svg completo, con un sacco di elementi <rect> ecc. La funzione che ho in mente si limita a considerare UNA SINGOLA serie di comandi del tipo (per fare un esempio):

Codice sorgente - presumibilmente Plain Text

  1. m 60.4762,80.0417 c 57.4528,0 47.6248,-60.4762 81.6428,-5.2917 34.018,55.184 75.595,107.345 27.97,111.88 -47.625,4.536 -109.6128,19.655 -92.9819,-27.97 16.6309,-47.624 28.7259,-89.9577 40.0659,-44.601 11.339,45.357 22.678,6.048 22.678,6.048 l -15.119,-52.9166 -51.405,29.4822 c 0,0 -5.2913,108.1004 -43.8448,65.7674 -38.5534,-42.333 30.994,-82.3983 30.994,-82.3983 z



Più tardi cercherò di andare più nel dettaglio. Ora ho la pastasciutta nel piatto! :)

PM Quote
Avatar
AldoBaldo (Member)
Expert


Messaggi: 533
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 13:51
Giovedì, 25/06/2020
Allora...

Non ho intenzione di creare nulla che possa anche solo lontanamente somigliare a qualcosa che sia in grado di interpretare il formato SVG dalla A alla Z. Sarebbe un'impresa colossale e sicuramente oltre le mie possibilità, senza contare che esistono già librerie sul tema.

La mia intenzione è ottenere UNA funzione che riceva UNA stringa (che definisce UNA sagoma, più o meno composita, fatta di linee e curve) e che restituisca un oggetto di tipo GraphicsPath in grado di tracciare quel che viene definito nella stringa. Il formato della stringa deve corrispondere a quello previsto per l'attributo (d) di un elemento SVG di tipo <path>.

Ad esempio, usando Inkscape per tracciare la sagoma in allegato, si ottiene un elemento SVG di tipo <path>, il cui attributo d è costituito da questa stringa:

Codice sorgente - presumibilmente Plain Text

  1. m 490.068,220.916 c -3.586,-0.09 -7.193,2.024 -12.017,5.248 -219.735,146.878 -200.91,163.498 -249.479,76.356 0,0 -262.8561,151.428 -117.142,311.425 145.714,159.999 43.797,-141.313 165.711,-224.283 l 205.714,-140.002 114.286,175.717 -40,42.855 c -53.114,56.904 -105.711,137.143 -148.569,-34.285 -24.794,-99.176 -43.288,-51.202 -67.162,13.526 -23.804,64.538 -9.653,36.699 -49.982,152.187 -62.857,180 171.426,122.857 351.426,105.713 179.999,-17.14 22.86,-214.285 -105.711,-422.853 -28.879,-46.848 -37.91,-61.388 -47.075,-61.604 z m -13.64,239.664 c -14.597,0 -26.936,12.341 -26.936,26.938 0,14.596 12.339,26.937 26.936,26.937 14.596,0 26.937,-12.341 26.937,-26.937 0,-14.597 -12.341,-26.938 -26.937,-26.938 z m 81.599,95.214 c 44.937,1.745 102.408,26.751 123.4,65.297 32.855,60.331 -38.25,46.436 -82.857,58.572 -46.227,12.576 -69.21,-16.574 -82.858,-58.572 -14.184,-43.645 3.995,-66.785 42.315,-65.297 z



SVG basa il tracciamento delle sagome <path> sui concetti di "comando" e di "punto corrente": ogni comando è un'istruzione rappresentata da una lettera, è seguito da una serie di parametri, ed ha effetto a partire dal punto corrente. Il punto corrente è il punto che ha coordinate corrispondenti al luogo in cui si arriva in conseguenza dell'esecuzione dell'ultimo comando preso in considerazione. E' un po' lo stesso metodo che usa GDI con MoveToEx() e LineTo().

Nella stringa che ho riportato, il primo comando (m) sta per "move", e dà l'istruzione di posizionare il punto corrente in 490.068,220.916. A seguire, c'è un comando (c), che sta per "curve" e chiede di tracciare una curva di bezier con due punti di controllo e un punto di destinazione, a partire dal punto corrente. I due punti di controllo sono (-3.586,-0.09) e (-7.193,2.024), e il punto di destinazione è (-12.017,5.248). Dal momento che il comando (c) è minuscolo, le coordinate sono da intendersi in senso relativo rispetto al punto corrente (se fosse stato maiuscolo, le coordinate sarebbero state da interpretare in senso assoluto). Esaurita la quantità dei parametri prevista da un certo comando (in questo caso sei, ovvero tre coppie x,y) la stringa viene interpretata cercando un nuovo comando. Se lo si trova, lo si usa; se non lo si trova, si continua ad usare il comando precedente. Dopo (12.017,5.248) NON c'è un comando, ma un nuovo parametro, per cui si intende che il terzo comando nella lista è nuovamente (c), con due punti di controllo (-219.735,146.878), (-200.91,163.498) e un punto di destinazione (-249.479,76.356). E così via...

I comandi che conosco e che ho implementato sono:

Codice sorgente - presumibilmente Delphi

  1. COMANDI CON PARAM. ASSOLUTI   |  COMANDI CON PARAM. RELATIVI
  2. M: move to                    |  m: move to
  3. L: line to                    |  l: line to
  4. H: horizontal line to         |  h: horizontal line to
  5. V: vertical line to           |  v: vertical line to
  6. Z: close path                 |  z: close path
  7. C: curve to                   |  c: curve to
  8. S: smooth curve to            |  s: smooth curve to
  9. Q: quadratic curve to         |  q: quadratic curve to
  10. T: smooth quadratic curve to  |  t: smooth quadratic curve to



Poi ci sono (A) e (a), e lì son dolori! Occorre chiedere aiuto a chi se ne intende di geometria.

A I U T O !!!


AldoBaldo ha allegato un file: sagoma.png (18212 bytes)
Clicca qui per guardare l'immagine

Ultima modifica effettuata da AldoBaldo il 25/06/2020 alle 13:53
PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 645
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 16:06
Giovedì, 25/06/2020
Mi dispiace....
A e a in SVG descrivono un arco che è frutto dell'intersezione di due ellissi, tale approcio ha il vantaggio che si può anche decidere l'orientamento (rotazione) dell'arco, a complicare le cose, si può anche scegliere quale intersezione usare.
In GDI si dovrebbe prima descrivere l'arco (fattibile), poi determinarne la rotazione e l'intersezione (non saprei come).

Spero che qualcuno ti aiuti.

Mio SVG per test:

Codice sorgente - presumibilmente C/C++

  1. <?xml version="1.0" standalone="no"?>
  2. <svg width="12cm" height="12cm" viewBox="0 0 510 510"
  3.      xmlns="http://www.w3.org/2000/svg" version="1.1">
  4.   <title>Example arcs01- arcs commands in path data'</title>
  5.   <desc>A path that draws an arc</desc>
  6.   <rect x="10" y="10" width="500" height="500"
  7.         fill="none" stroke="blue" stroke.width="2"/>
  8.   <path d="M100,200 a50,100 50 1,0 250, -10"
  9.         fill="none" stroke="red" stroke-width="5" />
  10.   <path d="M100,200 a50,100 50 1,1 250, -10"
  11.         fill="none" stroke="blue" stroke-width="5" />
  12.   <path d="M100,200 a50,100 100 1,0 250, -10"
  13.         fill="none" stroke="green" stroke-width="2" />
  14.   <path d="M100,200 a50,100 100 1,1 250, -10"
  15.         fill="none" stroke="purple" stroke-width="2" />
  16. </svg>



In Xamarin ho visto che esiste l'Arco Ellittico e ha lo stesso approcio di SVG, ma è grafica WPF no GDI:
https://docs.microsoft.com/it-it/xamarin/xamarin-forms/user ...

In GDI netcore c'è ArcSegment, potrebbe aiutare:
https://docs.microsoft.com/it-it/dotnet/api/system.windows. ...

Non li conoscevo sono da studiare.


Ultima modifica effettuata da Carlo il 25/06/2020 alle 16:35


in programmazione tutto è permesso
PM Quote
Avatar
AldoBaldo (Member)
Expert


Messaggi: 533
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 17:03
Giovedì, 25/06/2020
Purtroppo per me è fisica nucleare. O greco antico. O qualche altra roba esoterica tipo, che so, sesso venusiano.
Ti ringrazio per il tempo che mi hai dedicato. Chissà che "passi" qualcuno che sa darmi la soluzione.

Per la cronaca: non si tratta di un compito, né di qualcosa che faccio per lucrarci su, quindi non c'è niente di male a chiedere soluzioni "pronte all'uso", nè a fornirle.

Tra l'altro, per l'uso che intendo farne può andare bene anche la versione senza gli archi, perché basta spostare uno qualsiasi dei punti di controllo di uno zero virgola perché Inkscape sostituisca a o A con c o C senza che subentrino modifiche visibili della sagoma. Però mi sarebbe piaciuto poter aggiungere anche gli archi veri e propri, per completezza.

Ultima modifica effettuata da AldoBaldo il 25/06/2020 alle 17:04
PM Quote
Avatar
Carlo (Member)
Guru


Messaggi: 645
Iscritto: 29/01/2018

Segnala al moderatore
Postato alle 17:16
Giovedì, 25/06/2020
Hai detto grafia GDI+, significa che stai lavorando sotto Win e framework?


Ultima modifica effettuata da Carlo il 25/06/2020 alle 17:18


in programmazione tutto è permesso
PM Quote
Avatar
AldoBaldo (Member)
Expert


Messaggi: 533
Iscritto: 08/01/2015

Segnala al moderatore
Postato alle 17:48
Giovedì, 25/06/2020
Per i miei giochetti uso alcune parti di Win32. Per la grafica GDI e GDI+.

PM Quote
Pagine: [ 1 2 3 4 ] Precedente | Prossimo