2015-04-16 28 views
5

Sadece ImgView32'deki bir katmana dikey noktalı kalın çizgi çizmek istiyorum. Ayrıca, satırımın kalın olmasını istiyorum, böylece Canvas.Pen.Width'in LineTo yöntemleri üzerinde bir etkisi olmadığından, birbirine yakın çok çizgi çiziyorum. ImgView32 katmanında kalın noktalı çizgi çizimi

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; 

Yani çizgi amaçlanmaktadır

yeni tabakasının ortasında yerleştirilmek üzere şu şekildedir: Yani benim kodudur. Sadece Katmanlar Örneğin benim kodu ekleyin kod kalanı için

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

ve sen benim sorunu yeniden mümkün olacak: Bu kullanarak katman ekleyin.

Okuduğum kadarıyla noktalı bir çizgi çizmek için, LineToFSP ile Stipple (kodumda kullanılır) veya BuildDashedLine noktaları olan PolyPolygonFS gibi birden çok yazıcı vardır. Fakat hiçbirinin dürüstçe çalışmasını sağlayamıyorum. Aslında ikinci yaklaşım bir şey yapmıyor ... bu yüzden ilk yaklaşımımı sürdürüyorum. Bu yüzden bir çizgi çizmeye başladığı her sefer, noktalı çizginin başladığı şekilde rastgele görünüyor. Yani ya bir piksel ya da boş bir. Ben katmanı yeniden boyutlandırmak zaman Yani çizgi izleyen görüntülerde gibi dönüştürür:

desired result

:

before resizingafter first resize after more resizing after more resizing

Ve aslında ben başarmak isteyen tüm şudur

Ve tabiki çarpmadan katmanı yeniden boyutlandırırken çizginin tekrar çizilmesini istiyorum (bu yüzden onPain'i kullanıyorum) t işleyici yaklaşımı. Bir katmana (Bitmap.Canvas kullanarak) basit bir çizgi çizip katmanı yeniden boyutlandırırsam, çizgi bir jpeg'i germek gibi çarpıtılır, bundan kaçınmak isterim.

Peki nasıl çalışması yapılmış cevaplar kodu denedikten sonra ImgView32 (TGraphics32) bir katman üzerinde

DÜZENLEME

kalın noktalı çizgi çizmek için söyle lütfen. Bununla birlikte, bu tabakanın bir yan etki vardır: bir katman (fare kullanarak) yeniden boyutlandırma, bazı genişliklerinde noktalı çizgi rengi soluk ve körük gibi bulanık:

bazen (boyutlandırma sonra enter image description here boyutlandırma önce). enter image description here

Kendinizi aynı kodu kullanarak yeniden oluşturabilirsiniz.

DÜZENLEME

bu özel tabaka ile başka sorun var: o dosyaya kaydediliyor ... ben 2 yaklaşımlar kullanılarak şeffaf PNG olarak kaydedin çalıştım ama bozuk bir dosyayı almaya devam. Katmanı Bitmap olarak kaydetmeye çalışsa bile aynı bozulma oluşur.de bu soruyu göz atın:

Graphics32 - saving transparent drawing layer to png

+0

Sadece vahşi bir tahmin, ancak MoveToF ve LineToFSP'nizde, Üst ve Alttan ziyade Cy koordinatlarını kullanırdım. –

+0

Cy, çember çizdiğim başka bir işleyicideki değişkendir ve bunu, katmanın ortasındaki koordinatları almak için kullandım. Yani (Cx, Cy) ve katmanın merkez noktası. Cy kullanmak yukarıda açıklanan problemimle nasıl yardımcı olur? – user1137313

+0

Tekerleği yeniden icat ediyorsun. Mükemmel GR32_Lines uzantısını kullanmalısınız. –

cevap

3

. Ayrıca, hattınıza uygun bir çizgi deseni ayarlamanız da gerekir. Bu SetStripple yöntemi ile yapılabilir. Hile, bu kalıbı çizginizin genişliği için doğru şekilde ayarlamaktır. Çizginiz 5 piksel genişliğinde ise, 5 siyah piksel ve 5 beyaz pikselden oluşan bir desene ihtiyacınız vardır.

bu deneyin, ben kaldırdık gereksiz kod (güncellendi):

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; 

Ve sonuç resme gibi olmalıdır:

Line example

nedeni kendisi için' Satır yeniden boyutlandırılırken zaman zaman "bulanık" satır var, çünkü çizgi çizmek için kayan nokta değerleri üzerinde çalışıyordunuz. Tamsayı değerleri kullanmanız gerekir. Bazı durumlarda, çizim motorunun, çizginiz yalnızca bu pikselin bir kısmını doldururken bulanık bir piksel çizmeye karar verdiğimi tahmin ediyorum.

Bu yardımcı olur umarım.

+0

Kodunuz harika çalışıyor. Ancak, katmanı yatay olarak yeniden boyutlandırmaya çalışırken görülebilen yan etkinin nasıl önleneceğine dair herhangi bir fikriniz var mı? Bazı genişliklerde çizim siyahtan koyu griye dönüşür. Bunun neden olduğu ve nasıl önleneceği hakkında bir fikrin var mı? – user1137313

+0

Bu davranışı fark etmedim. Lütfen sorunuzu yan etkiyi gösterecek görüntü ile güncelleyin. – Wodzu

+0

Düzenlenen soruya göz atın. Ama bu etkiyi kendiniz üretebilmeniz gerekir. Sadece fare kullanarak yatay olarak katmanı yavaşça yeniden boyutlandırmayı deneyin. Zaman zaman, çizimin – user1137313

3

Her hat arasındaki stipple counter sıfırlamak gerekir. senin pattern de var bir sorun ayarlandı ancak örneklerden yargılamak olabileceğini nasıl

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... 

Sen olmadığını göstermiştir: Aksi her satır önceki bıraktığı desen devam edecektir. Ben (şimdi) böyle o şey yapacağını: @SpeedFreak her bir satır beraberlik çağrısından önce StrippleCounter sıfırlamak gerekir belirtildiği gibi

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

'StippleStep' Burada doğru bir yaklaşım değil. Bu özellik solma etkisinden sorumludur, 1/5 değerini vererek çizim motoruna beş adımda renk solması gerektiğini söylersiniz. – Wodzu

+0

Haklısınız. StippleStep'i cevaptan çıkardım. – SpeedFreak

İlgili konular