Blog Metlivi

Cara Membuat Sapuan Pena Bertepi Lebar dengan Menyapu Bentuk Tetap Sepanjang Jalur

Untuk membuat sapuan pena bertepi lebar, tentukan mata pena persegi panjang yang sempit, pertahankan sudutnya, lalu geser sepanjang jalur. Sapuan tersebut merupakan gabungan semua posisi yang ditempati persegi panjang itu. Ketebalannya berubah sesuai arah gerak, meskipun ukuran mata pena tidak pernah berubah.

Panduan ini menunjukkan cara menyusun geometri tersebut untuk gambar vektor atau aksen karakter. Anda akan menentukan mata pena, menyapukannya secara kontinu sepanjang garis poligonal, dan menghasilkan SVG menggunakan program Python lengkap. Konstruksi utamanya menghindari celah yang dapat muncul saat kuas disimulasikan dengan cap terpisah.

29 Oktober 20268 menit membacaOleh Metlivi Editorial Team
Bagian 1

Apa arti menyapu bentuk tetap?

Pisahkan gambar menjadi dua masukan: jalur yang menggambarkan lintasan titik acuan mata pena, dan jejak yang menggambarkan area yang tertutup mata pena pada satu posisi. Letakkan titik acuan jejak di titik asal. Pada setiap posisi di jalur, tambahkan posisi tersebut ke setiap titik pada jejak.

Secara matematis, himpunan yang dihasilkan adalah S = {p + n | p belongs to P, n belongs to N}, dengan P sebagai jalur dan N sebagai mata pena. Ini adalah jumlah Minkowski, mengikuti definisi titik demi titik dalam panduan pengguna Jumlah Minkowski 2D CGAL.

Dalam konstruksi ini, “tetap” berarti jejak dan orientasinya sama-sama tidak berubah dalam koordinat gambar. Mata pena bergeser tanpa berputar mengikuti jalur. Dengan mempertahankan titik acuan di tengah persegi panjang, jalur menggambarkan lintasan pusat mata pena yang bergerak.

Bagian 2

Bagaimana sudut mata pena dan arah gerak menentukan ketebalan?

Pilih tiga parameter: dimensi panjang persegi panjang w, dimensi pendeknya h, dan sudut α sisi panjangnya. Nilai h yang kecil dan positif memberi mata pena ketebalan minimum yang terlihat. Sebaliknya, mata pena berupa ruas garis ideal memiliki ketebalan nol dan dapat menghasilkan tanda berluas nol jika digerakkan tepat searah dengan panjangnya.

Untuk segmen jalur lurus dengan sudut arah θ, lebar mata pena persegi panjang yang diukur tegak lurus terhadap arah gerak adalah:

width across the stroke = w × |sin(θ − α)| + h × |cos(θ − α)|

Rumus ini diperoleh dengan memproyeksikan kedua dimensi persegi panjang yang saling tegak lurus ke arah normal jalur. Rumus tersebut menggambarkan segmen lurus, atau proyeksi jejak lokal sepanjang kurva mulus; bagian sapuan melengkung yang saling tumpang tindih dapat membuat siluet keseluruhannya lebih lebar.

Untuk mata pena ilustratif berukuran 24 unit kali 3 unit, gerak sejajar dengan sisi panjang menghasilkan jalur selebar 3 unit. Gerak tegak lurus menghasilkan jalur selebar 24 unit. Pada selisih sudut 45°, lebarnya kira-kira (24 + 3) / √2, atau 19,09 unit. Ini adalah dimensi hasil perhitungan, bukan hasil pengukuran kuas.

Gunakan ketiga arah tersebut sebagai uji kalibrasi sebelum menggambar kurva yang rumit. Uji ini menunjukkan apakah sudut dan dimensinya berperilaku sesuai harapan tanpa mengharuskan Anda menafsirkan beberapa lekukan yang saling bertumpuk.

Bagian 3

Bagaimana cara menyapu secara kontinu tanpa meninggalkan celah antarcap?

Untuk mata pena cembung yang bergerak sepanjang satu segmen lurus, buat salinan mata pena pada setiap titik ujung, lalu hitung selubung cembung dari gabungan titik sudut keduanya. Selubung itu tepat mencakup area yang tersapu selama translasi sepanjang segmen tersebut.

Alasannya sederhana: setiap penempatan di antaranya merupakan interpolasi linear antara penempatan pada kedua titik ujung. Karena mata pena tersebut cembung, selubungnya mencakup tepat posisi-posisi interpolasi itu. Konstruksi segmen ini merupakan konsekuensi langsung dari definisi jumlah Minkowski, bukan fitur kuas yang terpisah.

Untuk persegi panjang, setiap segmen hanya menghasilkan delapan titik kandidat: empat sudut di awal dan empat di akhir. Hitung selubungnya, ulangi untuk setiap pasangan titik jalur yang berurutan, lalu gabungkan poligon yang dihasilkan. Sapuan yang bersebelahan berbagi seluruh penempatan mata pena pada titik ujung bersama, sehingga geometrinya memiliki cakupan kontinu.

