|
![]() |
Пересечение двух Многоугольников |
![]() |
|
| Главная | Программные продукты | Freesource программные продукты | Статьи по Tcl/Tk | Статьи | Контакт | Карта сайта | |||
|
![]() |
Пересечение двух МногоугольниковПри, разработке программы MapTour, понадобилось найти фигуру (многоугольник), который получается в результате пересечения двух многоугольников. Вот что получилось:
Пересечение двух Многоугольников
![]() Первый Многоугольник Второй Многоугольник Результат пересечения
# Загружаем геометрическую библиотеку
package require math::geometry
proc PolygonIntersectPolygon { polygon1 polygon2 } {
set res ""
set isp1inside 0
set isp2inside 0
set isintersect 0
# определяем какие точки первого многоугольника находятся внутри второго
set lp1 ""
foreach { x y } $polygon1 {
if { [::math::geometry::pointInsidePolygon [list $x $y] $polygon2] } {
lappend lp1 [list $x $y 1]
set isp1inside 1
} else {
lappend lp1 [list $x $y 0]
}
}
# определяем какие точки второго многоугольника находятся внутри первого
set lp2 ""
foreach { x y } $polygon2 {
if { [::math::geometry::pointInsidePolygon [list $x $y] $polygon1] } {
lappend lp2 [list $x $y 1]
set isp2inside 1
} else {
lappend lp2 [list $x $y 0]
}
}
if { $isp1inside && $isp2inside } { set isintersect 1 }
# ищем точки пересечения сегментов и дополняем ими первый многоугольник
set newlp1 ""
foreach e1lp1 $lp1 e2lp1 [lrange $lp1 1 end] {
lassign $e2lp1 1x2 1y2
if { $1x2 eq "" } break
lassign $e1lp1 1x1 1y1
lappend newlp1 $e1lp1
foreach e1lp2 $lp2 e2lp2 [lrange $lp2 1 end] {
lassign $e2lp2 2x2 2y2
if { $2x2 eq "" } break
lassign $e1lp2 2x1 2y1
lassign [::math::geometry::findLineSegmentIntersection [list $1x1 $1y1 $1x2 $1y2] [list $2x1 $2y1 $2x2 $2y2]] x y
if { $x ne "" && $y ne "" } {
lappend newlp1 [list $x $y 2]
}
}
}
# ищем точки пересечения сегментов и дополняем ими второй многоугольник
set newlp2 ""
foreach e1lp1 $lp2 e2lp1 [lrange $lp2 1 end] {
lassign $e2lp1 1x2 1y2
if { $1x2 eq "" } break
lassign $e1lp1 1x1 1y1
lappend newlp2 $e1lp1
foreach e1lp2 $lp1 e2lp2 [lrange $lp1 1 end] {
lassign $e2lp2 2x2 2y2
if { $2x2 eq "" } break
lassign $e1lp2 2x1 2y1
lassign [::math::geometry::findLineSegmentIntersection [list $1x1 $1y1 $1x2 $1y2] [list $2x1 $2y1 $2x2 $2y2]] x y
if { $x ne "" && $y ne "" } {
lappend newlp2 [list $x $y 2]
}
}
}
set lp1 $newlp1
set lp2 $newlp2
# проходим по второму списку и добавляем внутренние точки второго списка в первый список
set segment ""
foreach el $lp2 {
lassign $el x y s
if { $s == 2 } {
if { [llength $segment] > 0 } {
set idx [lsearch $lp1 $el]
if { $idx > -1 } {
set lp1 [eval linsert {$lp1} $idx $segment]
set segment ""
}
}
}
if { $s == 1 } {
lappend segment $el
}
}
# и обратный проход, но до первой точки пересечения
if { $isintersect && [llength $segment] > 0 } {
foreach el [lreverse $lp2] {
lassign $el x y s
if { $s == 2 } {
set idx [lindex [lsearch -all $lp1 $el] end]
if { $idx > -1 } {
incr idx
set lp1 [eval linsert {$lp1} $idx $segment]
}
break
}
}
}
# формирование результирующего многоугольника
if { $isintersect } {
# существует пересечение
foreach el $lp1 {
lassign $el x y s
if { $s == 0 } continue
lappend res $x $y
}
} elseif { $isp1inside } {
# первый многоугольник полностью во втором
set res $polygon1
} elseif { $isp2inside } {
# второй многоугольник полностью в первом
set res $polygon2
}
return $res
}
|
||||||
| Copyright © Эдуард Зозуля | ||||||||
|
|
||||||||