Blog Metlivi

Cara Membina Sapuan Pen Bermata Lebar dengan Menyapu Bentuk Tetap Sepanjang Laluan

Untuk membina sapuan pen bermata lebar, tentukan mata pena segi empat tepat yang sempit, kekalkan sudutnya, dan gerakkannya sepanjang laluan. Sapuan itu ialah gabungan semua kedudukan yang diduduki oleh segi empat tepat tersebut. Ketebalannya berubah mengikut arah pergerakan, walaupun saiz mata pena itu sendiri tidak pernah berubah.

Panduan ini menunjukkan cara membina geometri tersebut untuk lukisan vektor atau aksen watak. Anda akan menentukan mata pena, menyapunya secara berterusan sepanjang garis berpoligon, dan menjana SVG menggunakan program Python yang lengkap. Pembinaan utama ini mengelakkan jurang yang boleh muncul apabila berus disimulasikan dengan cap berasingan.

29 Oktober 20268 minit bacaanOleh Metlivi Editorial Team
Bahagian 1

Apakah maksud menyapu bentuk tetap?

Pisahkan lukisan kepada dua input: laluan yang menerangkan tempat titik rujukan mata pena bergerak, dan jejak yang menerangkan kawasan yang diliputi mata pena pada satu kedudukan. Letakkan titik rujukan jejak pada asalan. Pada setiap kedudukan laluan, tambahkan kedudukan itu pada setiap titik dalam jejak.

Secara matematik, set yang terhasil ialah S = {p + n | p belongs to P, n belongs to N}, dengan P sebagai laluan dan N sebagai mata pena. Ini ialah jumlah Minkowski, berdasarkan takrif titik demi titik dalam manual pengguna Jumlah Minkowski 2D CGAL.

Dalam pembinaan ini, “tetap” bermaksud jejak dan orientasinya kekal sama dalam koordinat lukisan. Mata pena bergerak tanpa berpusing mengikut laluan. Dengan mengekalkan titik rujukan di tengah segi empat tepat, laluan itu menggambarkan pusat mata pena yang bergerak.

Bahagian 2

Bagaimanakah sudut mata pena dan arah pergerakan menentukan ketebalan?

Pilih tiga parameter: dimensi panjang segi empat tepat w, dimensi pendeknya h, dan sudut α bagi sisi panjangnya. Nilai h positif yang kecil memberikan ketebalan minimum yang kelihatan pada mata pena. Mata pena segmen garis yang ideal pula mempunyai ketebalan sifar dan boleh menghasilkan tanda berluas sifar apabila digerakkan tepat mengikut arahnya sendiri.

Bagi segmen laluan lurus dengan sudut arah θ, lebar mata pena segi empat tepat yang diukur serenjang dengan arah pergerakan ialah:

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

Formula ini diperoleh dengan mengunjurkan dua dimensi segi empat tepat yang saling serenjang kepada garis normal laluan. Formula ini menerangkan segmen lurus, atau unjuran jejak setempat sepanjang lengkung licin; bahagian sapuan melengkung yang bertindih boleh menjadikan siluet keseluruhannya lebih lebar.

Bagi mata pena contoh berukuran 24 unit kali 3 unit, pergerakan selari dengan sisi panjang menghasilkan jalur selebar 3 unit. Pergerakan serenjang menghasilkan jalur selebar 24 unit. Pada perbezaan sudut 45°, lebarnya kira-kira (24 + 3) / √2, atau 19.09 unit. Ini ialah dimensi yang dikira, bukan hasil berus yang diukur.

Gunakan tiga arah tersebut sebagai ujian penentukuran sebelum melukis lengkung yang rumit. Ujian ini menunjukkan sama ada sudut dan dimensi berfungsi seperti yang dimaksudkan tanpa perlu menafsirkan beberapa selekoh yang bertindih.

Bahagian 3

Bagaimanakah anda menyapu secara berterusan tanpa meninggalkan jurang antara cap?

Bagi mata pena cembung yang bergerak sepanjang satu segmen lurus, ambil salinan mata pena pada setiap titik hujung dan hitung sarung cembung bagi gabungan bucu kedua-duanya. Sarung itu ialah kawasan tepat yang disapu semasa translasi sepanjang segmen tersebut.

