Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Question to Tcl's math::geometrie package

140 views
Skip to first unread message

Helmut Giese

unread,
Sep 10, 2019, 11:03:30 AM9/10/19
to
Hello out there,
the following small script shows a surprising behaviour.
---
package require Tk
package require math::geometry
namespace import math::geometry::*
foreach ch [winfo children .] {destroy $ch}

set c [canvas .c -width 300 -height 100]
pack $c

set rect [$c create rectangle 100 50 200 100]
# the coords of $rect as a line
set rectAsLine {100 50 200 50 200 100 100 100 100 50}
set line1 [$c create line $rectAsLine -fill red -dash {4 4}]
set line2 [$c create line 50 75 150 75]

puts [findLineIntersection $rectAsLine [$c coords $line2]]
# -> none
puts [findLineIntersection {100 100 100 50} [$c coords $line2]]
# -> 100.0 75.0
puts [findLineIntersection [$c coords line1] [$c coords $line2]]
# -> can't use empty string as operand of "-"
---
What am I doing wrong?

Thank you
Helmut

Rich

unread,
Sep 10, 2019, 11:39:28 AM9/10/19
to
Helmut Giese <hgi...@ratiosoft.com> wrote:

This is what sticks out to me as the cause of the error message:

> set line1 [$c create line $rectAsLine -fill red -dash {4 4}]
^^^^^^^^^
> puts [findLineIntersection [$c coords line1] [$c coords $line2]]
^

You omitted a dollarsign when you tried to ask for the coordinates of
line 1. You ended up asking the canvas for the coordinates of an item
named "line1" instead.

greg

unread,
Sep 10, 2019, 12:50:35 PM9/10/19
to
#an additional proc
proc findLinePolylineIntersection { line polyline } {
set intersection "none"
for { set i 0 } { $i <= [expr [llength $polyline] -4] } { incr i +2 } {
set x1 [lindex $polyline $i]
set y1 [lindex $polyline [expr {$i +1 }]]
set x2 [lindex $polyline [expr {$i +2 }]]
set y2 [lindex $polyline [expr {$i +3 }]]
if {[::math::geometry::polylinesIntersect "$x1 $y1 $x2 $y2" $line] } {
# (infinite) lines
set intersection "[findLineIntersection "$x1 $y1 $x2 $y2" $line]"
}
}
return $intersection
}

puts "[findLinePolylineIntersection [$c coords $line2] [$c coords $line1]]"


best regards
greg

Helmut Giese

unread,
Sep 10, 2019, 3:53:09 PM9/10/19
to
On Tue, 10 Sep 2019 15:39:25 -0000 (UTC), Rich <ri...@example.invalid>
wrote:
Arrgh, what a blunder - and a public one to boot.

But my actual problem was, why the line
puts [findLineIntersection $rectAsLine [$c coords $line2]]
returned 'none'.
Well, meanwhile I found out that in math::geometry 'line' means a line
with just 2 points - everything else is a 'polyline'.

Thanks for exposing my ignorance :)
Helmut

jda...@gmail.com

unread,
Sep 10, 2019, 4:00:04 PM9/10/19
to
This one finds the first intersection found of the line segment with the polyline.

proc findLineSegmentPolylineIntersection {line poly} {
if {4 != [llength $line]} {
error "$line is not a line segment"
}
for {set i 0; set j 3} {$i < [llength $poly] - 4} {incr i 2; incr j 2} {
set seg [lrange $poly $i $j]
if {[::math::geometry::lineSegmentsIntersect $seg $line]} {
# return first intersection found
return [::math::geometry::findLineSegmentIntersection $line $seg]
}
}
# no intersections found
return ""
}

This may return "coincident" if the line overlays a polyline segment. I'm not sure how you want to handle that.

If you want intersection of an infinite line with the polyline, it gets complicated. You coule use findLineIntersection, however the case where the line intersects the infinitly extended polyline segment outside of the actual polyline segment needs to be eliminated.

The test for a valid line got added when I got the arguments reversed during testing.

Helmut Giese

unread,
Sep 10, 2019, 4:03:20 PM9/10/19
to
On Tue, 10 Sep 2019 09:50:31 -0700 (PDT), greg
<gregor...@googlemail.com> wrote:

