2015-04-16 14 views
5

Ich möchte nur eine vertikale gepunktete dicke Linie auf einer Ebene in ImgView32 zeichnen. Ich möchte auch, dass meine Linie dicker ist, also zeichne ich mehrere Linien nahe beieinander, weil Canvas.Pen.Width keinen Einfluss auf die LineTo-Methoden hat. Also mein Code ist wie folgt:Zeichnen einer dicken gepunkteten Linie auf einer ImgView32-Ebene

procedure TMainForm.PaintDottedHandler(Sender: TObject;Buffer: TBitmap32); 
var 
    Cx, Cy,raza: Single; 
    W2, H2: Single; 
    I,J: Integer; 
    points:TArrayOfFloatPoint; 
    Center, Radius:TFloatPoint; 
const 
    CScale = 1/200; 
begin 

    if Sender is TPositionedLayer then 
    with TPositionedLayer(Sender).GetAdjustedLocation do 
    begin 
     W2 := (Right - Left) * 0.5; 
     H2 := (Bottom - Top) * 0.5; 

     Cx := Left + W2; 
     Cy := Top + H2; 
     W2 := W2 * CScale; 
     H2 := H2 * CScale; 
     Buffer.PenColor := clRed32; 

     Buffer.MoveToF(Cx-2,Top); 
     Buffer.LineToFSP(Cx-2 , Bottom); 

     Buffer.MoveToF(Cx-1,Top); 
     Buffer.LineToFSP(Cx-1 , Bottom); 

     Buffer.MoveToF(Cx,Top); 
     Buffer.LineToFSP(Cx , Bottom); 

     Buffer.MoveToF(Cx+1,Top); 
     Buffer.LineToFSP(Cx+1 , Bottom); 

     Buffer.MoveToF(Cx+2,Top); 
     Buffer.LineToFSP(Cx+2 , Bottom); 
    end; 
end; 

So ist die Linie soll in der Mitte der neuen Ebene platziert werden. Ich füge die Schicht dies mit:

procedure TMainForm.DottedLine1Click(Sender: TObject); 
var 
    L: TPositionedLayer; 
begin 
    L := CreatePositionedLayer; 
    L.OnPaint := PaintDottedHandler; 
    L.Tag := 2; 
    Selection := L; 
end; 

Für den Rest des Codes nur den Code des Ebenen-Beispiel hinzufügen und Sie werden in der Lage, mein Problem zu reproduzieren.

Soweit ich gelesen habe, gibt es mehrere aproaches, wie Stipple mit LineToFSP (in meinem Code verwendet) oder PolyPolygonFS mit einem BuildDashedLine Punkte, um eine gepunktete Linie zu zeichnen. Aber ich kann anscheinend nicht alle dazu bringen, richtig zu arbeiten. Eigentlich macht der zweite Ansatz nichts ... also bleibe ich bei meinem ersten Ansatz. So scheint es, als ob jedes Mal, wenn es beginnt, eine Linie zu zeichnen, es zufällig ist, wie die gepunktete Linie beginnt. Es ist also entweder ein Pixel oder ein leeres Pixel. So , wenn ich die Schicht der Linie transformiert sich wie in den folgenden Bildern die Größe:

before resizing after first resize after more resizing after more resizing

Und in der Tat alles, was ich erreichen will, ist dies:

desired result

Und natürlich möchte ich, dass die Linie wieder gezeichnet wird, wenn ich die Größe der Ebene ändere, ohne sie zu verzerren (deshalb verwende ich onPain t-Handler-Ansatz). Wenn ich einfach eine einfache Linie auf einen Layer zeichne (mit Bitmap.Canvas) und dann die Größe des Layers ändere, dann würde die Linie genauso verzerrt werden wie das Dehnen eines JPEG, also möchte ich das vermeiden.

Also mir bitte sagen, wie auf einer Schicht in ImgView32 (TGraphics32)

EDIT

Nach dem Versuch, den Code aus den Antworten eine dicke gepunktete Linie zeichnen ich es Arbeit gemacht. Jedoch gibt es einen Nebeneffekt diese Schicht: Wenn die Schicht Ändern der Größe (mit der Maus), an einigen Breiten die Farbe der gestrichelten Linie gedimmt und verschwommene wie unten:

Bevor enter image description here Nach Ändern der Größe Ändern der Größe (manchmal). enter image description here

Sie können dies mit demselben Code selbst reproduzieren.

EDIT

ein weiteres Problem mit dieser speziellen Schicht Es ist: mit zwei Ansätzen es zu speichern ... Datei Ich habe versucht, es als transparenten PNG zu speichern, aber ich halte eine beschädigte Datei zu bekommen. Selbst wenn ich versuche, den Layer als Bitmap zu speichern, tritt die gleiche Beschädigung auf.Bitte überprüfen Sie diese Frage aus zu:

Graphics32 - saving transparent drawing layer to png

+0

Nur eine wilde Vermutung, aber in Ihrem MoveToF und LineToFSP, würde ich Cy-Koordinaten anstelle von Top und Bottom verwenden. –

+0

Cy ist eine Variable von einem anderen Handler, wo ich Kreise zeichne, und ich benutzte es, um die Koordinaten der Mitte der Ebene zu erhalten. Also (Cx, Cy) ist der Mittelpunkt der Ebene. Wie würde die Verwendung von Cy mir bei meinem oben beschriebenen Problem helfen? – user1137313