Sebabnya mudah: setiap kedudukan perantaraan ialah interpolasi linear antara kedudukan pada titik hujung. Oleh sebab mata pena itu cembung, sarung tersebut mengandungi tepat kedudukan interpolasi itu. Pembinaan segmen ini ialah akibat langsung daripada takrif jumlah Minkowski, bukannya ciri berus yang berasingan.

Bagi segi empat tepat, setiap segmen hanya menghasilkan lapan titik calon: empat bucu pada permulaan dan empat pada penghujung. Hitung sarungnya, ulangi untuk setiap pasangan titik laluan berturutan, dan gabungkan poligon yang terhasil. Sapuan bersebelahan berkongsi keseluruhan kedudukan mata pena pada titik hujung yang sama, jadi geometri itu mempunyai liputan berterusan.

Jangan hitung satu sarung cembung mengelilingi seluruh laluan. Tindakan itu akan mengisi bahagian dalam selekoh dan menghapuskan lekuk yang dimaksudkan. Sarung itu hanya untuk setiap segmen; keseluruhan sapuan ialah gabungan semua segmen tersebut.

Mata pena cekung memerlukan kaedah lain. Mengambil sarungnya akan mengisi lekukannya. Bahagikannya kepada bahagian cembung, sapu setiap bahagian, kemudian gabungkan hasilnya. CGAL menerangkan pendekatan berkaitan, iaitu penguraian dan penggabungan, untuk jumlah Minkowski bagi poligon bukan cembung.

Bahagian 4

Bagaimanakah anda melaksanakan sapuan dalam Python?

Program lengkap berikut memerlukan Python 3 dan pustaka standardnya. Program ini mentakrifkan laluan contoh dengan lima titik, membina mata pena segi empat tepat, dan mencetak dokumen SVG yang mengandungi empat poligon sapuan berisi. Simpan sebagai broad_edge.py, kemudian jalankan python broad_edge.py > stroke.svg untuk menghasilkan lukisan.

Koordinat mengikut konvensyen SVG yang digunakan di sini: x meningkat ke kanan dan y meningkat ke bawah. Oleh itu, sudut positif dalam program ini mencondongkan mata pena mengikut arah jam pada skrin. Sudut dalam antara muka lukisan lain mungkin menggunakan konvensyen yang berbeza.

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 mengendalikan satu titik laluan dengan melukis satu jejak mata pena. Titik berturutan yang berulang juga menghasilkan jejak tanpa memerlukan pengiraan arah. Laluan kosong dan dimensi mata pena yang bukan positif akan mencetuskan ralat. Berikan pasangan koordinat angka yang terhingga; contoh ringkas ini tidak mengesahkan data laluan yang diimport.

Pembinaan ini dijalankan menggunakan koordinat contoh: ia menghasilkan empat poligon sapuan dengan enam bucu setiap satu, dan SVG yang dijana berjaya dihuraikan sebagai XML. Kes satu titik dan titik berulang juga diperiksa. Pemeriksaan ini mengesahkan pembinaan dan struktur dokumen; pemeriksaan ini bukan ujian pemaparan visual.

Bahagian 5

Bagaimanakah anda mengendalikan lengkung, sudut dan titik hujung?

Contoh ini tepat untuk garis berpoligonnya, tertakluk pada aritmetik titik apung dan pembundaran koordinat. Untuk menggunakan lengkung Bézier, hampirkannya dahulu dengan segmen lurus, kemudian gunakan sapuan yang sama. Tambah lebih banyak segmen di tempat lengkung membengkok dengan tajam dan bukannya mengagihkan semua sampel secara seragam mengikut parameter lengkung.

Pilih toleransi penghampiran berdasarkan saiz output yang dimaksudkan. Sebagai contoh, sisihan suku piksel boleh menjadi sasaran awal paparan, kemudian periksa pada skala terbesar yang dirancang. Ini ialah pilihan kejuruteraan untuk tujuan ilustrasi, bukannya ambang kualiti sejagat. Penambahan subbahagian pada segmen yang memang lurus tidak mengubah kawasan sapuannya.

Asingkan laluan pen yang berasingan. Menghantar titik daripada dua sapuan yang tidak bersambung ke dalam satu panggilan akan menghasilkan sapuan penyambung yang tidak diingini. Jana setiap sapuan secara berasingan dan kumpulkan poligonnya dalam output.

