skishore / makemeahanzi

Free, open-source Chinese character data
https://www.skishore.me/makemeahanzi/
Other
1.83k stars 465 forks source link

Generate non-animated stroke order diagrams #47

Open T-vK opened 5 years ago

T-vK commented 5 years ago

I find it much easier to work with non-animated stroke order diagrams because I can just take my time and don't have to watch an animation over and over again.
Would it be possible to generate diagrams like this with makemeahanzi?
non-animated stroke order diagram

T-vK commented 5 years ago

I figured out a way in which I could write a simple script to generate images like this from all the SVGs: test

Any ideas how to make the text not be flipped horizontally and vertically? Here is the svg code:

<svg version="1.1" viewBox="0 0 1024 1024" xmlns="http://www.w3.org/2000/svg">
  <g stroke="lightgray" stroke-dasharray="1,1" stroke-width="1" transform="scale(4, 4)">
    <line x1="0" y1="0" x2="256" y2="256"></line>
    <line x1="256" y1="0" x2="0" y2="256"></line>
    <line x1="128" y1="0" x2="128" y2="256"></line>
    <line x1="0" y1="128" x2="256" y2="128"></line>
  </g>
  <g transform="scale(1, -1) translate(0, -900)">
      <style>
        .stroke1 {fill: #BF0909;}
        .stroke2 {fill: #BFBF09;}
        .stroke3 {fill: #09BF09;}
        .stroke4 {fill: #09BFBF;}
        .stroke5 {fill: #0909BF;}
        .stroke6 {fill: #BF09BF;}
        .stroke7 {fill: #BFBFBF;}
        .stroke8 {fill: #090909;}
        text {
            font-family: Helvetica;
            font-size: 80px;
            fill: #FFFFFF;
            paint-order: stroke;
            stroke: #000000;
            stroke-width: 4px;
            stroke-linecap: butt;
            stroke-linejoin: miter;
            font-weight: 800;
        }
      </style>
      <path class="stroke1" d="M 272 567 Q 306 613 342 669 Q 370 718 395 743 Q 405 753 400 769 Q 396 782 365 808 Q 337 827 316 828 Q 297 827 305 802 Q 318 769 306 741 Q 267 647 207 560 Q 150 476 72 385 Q 60 375 58 367 Q 54 355 70 358 Q 82 359 109 384 Q 155 421 213 493 Q 226 509 241 527 L 272 567 Z" fill="#BF0909"></path>

      <path class="stroke2" d="M 241 527 Q 262 506 258 375 Q 258 374 258 370 Q 254 253 221 135 Q 215 114 224 80 Q 236 44 248 32 Q 267 16 279 44 Q 294 86 294 134 Q 303 420 314 485 Q 321 515 295 543 Q 289 549 272 567 C 251 589 227 553 241 527 Z" fill="lightgray"></path>

      <path class="stroke3" d="M 521 560 Q 561 621 602 708 Q 620 751 638 773 Q 645 786 639 799 Q 633 811 602 830 Q 572 846 554 843 Q 535 839 546 817 Q 561 795 552 757 Q 513 619 407 448 Q 398 436 397 430 Q 394 418 409 423 Q 439 432 503 532 L 521 560 Z" fill="lightgray"></path>

      <path class="stroke4" d="M 503 532 Q 527 510 555 520 Q 795 608 782 549 Q 783 543 743 468 Q 736 458 741 453 Q 745 447 756 459 Q 852 532 894 549 Q 904 552 905 561 Q 906 574 876 592 Q 852 605 828 621 Q 800 637 783 630 Q 686 590 521 560 C 492 555 479 550 503 532 Z" fill="lightgray"></path>

      <path class="stroke5" d="M 568 72 Q 531 81 494 91 Q 482 94 483 86 Q 484 79 494 71 Q 569 7 596 -33 Q 611 -49 626 -36 Q 659 -3 661 82 Q 655 149 655 345 Q 656 382 667 407 Q 676 426 659 439 Q 634 461 604 470 Q 585 477 577 469 Q 571 462 582 447 Q 619 384 603 127 Q 597 82 589 74 Q 582 67 568 72 Z" fill="lightgray"></path>

      <path class="stroke6" d="M 444 320 Q 419 262 385 208 Q 364 180 381 144 Q 388 128 409 139 Q 460 181 468 264 Q 472 295 467 319 Q 463 328 456 328 Q 449 327 444 320 Z" fill="lightgray"></path>

      <path class="stroke7" d="M 738 307 Q 789 249 847 168 Q 860 146 876 139 Q 885 138 893 146 Q 908 159 900 204 Q 891 264 743 338 Q 734 345 731 332 Q 728 319 738 307 Z" fill="lightgray"></path>

      <text x="317" y="812">1</text>
      <text x="273" y="558">2</text>
      <text x="556" y="828">3</text>
      <text x="513" y="532">4</text>
      <text x="586" y="463">5</text>
      <text x="455" y="316">6</text>
      <text x="742" y="326">7</text>
  </g>
</svg>
skishore commented 5 years ago

Hi T-vK, thanks for your question!

The data in graphics.txt should be more than enough to generate images like that. It's just a question of automating the process. I would use the "medians" field of each character to get a list of line segments for each stroke.

The biggest challenge is laying out the numbers. A force-based layout algorithm would work well - have each number attracted to the start of its stroke and repelled by other strokes.

Would you be interested in trying to get that working? Since the graphics.txt file is just a bunch of JSON lines, Python is as viable an option as Javascript for this task.

On Tue, Aug 28, 2018 at 9:53 AM, T-vK notifications@github.com wrote:

I find it much easier to work with non-animated stroke order diagrams because I can just take my time and don't have to watch an animation over and over again. Would it be possible to generate diagrams like this with makemeahanzi? [image: non-animated stroke order diagram] https://camo.githubusercontent.com/93dc2144225b6c33de488a5e172674df89c6c81b/68747470733a2f2f646c332e616e6b697765622e6e65742f7368617265642f6d707265766965772f3734383537303138372f302e706e673f373335383139

— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/skishore/makemeahanzi/issues/47, or mute the thread https://github.com/notifications/unsubscribe-auth/AAmE0L8DXgLewdWpEFnTcjimZSAchRQJks5uVUtxgaJpZM4WPqZV .

skishore commented 5 years ago

There's a "g transform=..." around all the strokes to change from font coordinates to graphics coordinates.

You could apply the transform to each stroke and then drop it from the g; the text elements would then be the right way up. To do that, split each stroke on spaces, and for each pair of consecutive numbers (x, y), replace y with 900 - y.

On Tue, Aug 28, 2018 at 11:58 AM, T-vK notifications@github.com wrote:

I figured out a way in which I could write a simple script to generate images like this from all the SVGs:

[image: test] https://user-images.githubusercontent.com/11368523/44734832-1a4b9e80-aaeb-11e8-9efa-20bea7dfce8f.png

Any ideas how to make the text not be flipped horizontally and vertically? Here is the svg code:

1 2 3 4 5 6 7

— You are receiving this because you commented. Reply to this email directly, view it on GitHub https://github.com/skishore/makemeahanzi/issues/47#issuecomment-416640631, or mute the thread https://github.com/notifications/unsubscribe-auth/AAmE0APBN8EjhRTklXAXGm0RDNOIMb4yks5uVWicgaJpZM4WPqZV .

T-vK commented 5 years ago

The force-based layout sounds like a cool idea, but it would take me too long to implement that. I think it would be fine to have the numbers actually touching the beginning of each stroke.

The medians field of the gaphics.txt is actually what I used for the image. :) I'm definitely interested in getting this to work. My language of choice is JavaScript for this.

I'll see if I can get the "apply the transform to each stroke"-idea to work.

Another thing we could do would be to generate a font with this. Although I have no idea how much work that would take and we would certainly lose colors.

T-vK commented 5 years ago

I found some more time to work on this. What do you think is better? (I found the one with the white white to be way more readable at smaller scale, but the one with the colored numbers makes it way more obvious which line they belong to.)

Another problem that I found is that text rendering in SVGs is very inconsistent across different programs. Browsers usually render it really well, but in Gimp for instance the black border around the numbers is rendered way too big and I don't know it just looks really bad.

I now have an algorithm that can generate these very efficiently: (I made it so that numbers repel each other when they are too close.)

I'll update my PR when I find some more time to clean it up.

zopsicle commented 3 years ago

The PR was merged, can this issue be closed?

T-vK commented 3 years ago

I guess so.