set one {
54 40 74 40 94 50 104 70
104 90 94 110 74 120 54 120
34 110 24 90 24 70 34 50 54 40
}
set two {
60 60 70 60 80 65 85 75
85 85 80 95 70 100 60 100
50 95 45 85 45 75 50 65 60 60
}
.c create polygon $one -fill grey -outline black -tags test1
.c create polygon $two -fill grey -outline black -tags test1
This sort of works but with problems:
.c delete test1
proc coordReverse {clist} {
set ret [list]
foreach {x y} $clist {
set ret [concat $x $y $ret]
}
return $ret
}
set two [coordReverse $two]
.c create polygon [concat $one $two] -fill grey -outline black -tags
test2
The first obvious problem is the unsightly line connecting the outer
polygon to the inner polygon. But that is minor and can be easily
corrected by drawing the outlines separately.
The real problem I'm having is that while this works for a simple
"donut" in my example code above, it breaks down for more complex
shapes. Another problem is that you notice above that I had to reverse
the coordinates of the inner polygon to make it work. But in my real
world data that may not necessarily be the case which requires me to
detect if the polygon is clockwise or anti-clockwise.
Have anyone done this sort of thing before and is there a lib I can
use? In case you're wondering why I need this, I'm trying to parse GIS
shapefiles and while the lines are easy I'm having problems with
polygons. Currently I cheat by drawing hollow polygons but my users
want filled polygons.
George
O/H sleb...@yahoo.com έγραψε:
Cheat #2:
... -fill [.c cget -bg]
And then bind any movements on $one to also move $two?
R'
Can you get away with this?
1. Draw the "positive" polygon just as a single, solid, filled
polygon
2. Draw the "negative" holes in your polygon as single, solid, filled
polygons,
but use the "background" color as the fill color?
That'll give the illusion of holes in your polygons, without all the
normal complications.
I had a similar problem with a geometry viewing application I wrote,
and
that's how I solved it. While I'd rather have polygons with *real*
holes, the
mentioned method actually worked quite well for me.
Jeff
Ooops - missed Ralf's earlier response mentioning the same idea...
Jeff
Unfortunately I can't use this since maps can be overlaid on top of
each other. For example I can have a layer of rivers and another layer
for roads including bridges over rivers.
I had a look at Tkzinc and was quite impressed. It has some cool
features. Unfortunately it is far too slow for me. A 25000 point map
which takes canvas 5 seconds to draw takes zinc 2 minutes and 10
seconds to draw. Currently my average map size is around 12000 points.
I'm actually quite impressed at Tcl's performance handling such large
amounts of data in (almost) real-time.
> I had a look at Tkzinc and was quite impressed. It has some cool
> features. Unfortunately it is far too slow for me. A 25000 point map
> which takes canvas 5 seconds to draw takes zinc 2 minutes and 10
> seconds to draw. Currently my average map size is around 12000 points.
> I'm actually quite impressed at Tcl's performance handling such large
> amounts of data in (almost) real-time.
>
could that be an openGL issue? i.e. native GL or soft GL (Mesa)
uwe
We don't support clipping regions for (non-window[*]) items. It'd be a
cool thing to add if someone wants to write the code. :-)
Donal.
[* OK, we don't support this either, but there's an extension. ]
I have an ATI Radeon 9200 on this dev system with OpenGL drivers
installed. I can't expect the deployed system to be this powerful.
Especially for mobile deployment on laptops. How do I detect if zinc is
picking up on the OpenGL driver?
> Is there a way to punch holes through canvas polygons?
OK, I just cooked up this little tidbit. Give it a whirl.
I should probably make a wiki page where people can improve it...
# Produce a canvas polygon with cut-out area(s)
#
# polycut <canvas win> <coordinates> <more args>
#
# where <more args> include those allowed by the [canvas create polygon]
# command, plus instances of -cutout <coordinates>.
#
# If a cutout overlaps another cutout or the perimiter of the polygon,
# the results are odd. It acts like each layer of cutout toggles the
# transparency. (There is, in fact, no transparency involved though.)
#
# The return value is an ID to use for bindings (see the demonstration).
#
# There are lots of absent features, in that most canvas operations are not
# supported. Feel free to add support for more things!
#
# -- Donald Arseneau
proc polycut { canv perimiter args } {
# Collect cutouts from $args (make a list of lists)
set cutouts [list]
while { [set ci [lsearch -exact $args "-cutout"]] >= 0 } {
lappend cutouts [lindex $args [expr {$ci+1}]]
set args [lreplace $args $ci [expr {$ci+1}]]
}
# If no cutouts, then an ordinary polygon:
if { [llength $cutouts] == 0 } {
eval [list $canv create polygon $perimiter] $args
return
}
set coords $perimiter
# Look for fill option
set fi [lsearch -exact $args "-fill"]
if { $fi < 0 } {
set fillc ""
} else {
# Pull out -fill switch from args. TODO: handle other fill and stiple options.
set fillc [lindex $args [expr {$fi+1}]]
set args [lreplace $args $fi [expr {$fi+1}]]
}
# merge cutouts with perimeter
set coords [polymergecut $coords $cutouts]
# Pull out -width switch from fill-args. TODO: handle other width options.
set fargs $args
if { [set wi [lsearch -exact $fargs "-width"]] >= 0 } {
set width [lindex $fargs [expr {$wi+1}]]
set fargs [lreplace $fargs $wi [expr {$wi+1}]]
}
# Pull out -outline switch from fill-args. TODO: handle other outline options.
if { [set oi [lsearch -exact $fargs "-outline"]] >= 0 } {
set outc [lindex $fargs [expr {$oi+1}]]
set fargs [lreplace $fargs $oi [expr {$oi+1}]]
}
# If filling,
if { [string length $fi] } {
# Draw filled multi-poly-gon
eval [list $canv create polygon $coords -outline {} -width 0 -fill $fillc] $fargs
}
# Draw each polygon outline
foreach cutout $cutouts {
eval [list $canv create polygon $cutout -fill {}] $args
}
# Draw the perimiter outline
eval [list $canv create polygon $perimiter -fill {}] $args
# Draw a completely blank version of the filled polygon, to use for bindings
eval [list $canv create polygon $coords -outline {} -width $width -fill {}] $fargs
}
# Procedure to merge polygon outline coorfinates with the cutout coordinates.
# The shortest connecting paths are used to avoid crossing open space. You can
# still get problems if outlines overlap.
proc polymergecut { coords cutouts } {
while { [llength $cutouts] } {
# Look for closest points in the two sets
set dm 9999999e9
set ip -2
foreach { px py } $coords {
incr ip 2
set ih -1
foreach cutout $cutouts {
incr ih
set ic -2
foreach { cx cy } $cutout {
incr ic 2
set dp [expr { double($px-$cx)*($px-$cx)+double($py-$cy)*($py-$cy) }]
if { $dp < $dm } {
set dm $dp
set np $ip
set nh $ih
set nc $ic
}
}
}
}
# Pull out the cutout coordinates that are closest to perimiter plus
# previous cutouts.
set cutout [lindex $cutouts $nh]
set cutouts [lreplace $cutouts $nh $nh]
# Rotate this cutout so the nearest coordinate of cutout is (duplicated) first and last,
# and insert it into the accumulated multi-polygon
set coords [concat \
[lrange $coords 0 [expr {$np+1}]] \
[lrange $cutout $nc end] \
[lrange $cutout 0 [expr {$nc+1}]] \
[lrange $coords $np end] ]
} ;# End of while loop
return $coords
}
# Demonstration:
canvas .c
pack .c
# Create a yellow triangle as background decoration:
.c create polygon {1 1 1 250 250 250} -outline black -fill yellow
# Create a red square with two square cutouts:
set id [polycut .c {10 10 10 200 200 200 200 10} -outline black -width 2 -fill red \
-cutout {20 20 20 50 50 50 50 20} \
-cutout {100 100 100 150 150 150 150 100} ]
.c bind $id <Enter> {.c configure -cursor cross}
.c bind $id <Leave> {.c configure -cursor {} }
# Create a matching polycut with the cutout overlapping the edge
polycut .c {215 15 300 15 300 150 215 150} -outline black -width 1 -fill green \
-cutout {250 100 350 100 350 200 250 200}
# Overlay an outline
.c create polygon {215 15 300 15 300 150 215 150} -outline blue -width 2 -fill {}
--
Donald Arseneau as...@triumf.ca
> I have an ATI Radeon 9200 on this dev system with OpenGL drivers
> installed. I can't expect the deployed system to be this powerful.
> Especially for mobile deployment on laptops. How do I detect if zinc is
> picking up on the OpenGL driver?
>
On Linux( may be SuSE specific?):
look into the librarys zink is linked to.
look for libGL.so or libMesaGL.so
ldd /usr/X11R6/bin/glxgears ( no TkZink here )
.......
libGL.so.1 => /usr/lib/libGL.so.1 (0x40038000)
libGLcore.so.1 => /usr/lib/libGLcore.so.1 (0x402f9000)
libnvidia-tls.so.1 => /usr/lib/tls/libnvidia-tls.so.1 (0x409ea000)
..............
then look into /usr/lib. if your system runs GL natively
you will seen something like this:
lrwxrwxrwx 1 root root 7 2004-08-05 10:01 /usr/lib/libMesaGL.a -> libGL.a
lrwxrwxrwx 1 root root 8 2004-08-05 10:01 /usr/lib/libMesaGL.so -> libGL.so
lrwxrwxrwx 1 root root 10 2004-07-27 17:39 /usr/lib/libMesaGL.so.3 -> libGL.so.1
lrwxrwxrwx 1 root root 8 2004-08-05 10:01 /usr/lib/libMesaGLU.a -> libGLU.a
lrwxrwxrwx 1 root root 9 2004-08-05 10:01 /usr/lib/libMesaGLU.so -> libGLU.so
...
if GL stuff is run by way of Mesa the links would be the other way round.
uwe
On Windows? Specifically Win2k and WinXP. I can see the gl*** dlls
installed and some games supporting OpenGL works fine. But I want to
know if zinc specifically is picking up on the drivers.
I tried some GL benchmarking apps and the performance on my machine was
horrible. Too much dependence on DirectX in the windows world perhaps?
> On Windows? Specifically Win2k and WinXP. I can see the gl*** dlls
Please take the ParaTime Transporter 3 probabilities further left. Thank You ;-))
uwe