+0

Sie erfinden das Rad hier neu. Sie sollten die ausgezeichnete GR32_Lines-Erweiterung verwenden. –

Antwort

3

Wie @SpeedFreak erwähnt Sie StrippleCounter vor jeder Zeile Zeichenaufruf zurücksetzen müssen. Sie müssen außerdem ein geeignetes Linienmuster für Ihre Linie einrichten. Dies könnte durch SetStripple Methode durchgeführt werden. Der Trick besteht darin, dieses Muster korrekt für die Breite Ihrer Linie einzurichten. Wenn Ihre Linie 5 Pixel breit ist, benötigen Sie ein Muster, das aus 5 schwarzen Pixeln und 5 weißen Pixeln besteht.

dies ausprobieren, ich habe unnötiger Code entfernt (aktualisiert):

procedure TMainForm.PaintDottedHandler(Sender: TObject; Buffer: TBitmap32); 
var 
    R: TRect; 
    Cx: Integer; 
begin 
    if Sender is TPositionedLayer then 
    begin 
    // Five black pixels, five white pixels since width of the line is 5px 
    Buffer.SetStipple([clBlack32, clBlack32, clBlack32, clBlack32, clBlack32, 
     clWhite32, clWhite32, clWhite32, clWhite32, clWhite32]); 
    // We mest operate on integer values to avoid blurred line. 
    R := MakeRect(TPositionedLayer(Sender).GetAdjustedLocation); 
    Cx := R.Left + (R.Right - R.Left) div 2; 

    Buffer.StippleCounter := 0; 
    Buffer.MoveToF(Cx-2, R.Top); 
    Buffer.LineToFSP(Cx-2 , R.Bottom); 

    Buffer.StippleCounter := 0; 
    Buffer.MoveToF(Cx-1, R.Top); 
    Buffer.LineToFSP(Cx-1 , R.Bottom); 

    Buffer.StippleCounter := 0; 
    Buffer.MoveToF(Cx, R.Top); 
    Buffer.LineToFSP(Cx , R.Bottom); 

    Buffer.StippleCounter := 0; 
    Buffer.MoveToF(Cx+1, R.Top); 
    Buffer.LineToFSP(Cx+1 , R.Bottom); 

    Buffer.StippleCounter := 0; 
    Buffer.MoveToF(Cx+2, R.Top); 
    Buffer.LineToFSP(Cx+2 , R.Bottom); 
    end; 
end; 

Und das Ergebnis sollte wie auf dem Bild sein:

Line example

Der Grund für die Sie‘ Es gibt von Zeit zu Zeit eine "unscharfe" Linie, wenn die Größe der Ebene geändert wird, weil Sie mit Fließkommawerten gearbeitet haben, um die Linie zu zeichnen. Sie müssen Ganzzahlwerte verwenden. Ich vermute, dass in einigen Fällen die Zeichnungs-Engine entschied, ein unscharfes Pixel zu zeichnen, wenn Ihre Linie nur den Teil dieses Pixels füllte.

Hoffe, das hilft.

+0

Ihr Code funktioniert großartig. Haben Sie jedoch eine Idee, wie Sie den sichtbaren Effekt vermeiden können, wenn Sie versuchen, die Ebene horizontal zu verändern? Bei einigen Breiten wird die Zeichnung von Schwarz in ein Dunkelgrau umgewandelt. Irgendeine Idee warum dies passiert und wie man es verhindert? – user1137313

+0

Ich habe dieses Verhalten nicht bemerkt. Bitte aktualisieren Sie Ihre Frage mit einem Bild, das den Nebeneffekt zeigt. – Wodzu

+0

Überprüfen Sie die bearbeitete Frage. Aber Sie sollten in der Lage sein, den Effekt selbst zu reproduzieren. Versuchen Sie, die Ebene langsam horizontal mit der Maus zu skalieren. Sie werden feststellen, dass die Zeichnung von Zeit zu Zeit verschwimmt und in der Farbe abgeblendet wird. – user1137313

3

Sie müssen die stipple counter zwischen jeder Zeile zurückgesetzt. Ansonsten wird jede Linie das Muster fortsetzen, wo die vorherige aufhörte:

Buffer.StippleCounter := 0; 
Buffer.MoveToF(Cx-2,Top); 
Buffer.LineToFSP(Cx-2 , Bottom); 

Buffer.StippleCounter := 0; 
Buffer.MoveToF(Cx-1,Top); 
Buffer.LineToFSP(Cx-1 , Bottom); 
...etc... 

Sie haben nicht gezeigt, wie Sie Ihre pattern eingerichtet ist, aber von Ihren Beispielen zu urteilen könnte es ein Problem auch dort sein. Ich würde (jetzt) ​​tun es so etwas wie dieses:

Buffer.SetStipple([clBlack32, clBlack32, clBlack32, clBlack32, clBlack32, 
    clWhite32, clWhite32, clWhite32, clWhite32, clWhite32]); // Alternating black and white, 5 pixels each 
+1

'StippleStep' Ist hier kein richtiger Ansatz. Diese Eigenschaft ist verantwortlich für den Fading-Effekt. Mit dem Wert 1/5 sagen Sie der Zeichnungs-Engine, die Farbe in fünf Schritten zu verblassen. – Wodzu

+0

Sie haben Recht. Ich habe 'StippleStep' aus der Antwort entfernt. – SpeedFreak

Verwandte Themen