• improve a spline

    From saito@saitology9@gmail.com to comp.lang.tcl on Thu Jun 12 12:51:58 2025
    From Newsgroup: comp.lang.tcl

    When you run the following code, a canvas comes up and you can
    click-hold your mouse and drag it around to create bezier curves.

    The line is jagged and it has a double curve. I wonder if it is possible
    to make it smooth and reduce it to a plain s shape. Any ideas?


    package req Tk


    canvas .c -width 500 -height 500
    pack .c -fill both -expand 1

    bind .c <Button-1> [list mark %x %y]
    bind .c <B1-Motion> [list draw %x %y]

    proc mark {x y} {
    set ::id 0
    set ::ax $x
    set ::ay $y
    }

    proc draw {x y} {
    .c delete $::id

    set xdiff [expr {($x - $::ax) / 2.0}]
    set tx2 [expr {$::ax + 2 * $xdiff}]
    set tx3 [expr {$x - 2 * $xdiff}]
    set ::id [.c create line $::ax $::ay $tx2 $::ay $tx3 $y $x $y \
    -fill #494949 -width 3 -smooth bezier -splinesteps 24]
    }


    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Emiliano@emiliano@example.invalid to comp.lang.tcl on Thu Jun 12 20:08:45 2025
    From Newsgroup: comp.lang.tcl

    On Thu, 12 Jun 2025 12:51:58 -0400
    saito <saitology9@gmail.com> wrote:

    When you run the following code, a canvas comes up and you can
    click-hold your mouse and drag it around to create bezier curves.

    The line is jagged and it has a double curve. I wonder if it is possible
    to make it smooth and reduce it to a plain s shape. Any ideas?

    If by "smooth" you mean antialias, then no, Tk canvas doesn't do antialias.
    As I undertand it, the tkpath package does, but I can't confirm since never used it.

    Regards
    --
    Emiliano
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From saito@saitology9@gmail.com to comp.lang.tcl on Thu Jun 12 20:49:44 2025
    From Newsgroup: comp.lang.tcl

    On 6/12/2025 7:08 PM, Emiliano wrote:

    If by "smooth" you mean antialias, then no, Tk canvas doesn't do antialias. As I undertand it, the tkpath package does, but I can't confirm since never used it.


    Thanks for taking a look. This is a piece of very old code from someone
    else and I need to decide whether to improve it or trash it.

    I guess there is no escaping the jagged lines. That is OK. How about
    just making it a simple curve? As it is currently, there are two points
    where it curves making it look like an S. Any ideas to reduce it to
    simple / relaxed sine curve?
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Arjen@user153@newsgrouper.org.invalid to comp.lang.tcl on Fri Jun 13 08:28:03 2025
    From Newsgroup: comp.lang.tcl


    saito <saitology9@gmail.com> posted:

    On 6/12/2025 7:08 PM, Emiliano wrote:

    If by "smooth" you mean antialias, then no, Tk canvas doesn't do antialias. As I undertand it, the tkpath package does, but I can't confirm since never used it.


    Thanks for taking a look. This is a piece of very old code from someone
    else and I need to decide whether to improve it or trash it.

    I guess there is no escaping the jagged lines. That is OK. How about
    just making it a simple curve? As it is currently, there are two points where it curves making it look like an S. Any ideas to reduce it to
    simple / relaxed sine curve?

    This is the character of the Bezier smoothing. If you want a curve with
    only a single "bent", you might consider to derive a midpoint from the
    two endpoints and draw a smoothed line (-smooth 1) through THREE points.

    A possible method:
    - Take the vector from point A to point B
    - Determine the normal n to that vector (note: choice of direction!)
    - Use a fraction of the distance between A and B to calculate the new point:

    new point = (A + B)/2 + fraction * distance(A,B) * normal vector

    You have a number of choices here :).
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From Emiliano@emil.g@example.invalid to comp.lang.tcl on Fri Jun 13 10:19:09 2025
    From Newsgroup: comp.lang.tcl

    On Thu, 12 Jun 2025 20:49:44 -0400
    saito <saitology9@gmail.com> wrote:

    On 6/12/2025 7:08 PM, Emiliano wrote:

    If by "smooth" you mean antialias, then no, Tk canvas doesn't do antialias. As I undertand it, the tkpath package does, but I can't confirm since never used it.


    Thanks for taking a look. This is a piece of very old code from someone
    else and I need to decide whether to improve it or trash it.

    I guess there is no escaping the jagged lines. That is OK. How about
    just making it a simple curve? As it is currently, there are two points where it curves making it look like an S. Any ideas to reduce it to
    simple / relaxed sine curve?

    See the "-smooth raw" option. With this option you can define the spline control points. In the following code, circles are knot points (coordinate pairs 0, 3, 6 ...) and the squares are control points (coordinate pairs 1, 2, 4, 5 ...). Try moving the points around.

    Sample code: ==================================================
    package require Tk

    proc lexpr {args} {
    lmap expr $args {uplevel 1 [list expr $expr]}
    }

    proc point-coords {x y} {
    lexpr {$x-5} {$y-5} {$x+5} {$y+5}
    }

    proc move-node {c item idx x y} {
    set x [$c canvasx $x]
    set y [$c canvasy $y]
    $c coords $item [point-coords $x $y]
    $c rchars line {*}[lexpr {$idx*2} {1+2*$idx}] [list $x $y]
    }

    canvas .c -xscrollcommand [list .sx set] -yscrollcommand [list .sy set] ttk::scrollbar .sy -orient vertical -command [list .c yview]
    ttk::scrollbar .sx -orient horizontal -command [list .c xview]
    grid .c .sy -sticky news
    grid .sx -sticky ew
    grid columnconfigure . 0 -weight 1
    grid rowconfigure . 0 -weight 1

    set coords {50 150 100 250 150 50 200 150}
    set idx 0
    .c create line $coords -smooth raw -tags line -splinesteps 20
    foreach {x y} $coords type {oval rectangle rectangle oval} {
    set item [.c create $type [point-coords $x $y] -fill red]
    .c bind $item <B1-Motion> [list move-node %W $item $idx %x %y]
    incr idx
    }
    bind .c <ButtonRelease-1> {%W configure -scrollregion [%W bbox all]}
    .c configure -scrollregion [.c bbox all] ==================================================

    Regards
    --
    Emiliano
    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From saito@saitology9@gmail.com to comp.lang.tcl on Fri Jun 13 13:44:59 2025
    From Newsgroup: comp.lang.tcl

    On 6/13/2025 4:28 AM, Arjen wrote:


    This is the character of the Bezier smoothing. If you want a curve with
    only a single "bent", you might consider to derive a midpoint from the
    two endpoints and draw a smoothed line (-smooth 1) through THREE points.

    A possible method:
    - Take the vector from point A to point B
    - Determine the normal n to that vector (note: choice of direction!)
    - Use a fraction of the distance between A and B to calculate the new point:

    new point = (A + B)/2 + fraction * distance(A,B) * normal vector

    You have a number of choices here :).

    Thanks. I will give it a try. And I appreciate your confidence in my
    geometry chops :-)


    --- Synchronet 3.21a-Linux NewsLink 1.2
  • From saito@saitology9@gmail.com to comp.lang.tcl on Fri Jun 13 13:46:20 2025
    From Newsgroup: comp.lang.tcl

    On 6/13/2025 9:19 AM, Emiliano wrote:


    See the "-smooth raw" option. With this option you can define the spline control points. In the following code, circles are knot points (coordinate pairs 0, 3, 6 ...) and the squares are control points (coordinate pairs 1, 2, 4, 5 ...). Try moving the points around.


    Thanks for the code! Very interesting. I have to look at it in detail to understand what is going on.
    --- Synchronet 3.21a-Linux NewsLink 1.2