>
>#an additional proc
>proc findLinePolylineIntersection { line polyline } {
> set intersection "none"
> for { set i 0 } { $i <= [expr [llength $polyline] -4] } { incr i +2 } {
> set x1 [lindex $polyline $i]
> set y1 [lindex $polyline [expr {$i +1 }]]
> set x2 [lindex $polyline [expr {$i +2 }]]
> set y2 [lindex $polyline [expr {$i +3 }]]
> if {[::math::geometry::polylinesIntersect "$x1 $y1 $x2 $y2" $line] } {
> # (infinite) lines
> set intersection "[findLineIntersection "$x1 $y1 $x2 $y2" $line]"
> }
> }
> return $intersection
>}
>
>puts "[findLinePolylineIntersection [$c coords $line2] [$c coords $line1]]"
>
>
>best regards
>greg
Hi Greg,
an interesting proc. In the meantime (after realizing that in
math::geometry a 'line' must not have more than 2 points) I realized
something similar by explicitely taking each side of the rectangle.
Thank you
Helmut

Arjen Markus

unread,
Sep 11, 2019, 2:38:25 AM9/11/19
to
On Tuesday, September 10, 2019 at 10:03:20 PM UTC+2, Helmut Giese wrote:
> On Tue, 10 Sep 2019 09:50:31 -0700 (PDT), greg
As maintainer of the math::geometry package I have made a copy of these two procedures :). To be included in that package later.

Regards,

Arjen

Helmut Giese

unread,
Sep 11, 2019, 8:01:35 AM9/11/19
to
>
>As maintainer of the math::geometry package I have made a copy of these two procedures :). To be included in that package later.
>
>Regards,
>
>Arjen
Hi Arjen,
since you are the maintainer: The function
'calculateDistanceToPolyline' is omitted from the export statement. I
filed a bug report yesterday
Best regards
Helmut

greg

unread,
Sep 11, 2019, 8:22:14 AM9/11/19
to

# all cut points will be spent
proc findLinePolylineIntersection { line polyline } {
set intersection ""
for { set i 0 } { $i <= [llength $polyline] -4 } { incr i +2 } {
set seq [lrange $polyline $i [expr {$i+3}]]
# (infinite) lines
if {[::math::geometry::polylinesIntersect $seq $line] } {
lappend intersection [::math::geometry::findLineIntersection $seq $line]
}
}
return $intersection
}

heinrichmartin

