View Full Version : [C#] Graphics.DrawLines disegnare linee con "bordi"
ciao ragazzi!
il mio problema è questo: vorrei disegnare una linea larga x che ha il centro di un colore e i due bordi di un altro..
ho provato creando un Texturebrush da una bitmap di questo tipo:
"#" bordo
"O"
"O" colore principale
"O"
"#" bordo
il problema che quando creo una pen larga x con il suddetto brush la linea mi viene riempita senza "girare la pen" al cambiamento di inclinazione della linea...
quindi il risultato è del tipo:
###
OOO
OOO
OOO
###
###
OOO
OOO
OOO
###
invece che
#OOO#
#OOO#
#OOO#
come posso fare?
grazie!
banryu79
23-09-2010, 21:07
Non conosco C# ma ho un'idea: creati una classe che rappresenti la tua linea con i bordi e faccia ciò che desideri; in particolare ti basta eseguire 3 operazioni di "disegno linea".
Una per disegnare la "linea centrale" con lo spessore "centrale" e il colore "centrale", e due per disegnare le due "linee dei bordi", con lo "spessore dei bordi" e il "colore dei bordi".
Non conosco C# ma ho un'idea: creati una classe che rappresenti la tua linea con i bordi e faccia ciò che desideri; in particolare ti basta eseguire 3 operazioni di "disegno linea".
Una per disegnare la "linea centrale" con lo spessore "centrale" e il colore "centrale", e due per disegnare le due "linee dei bordi", con lo "spessore dei bordi" e il "colore dei bordi".
questa era la soluzione estrema.. dovrei eseguire molto codice in più per fare ciò :D (nel senso di spostare un array di punti su e giù)
banryu79
24-09-2010, 08:36
questa era la soluzione estrema.. dovrei eseguire molto codice in più per fare ciò :D (nel senso di spostare un array di punti su e giù)
E perchè mai?
Supponendo che il metodo per disegnare una linea esposto dall'oggetto Graphics della libreria C# sia un metodo che prende 4 parametri, tipo:
Graphics
void drawLine(int x1, int y1, int x2, int y2)
Ti puoi creare una classe utility che espone un metodo che prende in ingresso il riferimento al Graphics sul quale deve disegnare la linea e le coordinate della linea.
La linea da disegnare in realtà è una linea-composta, ovvero due linee singole: una di spessore uguale allo spessore totale desiderato e di colore uguale al colore dei bordi e l'altra di spessore minore, del colore della linea centrale, da disegnarci sopra.
Le caratteristiche/stato della linea-composta da rappresentare potrebbero essere:
- spessore totale linea "bordi"
- colore linea "bordi"
- spessore minore linea "centrale"
- colore linea "centrale"
A questo punto la tua classe, che potrebbe chiamarsi LineService, potrebbe tenere memorizzato questo stato in modo statico (cioè a livello di classe e non di istanza) ed esporre un metodo statico che permetta di settarlo.
Infine espone un metodo statico "draw" che prende in ingresso il riferimento al Graphic su cui disegnare, le coordinate del punto di inizio e fine della linea e disegna le due linee: prima quella più grossa, e poi sopra l'altra.
Bisognerebbe però verificare se il risultato, per certi insiemi di valori, a livello estetico, è gradevole.
Ecco uno stralcio (tanto per dare un'idea) in Java (vedi la classe LineService):
import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Stroke;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;
/**
* Class LineServiceExample
*
* @author Francesco Baro
*/
public class LineServiceExample
{
public static void main(String[] args) {
// imposto le caratteristiche della linea composta
LineService.setEdgeLineAttributes(6.0f, Color.black);
LineService.setCenterLineAttributes(4.0f, Color.yellow);
// creiamo un array di coordinate per le linee
final int[] COORD = new int[] {100,100, 200,100, 200,150, 120,250};
// creiamo una "tela" (canvas) sulla quale eseguire
// il disegno delle nostre linee
final JPanel CANVAS = new JPanel() {
@Override public void paintComponent(Graphics g) {
final int STEP = 2;
for (int i=0; i<(COORD.length-STEP); i=i+STEP)
LineService.draw(g, COORD[i], COORD[i+1], COORD[i+2], COORD[i+3]);
}
};
CANVAS.setPreferredSize(new Dimension(640, 480));
// creaiamo e visualizziamo la finestra che contiene
// la nostra tela di disegno:
final JFrame FRAME = new JFrame("LineService example");
FRAME.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
FRAME.add(CANVAS);
// le operazioni che rendono "visualizzabile" un componente
// in Swing vanno fatte eseguire da un apposito thread
SwingUtilities.invokeLater(new Runnable() {
@Override public void run() {
FRAME.pack(); // rende visualizzabile FRAME
FRAME.setLocationRelativeTo(null); // centra FRAME nello schermo
FRAME.setVisible(true); // si spiega da se, no?
}
});
}
}
class LineService
{
// line for rendering the edges
private static Stroke edgeLineStroke;
private static Color edgeColor;
// line for rendering the center
private static Stroke centerLineStroke;
private static Color centerColor;
public static void setEdgeLineAttributes(float width, Color color) {
edgeLineStroke = new BasicStroke(width);
edgeColor = color;
}
public static void setCenterLineAttributes(float width, Color color) {
centerLineStroke = new BasicStroke(width);
centerColor = color;
}
public static void draw(Graphics graphics, int x1, int y1, int x2, int y2) {
Graphics2D g = (Graphics2D) graphics;
g.setColor(edgeColor);
g.setStroke(edgeLineStroke);
g.drawLine(x1, y1, x2, y2);
g.setColor(centerColor);
g.setStroke(centerLineStroke);
g.drawLine(x1, y1, x2, y2);
}
}
vien fuori sta roba:
http://www.freeimagehosting.net/uploads/0b11d7eb43.png (http://www.freeimagehosting.net/)
vista così non sembra una cattiva idea... stasera ci provo...
io avevo pensato a disegnare 2 linee x i bordi..
ma la tua idea è molto più sensata e semplice rispetto alle mie :D
usando drawlineS non dovrebbero venire nemmeno i bordini sul lato piccolo in teoria ^^
grazie!
banryu79
24-09-2010, 10:24
io avevo pensato a disegnare 2 linee x i bordi..
Anche io all'inizio: è la cosa ovvia, ma poi uno si accorge che così gli toccherebbe calcolare e impostare un offset per le coordianate da usare nel disegno delle due linee per i bordi, mentre disegnandone una sola grossa sotto la linea centrale si evita questa operazione.
Il trade-off è che così non puoi avere i due bordi di spessore e colore diverso tra loro.
Nota che rispetto al codice postato, puoi migliorare molto LineService, a partire dal nome, dal codice ridonante, dallo supportare le caratteristiche di stroking tipiche delle penne (tipo gli stili per gli "end cap", i "line join" e così via).
A quel punto avrebbe senso avere più istanze della classe, per supportare una pluralità di stili/linee con caratteristiche diverse.
testato e perfetto... manca un pò di antialias ma tutto verrà a suo tempo...
renderizzare le strade con i bordi è tutto un'altra cosa su una mappa :D
grazie mille!
vBulletin® v3.6.4, Copyright ©2000-2025, Jelsoft Enterprises Ltd.