Pada titik hujung, mata pena mengekalkan keseluruhan jejaknya. Pada sudut, dua sapuan yang bersebelahan bertindih. Model ini tidak mempunyai sambungan miter atau hujung bulat tambahan. Sifat sapuan biasa SVG mentakrifkan pembinaan hujung dan sambungannya sendiri, jadi penambahannya akan menghasilkan geometri di luar sapuan mata pena tetap ini. Lihat takrif hujung dan sambungan sapuan SVG 2.

Bahagian 6

Bilakah anda perlu menggabungkan poligon?

Program ini mengeksport poligon berisi yang bertindih. Untuk pratonton warna padu, poligon ini mewakili liputan sapuan tanpa memerlukan pustaka gabungan poligon. Namun, poligon tersebut kekal sebagai objek berasingan yang boleh disunting; program ini tidak mengira satu sempadan gabungan.

Jika anda memerlukan siluet yang kemas untuk penyuntingan garis luar seterusnya, hitung gabungan Boolean bagi semua poligon segmen. Kekalkan sebarang lubang yang kekal pada hasilnya. Laluan yang berlingkar mungkin mengelilingi kawasan yang tidak diwarnakan, dan mengisi setiap kontur tertutup akan mengubah sapuan.

Ketelusan juga perlu dikendalikan dengan teliti. Penggunaan fill-opacity separa secara berasingan pada poligon yang bertindih boleh menjadikan kawasan pertindihan lebih gelap. Untuk ketelusan seragam, kenakan kelegapan pada kumpulan yang merangkumi semuanya, atau gabungkan geometri sebelum mengenakan kelegapan isian. SVG membezakan kelegapan isian objek daripada kelegapan kumpulan dalam spesifikasi pengecatan.

Hasil yang dimaksudkan Langkah seterusnya yang sesuai
Pratonton warna padu Kekalkan poligon sapuan berisi
Pratonton lut sinar seragam Kenakan kelegapan pada kumpulan yang merangkuminya
Satu siluet yang boleh disunting Gabungkan poligon sapuan secara Boolean
Mata pena tersuai yang cekung Uraikan mata pena sebelum menyapunya
Sapuan melengkung yang licin Hampiri lengkung, kemudian sapu segmennya
Bahagian 7

Bagaimanakah anda mendiagnosis sapuan yang tidak dijangka?

Mulakan dengan arah penentukuran, kemudian periksa laluan dan pembinaan output. Ubah satu input pada satu masa supaya punca perubahan yang kelihatan kekal jelas.

  • Ketebalan hampir tidak berubah: Periksa sama ada mata pena berputar mengikut laluan. Sudutnya mesti kekal tetap dalam koordinat lukisan.
  • Ruang kelihatan antara tanda: Gantikan cap terasing dengan pembinaan sarung segmen.
  • Baji lebar mengisi bahagian dalam selekoh: Periksa sama ada anda tersilap mengambil sarung bagi beberapa segmen laluan sekaligus.
  • Hujung kelihatan bulat: Periksa sama ada terdapat sapuan biasa tambahan atau jejak mata pena yang berbeza.
  • Lengkung sumber yang licin kelihatan bersudut: Perhalus penghampiran garis berpoligonnya di sekitar selekoh.
  • Penyambung yang tidak dijangka muncul: Asingkan laluan yang tidak bersambung dalam panggilan sapuan yang berlainan.

Jika anda membandingkan hasilnya dengan alat Kaligrafi Inkscape, dokumentasinya menyediakan semakan parameter yang berguna: Fixation 100 mengekalkan sudut tetap, Thinning 0 menghapuskan variasi lebar berdasarkan halaju, manakala kawalan tekanan dan kecondongan boleh mengubah lebar dan sudut. Nyahdayakan input berubah tersebut apabila meneliti tingkah laku mata pena tetap. Tetapan ini menerangkan kawalan alat itu; tetapan tersebut tidak membuktikan bahawa outputnya sama dengan pembinaan segi empat tepat ini. Lihat dokumentasi Bar Alat Kaligrafi Inkscape.

Sapuan bermata lebar yang boleh diharap bermula dengan laluan penentukuran yang ringkas dan jejak yang ditakrifkan dengan jelas. Setelah ujian selari, serenjang dan pepenjuru berfungsi dengan betul, gunakan sapuan segmen yang sama pada laluan pilihan anda, perhalus bahagian melengkung mengikut skala output, dan gabungkan poligon apabila langkah penyuntingan seterusnya memerlukan satu siluet.

Bahagian 8

Sumber

Bacaan berkaitan

Terus meneroka topik ini