unread,
Sep 11, 2019, 9:05:41 AM9/11/19
to
On Wednesday, September 11, 2019 at 2:22:14 PM UTC+2, greg wrote:
> for { set i 0 } { $i <= [llength $polyline] -4 } { incr i +2 } {

This makes me think of all these ...
::math::geometry::forPoints {x y} $polyline {# body}
::math::geometry::forPoints p $polyline {# body}
::math::geometry::forSegments {x1 y1 x2 y2} $polyline {# body}
::math::geometry::forSegments {p1 p2} $polyline {# body}
::math::geometry::forSegments s $polyline {# body}
That's why I like Tcl so much :-)

> set seq [lrange $polyline $i [expr {$i+3}]]

I am quite sure that [lrange] uses the same index calculation like [lindex]. It therefore accepts "$i+3" without [expr]. Not so sure about the performance impact (shimmering instead of bytecode optimization).

Arjen Markus

unread,
Sep 11, 2019, 10:01:02 AM9/11/19
to
Ah thanks!

Regards,

Arjen

greg

unread,
Sep 11, 2019, 10:03:18 AM9/11/19
to
I had an error message with

set seq [lrange $polyline $i ($i+3)

I did not realize the difference (the brackets).

set seq [lrange $polyline $i $i+3

thank you

proc findLinePolylineIntersection { line polyline } {
set intersection ""
for { set i 0 } { $i <= [llength $polyline] -4 } { incr i +2 } {
set seq [lrange $polyline $i $i+3 ]
# (infinite) lines
if {[::math::geometry::polylinesIntersect $seq $line] } {
lappend intersection [::math::geometry::findLineIntersection $seq $line]
}
}
return $intersection
}


# (Idea from source code math :: geometry) with foreach
proc findLinePolylineIntersection2 { line polyline } {
set intersection ""
foreach {x2 y2} [lassign $polyline x1 y1] {
# (infinite) lines
if {[::math::geometry::polylinesIntersect "$x1 $y1 $x2 $y2" $line] } {
lappend intersection [::math::geometry::findLineIntersection "$x1 $y1 $x2 $y2" $line]
}
set x1 $x2; set y1 $y2
}
return $intersection
}

heinrichmartin

unread,
Sep 11, 2019, 11:03:12 AM9/11/19
to
On Wednesday, September 11, 2019 at 4:03:18 PM UTC+2, greg wrote:
> set seq [lrange $polyline $i ($i+3)

Parentheses were discussed as an extension to the Tcl syntax on c.l.t.; and indices are a great use-case, e.g. $n-$k+1 requires [expr].

> foreach {x2 y2} [lassign $polyline x1 y1] {
> ...
> set x1 $x2; set y1 $y2

This is quite elegant. The proc could support several numbers of variables and assign the right things (values, points, or segments).

> if {[::math::geometry::polylinesIntersect "$x1 $y1 $x2 $y2" $line] } {

This is shimmering. I assume [polylinesIntersect] parses a list... should use [list $x1 $y1 $x2 $y2].

two...@gmail.com

unread,
Sep 11, 2019, 12:53:12 PM9/11/19
to
On Wednesday, September 11, 2019 at 8:03:12 AM UTC-7, heinrichmartin wrote:

> Parentheses were discussed as an extension to the Tcl syntax on c.l.t.; and indices are a great use-case, e.g. $n-$k+1 requires [expr].

What is c.l.t? Is there some progress on that?

Rich

unread,
Sep 11, 2019, 1:16:42 PM9/11/19
to
two...@gmail.com wrote:
> On Wednesday, September 11, 2019 at 8:03:12 AM UTC-7, heinrichmartin wrote:
>
>> Parentheses were discussed as an extension to the Tcl syntax on
>> c.l.t.; and indices are a great use-case, e.g. $n-$k+1 requires
>> [expr].
>
> What is c.l.t?

Short name for comp.lang.tcl, the Usenet newsgroup you are currently
reading.

Christian Gollwitzer

unread,
Sep 11, 2019, 1:46:01 PM9/11/19
to
Am 11.09.19 um 18:53 schrieb two...@gmail.com:
> On Wednesday, September 11, 2019 at 8:03:12 AM UTC-7, heinrichmartin wrote:
>
>> Parentheses were discussed as an extension to the Tcl syntax on c.l.t.; and indices are a great use-case, e.g. $n-$k+1 requires [expr].
>
> What is c.l.t? Is there some progress on that?
>

Someone has reported a successful patch to the parser which makes () an
alias to expr. IMHO a very sensible suggestion, but currently there are
no plans (i.e. TIP) to bring this into mainstream Tcl. Possibly held
back due to conservative opinions about backwards compatibility.

Christian

two...@gmail.com

unread,
Sep 11, 2019, 2:10:40 PM9/11/19
to
On Wednesday, September 11, 2019 at 10:46:01 AM UTC-7, Christian Gollwitzer wrote:
>
> Someone has reported a successful patch to the parser which makes () an
> alias to expr. IMHO a very sensible suggestion, but currently there are
> no plans (i.e. TIP) to bring this into mainstream Tcl. Possibly held
> back due to conservative opinions about backwards compatibility.
>
> Christian

The one backwards compatibility I know of is that some package uses a null string for a variable name and so a word beginning with ( would be confused with an array whose name is the null string. IMHO a pretty nutty idea, but nevertheless currently legal.

greg

unread,
Sep 11, 2019, 3:24:55 PM9/11/19
to
# (Idea from source code math :: geometry) with foreach
proc findLinePolylineIntersection { line polyline } {
set intersection ""
foreach {x2 y2} [lassign $polyline x1 y1] {
# (infinite) lines
set seq [list $x1 $y1 $x2 $y2 ]
if {[::math::geometry::polylinesIntersect $seq $line] } {
lappend intersection [::math::geometry::findLineIntersection $seq $line]
}
set x1 $x2; set y1 $y2
}
return $intersection
}

greg

unread,
Sep 11, 2019, 3:54:42 PM9/11/19
to
Am Mittwoch, 11. September 2019 15:05:41 UTC+2 schrieb heinrichmartin:
That's right, the expr is not necessary.
Not needed for indices. Have my knowledge
refreshed.
https://www.tcl-lang.org/man/tcl/TclCmd/string.htm#M54

best regards
greg

Arjen Markus

unread,
Sep 12, 2019, 2:48:58 AM9/12/19
to
On Wednesday, September 11, 2019 at 7:46:01 PM UTC+2, Christian Gollwitzer wrote:
> Am 11.09.19 um 18:53 schrieb twogm6:
Any idea who? It might be a nice opportunity ...

Regards,

Arjen

heinrichmartin

unread,
Sep 12, 2019, 5:17:04 AM9/12/19
to
On Thursday, September 12, 2019 at 8:48:58 AM UTC+2, Arjen Markus wrote:
> > Someone has reported a successful patch to the parser which makes () an
> > alias to expr. IMHO a very sensible suggestion, but currently there are
> > no plans (i.e. TIP) to bring this into mainstream Tcl. Possibly held
> > back due to conservative opinions about backwards compatibility.
> >
> > Christian
>
> Any idea who? It might be a nice opportunity ...
>
> Regards,
>
> Arjen

Hi, from the tread "some questions on Tcl_ParseCommand (tclParse.c)" in Nov 2018 I derive:
* it was a cooperation by twogm6 and me
* it was a hack rather than a reference implementation
* pastebin is down and I don't have the patch (at least not on short notice)

The full story seems to have started in "Tcl syntax and expressions [was: tcl ?missing? expr operator?]" ...

Arjen Markus

unread,
Sep 12, 2019, 6:00:27 AM9/12/19
to
Ah, thanks.

Regards,

Arjen

two...@gmail.com

unread,
Sep 12, 2019, 10:50:31 AM9/12/19
to
On Thursday, September 12, 2019 at 2:17:04 AM UTC-7, heinrichmartin wrote:

> * it was a hack rather than a reference implementation

This discussion has jogged my memory and in light of full disclosure, I should mention the one potential incompatibility which is the problem of barewords beginning with the ( character. While unknown how often that occurs in everyday code, packages, or the tcl library, I had determined that this idiom is a popular one in the tcl test suite, which triggered many errors when I ran it against the change. That’s likely to it trying out all sorts of tortured corner cases to verify they didn’t cause parser errors. They would need to be quoted, braced, or escaped for the () expr alias to be truly implemented.

Still, I've written up a proposal and am attempting to find a sponsor to submit it as an official TIP. It should at least be voted up or down along with a full discussion.

two...@gmail.com

unread,
Sep 13, 2019, 1:08:02 PM9/13/19
to
On Thursday, September 12, 2019 at 7:50:31 AM UTC-7, two...@gmail.com wrote:

> Still, I've written up a proposal and am attempting to find a sponsor to submit it as an official TIP. It should at least be voted up or down along with a full discussion.

I sent off a proposal for the ()'s TIP, but it would appear that it has little likelihood of approval.

However, Peter Da Silva said that in the past he has suggested that $(expr) might be used which is pretty close. It has the advantage that it only would conflict with the null string variable name of an array, which was mentioned as an actual use in some package.

Rich

unread,
Sep 13, 2019, 1:51:05 PM9/13/19
to
two...@gmail.com wrote:
> I sent off a proposal for the ()'s TIP, but it would appear that it
> has little likelihood of approval.
>
> However, Peter Da Silva said that in the past he has suggested that
> $(expr) might be used which is pretty close. It has the advantage
> that it only would conflict with the null string variable name of an
> array, which was mentioned as an actual use in some package.

Use of the "empty string" as a variable or array name may be more
prevalent than you realize. Not just 'some package' (almost implying
singular). I've made use of the empty string array for at least
command line switch data parsed by the cmdline module in Tcllib several
times for several different personal bits of code. I very much suspect
that I'm not the only one.

And there used to be a wiki page for the empty string variable name,
but after the wiki makeover I'm no longer able to convince google to
locate the page.

two...@gmail.com

unread,
Sep 13, 2019, 2:11:01 PM9/13/19
to
On Friday, September 13, 2019 at 10:51:05 AM UTC-7, Rich wrote:

>
> Use of the "empty string" as a variable or array name may be more
> prevalent than you realize.
<snip>

I very much suspect
> that I'm not the only one.
>

Well, I think that likely puts a nail in the coffin of that proposal. I've pretty much resigned myself to using a text editor feature to enclose expressions with the required [expr] text. It's kinda hard on the eyes, so I add a fair bit of spacing around the expression. Syntax coloring helps too.

But I also use mouse invoked macros for all the other enclosing items, such as quotes, braces etc. I can write lots of tcl code without my fingers ever touching the keyboard :)

And I may have a sponsor for my other proposal that you suggested I do something about. It's funny too, since one objection was that ' might be better than _ and with a quick test would seem to be compatible as well, though I'm not yet ready to put that into the TIP as well.


Rich

unread,
Sep 13, 2019, 4:17:24 PM9/13/19
to
two...@gmail.com wrote:
> On Friday, September 13, 2019 at 10:51:05 AM UTC-7, Rich wrote:
>
>> Use of the "empty string" as a variable or array name may be more
>> prevalent than you realize.
> <snip>
>
>> I very much suspect that I'm not the only one.
>
> Well, I think that likely puts a nail in the coffin of that proposal.

Well, use of $(), yes. But some other sigil might be suitable that
will not conflict with a small, but unknown, amount of usage. I.e.,
(just off the top of my head) something like +() (where the plus itself
possibly implies "math inside").

> But I also use mouse invoked macros for all the other enclosing
> items, such as quotes, braces etc. I can write lots of tcl code
> without my fingers ever touching the keyboard :)

Hmm.... You have quite the opposite code writing style than I do.
Keeping fingers on the keyboard a maximum amount of time provides (for
me) the optimal code writing experience. When deep in a code writing
session, esp. for a CLI tool, I can go for hours without ever touching
the mouse (or trackpad for those writing on laptops).

> And I may have a sponsor for my other proposal that you suggested I
> do something about. It's funny too, since one objection was that '
> might be better than _ and with a quick test would seem to be
> compatible as well, though I'm not yet ready to put that into the TIP
> as well.

At this point I no longer recall which "other proposal" that I
"[suggested you] do something about".

two...@gmail.com

unread,
Sep 13, 2019, 4:43:29 PM9/13/19
to
On Friday, September 13, 2019 at 1:17:24 PM UTC-7, Rich wrote:

> Hmm.... You have quite the opposite code writing style than I do.
> I can go for hours without ever touching
> the mouse (or trackpad for those writing on laptops).
>

With my text editor, I use drag and drop since there's always something on the page that's what I need. I also have 20 or so templates, with several varieties of if/elseif/else, while, foreach, for, and pre-try days: if-catch templates that can nest and have proper indentation. I map my mouse wheel button to a double click so selection of most anything is just a single click. But everyone has their own ways and all work.



> At this point I no longer recall which "other proposal" that I
> "[suggested you] do something about".

I'm afraid to jinx it then, so if a new TIP appears on the tip index page, I'll let you know. And if it's approved, you should get an assist.


Rich

unread,
Sep 13, 2019, 6:36:13 PM9/13/19
to
two...@gmail.com wrote:
> On Friday, September 13, 2019 at 1:17:24 PM UTC-7, Rich wrote:
>
>> Hmm.... You have quite the opposite code writing style than I do.
>> I can go for hours without ever touching the mouse (or trackpad for
>> those writing on laptops).
>
> With my text editor, I use drag and drop since there's always
> something on the page that's what I need. I also have 20 or so
> templates, with several varieties of if/elseif/else, while, foreach,
> for, and pre-try days: if-catch templates that can nest and have
> proper indentation. I map my mouse wheel button to a double click so
> selection of most anything is just a single click. But everyone has
> their own ways and all work.

To each his own. I was neither suggesting your way was better, nor
worse. It works for you, that is all that matters.

>> At this point I no longer recall which "other proposal" that I
>> "[suggested you] do something about".
>
> I'm afraid to jinx it then, so if a new TIP appears on the tip index
> page, I'll let you know. And if it's approved, you should get an
> assist.

Fair enough then. I can wait.

Arjen Markus

unread,
Sep 16, 2019, 3:38:03 AM9/16/19
to
Done - I have not included the additional procedures that were posted in this thread yet (a bit more work than correcting the export and the documentation), but that will come in the next few days, I think.

Regards,

Arjen

Helmut Giese

unread,
Sep 16, 2019, 9:07:30 AM9/16/19
to
Thank you.

Arjen Markus

unread,
Sep 17, 2019, 5:27:08 AM9/17/19
to
Well, Andreas found out that something went wrong with my commit. So, you won't see it immediately. That needs to be repaired.

Regards,

Arjen
0 new messages