banryu79
01-05-2008, 16:06
Lo scenario:
Ho un insieme di figure a contorno chiuso che rappresentano ognuna una sagoma reale da tagliare con una macchina CN.
Queste figure vengono dispososte su una lastra di materiale di forma rettangolare e dimensione nota.
Devo renderizzare queste figure, disposte sul pannello, per visualizzarle all'utente e permettergli di interfacciarsi con il mouse per riposizionarle dove meglio crede nella lastra (quindi trascinamento della sagoma, sua rotazione attorno al proprio centro).
L'immagine della lastra e delle sagome che contiene viene renderizzata sull'oggetto Graphics (Graphics2D) di un JPanel contenuto in una JDialog; per una visualizzazione opportuna, il rendering viene scalato e l'immagine della lastra centrata nel JPanel.
Il problema:
Ad ogni evento MouseMoved si vogliono stampare a video (in una zona apposita del Graphics) le coordinate correnti del puntatore del mouse.
Si recuperano le coordinate correnti del mouse all'interno del metodo public void mouseMoved(MouseEvent e) del Listener e tramite i metodi e.getX() ed e.getY().
Le coordinate così ottenute però non sono le coordinate "user space" (infatti il disegno della lastra è stato scalato e traslato) ma le coordinate screen/device space (cioè i valori X e Y correnti del mouse rispetto le origini del sistema cartesiano "nativo" del componente: l'origine è l'angolo in alto a sinistra, l'asse delle X si estende con verso positivo a destra, l'asse delle Y con verso positivo in basso).
Si devono quindi mappare le coordinate così ricavate rispetto alle trasformazioni inizialmente applicate al Graphics2D: ho visto in giro che normalmente basta prendere dal Graphics2D la sua trasformazione affine modificata dai vari translate(), rotate() ecc... e utilizzare quella per calcolare l'inversa da applicare alle coordinate del mouse in "device space" per ottenere le corrispettive coordinate in "user space".
Ho provato con questo approccio ma ottengo un risultato "strano" che temo dipenda da come utilizzo il Graphics2D e le AffineTransform
Ho realizzato un piccolo test per verificare la cosa, e di questo ora parlo: ho un JFrame che contiene 2 JPanel: in quello superiore ci sono delle label, una checkbox e dei textField; quello inferiore a sua volta contiene un altro JPanel, dove avviene il rendering (ho fatto così perchè il JPanel esterno l'ho inserito tramite Matisse e non lo posso estendere, mentre il JPanel interno è una mia classe che estende JPanel).
Quello che succede nel test è il semplice disegno degli assi cartesiani centrati sull'origine (X0Y0) del sistema di riferimento del Graphics2D su cui vengono poi disegnati un Rectangle2D e un Arc2D (stile "PIE").
Con i primi due textField in alto a sinistra si possono impostare dei valori in X e Y per eseguire una traslazione dell'origine in quelle coordinate.
C'è un MouseListener che on MouseMoved stampa continuamente i valori delle coordinate mappate in "device" e in "user" space.
Infine a destra c'è la stampa dei valori attualmente contenuti nella AffineTransform associata al Graphics2D su cui si renderizza. Questi valori vengono aggiornati solo all'evento MouseEntered nel JPanel di rendering.
Il problema è che mentre i valori delle coordinate "device space" del mouse combaciano sempre (provare prima e dopo eventuali traslazioni) i relativi valori rimappati in "user space" non sono esatti, perchè sembra (e si evince anche esaminando i valori stampati della AffineTransform) che sia sempre presente una certa quantità di offset sia nelle coordinate X (molto poco) che nelle Y (molto di più).
Guardando bene il valore di questo offset, ho quasi l'impressione che rappresenti la distanza (aka traslazione) del punto x0y0 del JPanel su cui disegno rispetto al punto x0y0 del JFrame che lo contiene.
Per chiarezza allego codice (due classi) e jar file eseguibile del applicativo di test.
Il jar è il file TransformTests.zip, basta rinominarlo cambiandogli l'estensione in .jar
Più tardi mi riconnetto per postare delle immagini di esempio che ho catturato, ora devo volare che ho la cresima di un cuginetto :D
Se qualcuno si è già imbattuto in un problema analogo o ha semplicemente già affrontato in un modo diverso la questione o ancora meglio sa esattamente cosa succede e mi da consigli gliene sarò davvero molto grato.
Ciao a tutti :)
Ho un insieme di figure a contorno chiuso che rappresentano ognuna una sagoma reale da tagliare con una macchina CN.
Queste figure vengono dispososte su una lastra di materiale di forma rettangolare e dimensione nota.
Devo renderizzare queste figure, disposte sul pannello, per visualizzarle all'utente e permettergli di interfacciarsi con il mouse per riposizionarle dove meglio crede nella lastra (quindi trascinamento della sagoma, sua rotazione attorno al proprio centro).
L'immagine della lastra e delle sagome che contiene viene renderizzata sull'oggetto Graphics (Graphics2D) di un JPanel contenuto in una JDialog; per una visualizzazione opportuna, il rendering viene scalato e l'immagine della lastra centrata nel JPanel.
Il problema:
Ad ogni evento MouseMoved si vogliono stampare a video (in una zona apposita del Graphics) le coordinate correnti del puntatore del mouse.
Si recuperano le coordinate correnti del mouse all'interno del metodo public void mouseMoved(MouseEvent e) del Listener e tramite i metodi e.getX() ed e.getY().
Le coordinate così ottenute però non sono le coordinate "user space" (infatti il disegno della lastra è stato scalato e traslato) ma le coordinate screen/device space (cioè i valori X e Y correnti del mouse rispetto le origini del sistema cartesiano "nativo" del componente: l'origine è l'angolo in alto a sinistra, l'asse delle X si estende con verso positivo a destra, l'asse delle Y con verso positivo in basso).
Si devono quindi mappare le coordinate così ricavate rispetto alle trasformazioni inizialmente applicate al Graphics2D: ho visto in giro che normalmente basta prendere dal Graphics2D la sua trasformazione affine modificata dai vari translate(), rotate() ecc... e utilizzare quella per calcolare l'inversa da applicare alle coordinate del mouse in "device space" per ottenere le corrispettive coordinate in "user space".
Ho provato con questo approccio ma ottengo un risultato "strano" che temo dipenda da come utilizzo il Graphics2D e le AffineTransform
Ho realizzato un piccolo test per verificare la cosa, e di questo ora parlo: ho un JFrame che contiene 2 JPanel: in quello superiore ci sono delle label, una checkbox e dei textField; quello inferiore a sua volta contiene un altro JPanel, dove avviene il rendering (ho fatto così perchè il JPanel esterno l'ho inserito tramite Matisse e non lo posso estendere, mentre il JPanel interno è una mia classe che estende JPanel).
Quello che succede nel test è il semplice disegno degli assi cartesiani centrati sull'origine (X0Y0) del sistema di riferimento del Graphics2D su cui vengono poi disegnati un Rectangle2D e un Arc2D (stile "PIE").
Con i primi due textField in alto a sinistra si possono impostare dei valori in X e Y per eseguire una traslazione dell'origine in quelle coordinate.
C'è un MouseListener che on MouseMoved stampa continuamente i valori delle coordinate mappate in "device" e in "user" space.
Infine a destra c'è la stampa dei valori attualmente contenuti nella AffineTransform associata al Graphics2D su cui si renderizza. Questi valori vengono aggiornati solo all'evento MouseEntered nel JPanel di rendering.
Il problema è che mentre i valori delle coordinate "device space" del mouse combaciano sempre (provare prima e dopo eventuali traslazioni) i relativi valori rimappati in "user space" non sono esatti, perchè sembra (e si evince anche esaminando i valori stampati della AffineTransform) che sia sempre presente una certa quantità di offset sia nelle coordinate X (molto poco) che nelle Y (molto di più).
Guardando bene il valore di questo offset, ho quasi l'impressione che rappresenti la distanza (aka traslazione) del punto x0y0 del JPanel su cui disegno rispetto al punto x0y0 del JFrame che lo contiene.
Per chiarezza allego codice (due classi) e jar file eseguibile del applicativo di test.
Il jar è il file TransformTests.zip, basta rinominarlo cambiandogli l'estensione in .jar
Più tardi mi riconnetto per postare delle immagini di esempio che ho catturato, ora devo volare che ho la cresima di un cuginetto :D
Se qualcuno si è già imbattuto in un problema analogo o ha semplicemente già affrontato in un modo diverso la questione o ancora meglio sa esattamente cosa succede e mi da consigli gliene sarò davvero molto grato.
Ciao a tutti :)