Bagikan melalui


Sampel Penghapusan Tinta

Aplikasi ini dibangun berdasarkan Sampel Koleksi Tinta dengan mendemonstrasikan penghapusan goresan tinta. Sampel ini menyediakan pengguna dengan menu yang memiliki empat mode untuk dipilih: mendukung tinta, menghapus di titik puncak, menghapus di titik perpotongan, dan menghapus goresan.

Dalam mode berkemampuan tinta, objek InkCollector mengumpulkan tinta seperti yang ditunjukkan dalam Sampel Koleksi Tinta.

Dalam mode penghapusan, segmen goresan tinta yang ada yang disentuh pengguna dengan kursor dihapus. Selain itu, titik atau persimpangan dapat ditandai dengan lingkaran merah.

Bagian paling menarik dari sampel ini terletak pada penanganan aktivitas OnPaint formulir InkErase dan dalam fungsi penghapusan yang dipanggil dari penanganan aktivitas OnMouseMove formulir.

Mengelilingi Cusps dan Persimpangan

Pengelola acara OnPaint dari formulir awalnya menggambar goresan, dan tergantung pada mode aplikasi, dapat menemukan dan menandai semua titik tajam atau persimpangan dengan lingkaran merah kecil. Sebuah cusp menandai titik di mana garis berubah arah secara tiba-tiba. Persimpangan menandai titik di mana satu goresan bersinggungan dengan dirinya sendiri atau goresan lain.

Peristiwa Paint terjadi setiap kali kontrol digambar ulang.

Nota

Sampel memaksa formulir untuk menggambar ulang dirinya sendiri setiap kali stroke dihapus, atau ketika mode aplikasi berubah, menggunakan metode Refresh formulir.

 

private void InkErase_OnPaint(object sender, PaintEventArgs e)
{
    Strokes strokesToPaint = myInkCollector.Ink.Strokes;

    myInkCollector.Renderer.Draw(e.Graphics, strokesToPaint);

    switch (mode)
    {
        case ApplicationMode.CuspErase:
            PaintCusps(e.Graphics, strokesToPaint);
            break;
        case ApplicationMode.IntersectErase:
            PaintIntersections(e.Graphics, strokesToPaint);
            break;
    }
}

Dalam PaintCusps, kode melakukan iterasi pada setiap cusp di setiap goresan, dan menggambar lingkaran merah di sekitarnya. Properti PolylineCusps dari stroke mengembalikan indeks dari titik-titik dalam stroke yang sesuai dengan cusps. Selain itu, perhatikan metode Renderer objek InkSpaceToPixel, yang mengonversi titik ke koordinat yang relevan dengan metode DrawEllipse.

private void PaintCusps(Graphics g, Strokes strokesToPaint)
{
    foreach (Stroke currentStroke in strokesToPaint)
    {
        int[] cusps = currentStroke.PolylineCusps;

        foreach (int i in cusps)
        {
            Point pt = currentStroke.GetPoint(i);

            // Convert the X, Y position to Window based pixel coordinates
            myInkCollector.Renderer.InkSpaceToPixel(g, ref pt);

            // Draw a red circle as the cusp position
            g.DrawEllipse(Pens.Red, pt.X-3, pt.Y-3, 6, 6);
        }
    }
}

Dalam PaintIntersections, kode berulang melalui setiap goresan untuk menemukan persimpangannya dengan seluruh set goresan. Perhatikan bahwa metode FindIntersections stroke diteruskan stroke koleksi dan mengembalikan array nilai indeks titik mengambang yang mewakili persimpangan. Kode kemudian menghitung koordinat X-Y untuk setiap persimpangan, dan menggambar lingkaran merah di sekitarnya.

private void PaintIntersections(Graphics g, Strokes strokesToPaint)
{
    foreach (Stroke currentStroke in strokesToPaint)
    {
        float[] intersections =            currentStroke.FindIntersections(strokesToPaint);
    }
}

Menangani Pena yang Memiliki Dua Ujung

Tiga pengendali peristiwa didefinisikan untuk objek InkCollector pada peristiwa CursorDown, NewPackets, dan Stroke. Setiap penangan kejadian memeriksa properti Terbalik dari objek Kursor untuk menentukan ujung pena mana yang sedang digunakan. Ketika pena dibalik:

  • Metode myInkCollector_CursorDown membuat stroke transparan.
  • Metode myInkCollector_NewPackets menghapus goresan.
  • Metode myInkCollector_Stroke membatalkan acara. Peristiwa NewPackets dihasilkan sebelum peristiwa Stroke.