Jangan hitung satu selubung cembung di sekeliling seluruh jalur. Itu akan mengisi area di antara lekukan dan menghapus ceruk yang diinginkan. Selubung dibuat untuk setiap segmen secara terpisah; sapuan lengkap merupakan gabungan semuanya.

Mata pena cekung memerlukan penanganan berbeda. Mengambil selubungnya akan mengisi lekukannya. Uraikan menjadi bagian-bagian cembung, sapu setiap bagian, lalu gabungkan hasilnya. CGAL mendokumentasikan pendekatan penguraian dan penggabungan terkait untuk jumlah Minkowski dari poligon noncembung.

Bagian 4

Bagaimana cara menerapkan sapuan dalam Python?

Program lengkap berikut memerlukan Python 3 dan pustaka standarnya. Program ini menetapkan contoh jalur dengan lima titik, membangun mata pena persegi panjang, dan mencetak dokumen SVG yang berisi empat poligon sapuan terisi. Simpan sebagai broad_edge.py, lalu jalankan python broad_edge.py > stroke.svg untuk membuat gambar.

Koordinat mengikuti konvensi SVG yang digunakan di sini: x bertambah ke kanan dan y bertambah ke bawah. Karena itu, sudut positif dalam program ini memiringkan mata pena searah jarum jam pada layar. Antarmuka gambar lain mungkin menggunakan konvensi berbeda.

from math import cos, sin, radians


def hull(points):
    pts = sorted(set(points))
    if len(pts) <= 1:
        return pts

    def cross(o, a, b):
        return ((a[0] - o[0]) * (b[1] - o[1])
                - (a[1] - o[1]) * (b[0] - o[0]))

    def half(sequence):
        out = []
        for p in sequence:
            while len(out) >= 2 and cross(out[-2], out[-1], p) <= 0:
                out.pop()
            out.append(p)
        return out

    return half(pts)[:-1] + half(reversed(pts))[:-1]


def sweep(path, width=24, thickness=3, angle=30):
    if not path or width <= 0 or thickness <= 0:
        raise ValueError(
            'Provide a nonempty path and positive nib dimensions'
        )

    a = radians(angle)
    u = (cos(a), sin(a))
    v = (-sin(a), cos(a))
    nib = [
        (s * width * u[0] / 2 + t * thickness * v[0] / 2,
         s * width * u[1] / 2 + t * thickness * v[1] / 2)
        for s, t in [(-1, -1), (1, -1), (1, 1), (-1, 1)]
    ]
    pairs = list(zip(path, path[1:])) or [(path[0], path[0])]
    return [
        hull([(p[0] + q[0], p[1] + q[1])
              for p in (start, end) for q in nib])
        for start, end in pairs
    ]


path = [(40, 45), (85, 125), (140, 150), (195, 110), (245, 45)]
polygons = sweep(path)
all_points = [p for polygon in polygons for p in polygon]
x0, y0 = (min(p[i] for p in all_points) - 5 for i in (0, 1))
x1, y1 = (max(p[i] for p in all_points) + 5 for i in (0, 1))

svg = [
    '<svg xmlns="http://www.w3.org/2000/svg" '
    f'viewBox="{x0} {y0} {x1 - x0} {y1 - y0}">',
    '<g fill="#23364d" stroke="none">'
]
for polygon in polygons:
    coordinates = ' '.join(f'{x:.6f},{y:.6f}' for x, y in polygon)
    svg.append(f'<polygon points="{coordinates}"/>')
svg.extend(['</g>', '</svg>'])
print('\n'.join(svg))

Program ini menangani jalur satu titik dengan menggambar satu jejak mata pena. Titik berurutan yang berulang juga menghasilkan jejak, tanpa perlu menghitung arah. Jalur kosong dan dimensi mata pena yang tidak positif akan memunculkan galat. Masukkan pasangan koordinat numerik yang bernilai hingga; contoh ringkas ini tidak memvalidasi data jalur yang diimpor.

Konstruksi ini dijalankan dengan koordinat contoh: hasilnya empat poligon sapuan dengan masing-masing enam titik sudut, dan SVG yang dihasilkan berhasil diuraikan sebagai XML. Kasus satu titik dan titik berulang juga diperiksa. Pemeriksaan ini memverifikasi konstruksi dan struktur dokumen, tetapi bukan pengujian visualisasi hasil render.

Bagian 5

Bagaimana menangani kurva, sudut, dan titik ujung?

Contoh ini tepat untuk garis poligonalnya, dengan memperhitungkan aritmetika titik mengambang dan pembulatan koordinat. Untuk menggunakan kurva Bézier, aproksimasi terlebih dahulu dengan segmen lurus, lalu terapkan sapuan yang sama. Tambahkan lebih banyak segmen di bagian kurva yang melengkung tajam, alih-alih menyebarkan semua sampel secara merata pada parameter kurva.