Melacak Kursor

Baik pengguna menggunakan pena maupun mouse, MouseMove menghasilkan peristiwa. Penanganan aktivitas MouseMove pertama-tama memeriksa untuk menentukan apakah mode saat ini adalah mode penghapusan dan jika ada tombol mouse yang ditekan, dan mengabaikan peristiwa jika status ini tidak ada. Kemudian, penanganan aktivitas mengonversi koordinat piksel untuk kursor menjadi koordinat ruang tinta dengan menggunakan metode Renderer objek PixelToInkSpace, dan memanggil salah satu metode penghapusan kode tergantung pada mode penghapusan saat ini.

Menghapus Goresan

Metode EraseStrokes mengambil lokasi kursor di ruang tinta dan menghasilkan kumpulan goresan yang berada dalam unit HitTestRadius. Parameter currentStroke menentukan objek Stroke yang tidak boleh dihapus. Kemudian kumpulan coretan dihapus dari kumpulan, dan bentuknya digambar ulang.

private void EraseStrokes(Point pt, Stroke currentStroke)
{
    Strokes strokesHit = myInkCollector.Ink.HitTest(pt, HitTestRadius);

    if (null!=currentStroke && strokesHit.Contains(currentStroke))
    {
        strokesHit.Remove(currentStroke);
    }

    myInkCollector.Ink.DeleteStrokes(strokesHit);

    if (strokesHit.Count > 0)
    {
        this.Refresh();
    }
}

Menghapus di Simpang Jalan

Metode EraseAtIntersections mengiterasi setiap garis yang termasuk dalam radius uji dan menghasilkan array titik perpotongan antara garis itu dan semua garis lainnya dalam koleksi. Jika tidak ada persimpangan yang ditemukan, maka seluruh garis tersebut akan dihapus; jika tidak, titik terdekat pada garis dengan titik pengujian ditentukan, dan dari sana, persimpangan di kedua sisi titik tersebut ditemukan, yang menggambarkan segmen yang akan dihapus.

Metode Stroke objek Split digunakan untuk memisahkan segmen dari sisa goresan, dan kemudian segmen dihapus, membiarkan sisa stroke tetap utuh. Seperti dalam EraseStrokes, bentuk digambar ulang sebelum metode dikembalikan.

private void EraseAtIntersections(Point pt)
{
    Strokes strokesHit = myInkCollector.Ink.HitTest(pt, HitTestRadius);

    foreach (Stroke currentStroke in strokesHit)
    {
        float[] intersections = currentStroke.FindIntersections(myInkCollector.Ink.Strokes);
        ...
        float findex = currentStroke.NearestPoint(pt);
        ...
        strokeToDelete = currentStroke.Split(intersections[i]);
        ...
    }
    ...
}

Menghapus di Cusps

Untuk setiap stroke yang termasuk dalam radius pengujian, metode EraseAtCusps mengambil array cusps dari metode objek Stroke PolylineCusps. Setiap ujung garis juga merupakan titik tajam, jadi apabila garis hanya memiliki dua titik tajam, seluruh garis akan dihapus; jika tidak, titik terdekat pada garis ke titik pengujian akan ditemukan, dan dari sana, persimpangan di kedua sisi titik tersebut ditentukan, menggambarkan segmen yang akan dihapus.

Metode Stroke objek Split digunakan untuk memisahkan segmen dari sisa goresan, dan kemudian segmen dihapus, membiarkan sisa stroke tetap utuh. Seperti dalam EraseStrokes, bentuk digambar ulang sebelum metode mengembalikan.

private void EraseAtCusps(Point pt)
{
    ...
    strokesHit = myInkCollector.Ink.HitTest(pt, HitTestRadius);
    
    foreach (Stroke currentStroke in strokesHit)
    {
        int[] cusps = currentStroke.PolylineCusps;
        ...
        float findex = currentStroke.NearestPoint(pt);
        ...
        strokeToDelete = currentStroke.Split(cusps[i]); 
        myInkCollector.Ink.DeleteStroke(strokeToDelete);
        ...
    }
    ...
}

Menutup Formulir

Metode Buang formulir membuang objek InkCollector, myInkCollector.