Pilih toleransi aproksimasi sesuai ukuran keluaran yang diinginkan. Sebagai contoh, penyimpangan seperempat piksel dapat menjadi sasaran awal untuk tampilan, lalu periksa pada skala terbesar yang direncanakan. Itu pilihan rekayasa yang bersifat ilustratif, bukan ambang mutu universal. Yang penting, penambahan pembagian di sepanjang segmen yang sudah lurus tidak mengubah area yang tersapu.

Pisahkan jalur pena yang terputus. Jika titik dari dua sapuan terpisah dimasukkan ke satu pemanggilan, akan terbentuk sapuan penghubung yang tidak diinginkan. Buat setiap sapuan secara terpisah dan kumpulkan poligonnya dalam keluaran.

Pada titik ujung, mata pena tetap mempertahankan seluruh jejaknya. Pada sudut, kedua sapuan yang bersebelahan saling tumpang tindih. Model ini tidak menambahkan sambungan miter atau ujung membulat. Properti sapuan biasa SVG menentukan konstruksi ujung dan sambungannya sendiri, sehingga penambahannya akan menghasilkan geometri di luar sapuan mata pena tetap ini. Lihat definisi ujung dan sambungan sapuan dalam SVG 2.

Bagian 6

Kapan poligon perlu digabungkan?

Program ini mengekspor poligon terisi yang saling tumpang tindih. Untuk pratinjau warna solid, poligon tersebut merepresentasikan cakupan sapuan tanpa memerlukan pustaka penggabungan poligon. Namun, objeknya tetap terpisah dan dapat diedit; program ini tidak menghitung satu batas gabungan.

Jika Anda memerlukan siluet rapi untuk penyuntingan garis tepi berikutnya, hitung gabungan Boolean dari semua poligon segmen. Pertahankan lubang yang tersisa pada hasilnya. Jalur melingkar dapat mengelilingi area yang tidak diwarnai, dan mengisi setiap kontur tertutup akan mengubah sapuan.

Transparansi juga perlu ditangani dengan saksama. Menerapkan fill-opacity parsial pada poligon yang saling tumpang tindih secara terpisah dapat membuat area tumpang tindih lebih gelap. Untuk transparansi yang seragam, terapkan opasitas pada grup pembungkus atau gabungkan geometri sebelum menerapkan opasitas isian. SVG membedakan opasitas isian objek dari opasitas grup dalam spesifikasi pengecatannya.

Hasil yang diinginkan Langkah selanjutnya yang sesuai
Pratinjau warna solid Pertahankan poligon sapuan terisi
Pratinjau transparan seragam Terapkan opasitas pada grup pembungkusnya
Satu siluet yang dapat diedit Gabungkan poligon sapuan dengan operasi Boolean
Mata pena kustom cekung Uraikan mata pena sebelum menyapunya
Sapuan melengkung mulus Aproksimasi kurva, lalu sapu segmen-segmennya
Bagian 7

Bagaimana mendiagnosis sapuan yang tidak sesuai harapan?

Mulailah dengan arah kalibrasi, lalu periksa jalur dan konstruksi keluaran. Ubah satu masukan setiap kali agar penyebab perubahan yang terlihat tetap jelas.

  • Ketebalan hampir tidak berubah: Periksa apakah mata pena berputar mengikuti jalur. Sudutnya harus tetap dalam koordinat gambar.
  • Muncul celah yang terlihat di antara tanda: Ganti cap terpisah dengan konstruksi selubung segmen.
  • Baji lebar mengisi bagian dalam lekukan: Periksa apakah Anda tidak sengaja mengambil selubung beberapa segmen jalur sekaligus.
  • Ujungnya tampak membulat: Periksa apakah ada sapuan biasa tambahan atau jejak mata pena yang berbeda.
  • Kurva sumber yang mulus tampak bersudut: Perhalus aproksimasi garis poligonal di sekitar lekukan.
  • Muncul penghubung yang tidak diinginkan: Pisahkan jalur yang terputus ke dalam pemanggilan sapuan berbeda.

Jika Anda membandingkan hasilnya dengan alat Kaligrafi Inkscape, dokumentasinya menyediakan pemeriksaan parameter yang berguna: Fixation 100 mempertahankan sudut, Thinning 0 menghilangkan variasi lebar berdasarkan kecepatan, dan kontrol tekanan serta kemiringan dapat mengubah lebar dan sudut. Nonaktifkan masukan yang berubah-ubah itu saat memeriksa perilaku mata pena tetap. Pengaturan ini menjelaskan kontrol alat tersebut; pengaturan ini tidak membuktikan bahwa keluarannya identik dengan konstruksi persegi panjang ini. Lihat dokumentasi Bilah Alat Kaligrafi Inkscape.

Sapuan bertepi lebar yang andal bermula dari jalur kalibrasi sederhana dan jejak yang didefinisikan dengan jelas. Setelah uji sejajar, tegak lurus, dan diagonal berperilaku benar, terapkan sapuan segmen yang sama pada jalur pilihan Anda, perhalus bagian melengkung agar sesuai dengan skala keluaran, dan gabungkan poligon saat langkah penyuntingan berikutnya memerlukan satu siluet.

Bagian 8

Sumber

Bacaan terkait

Lanjutkan topik ini