This repository has been archived by the owner on Jun 1, 2020. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tp.go
159 lines (144 loc) · 3.39 KB
/
tp.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
package tp
import (
"container/list"
"fmt"
)
// main data structure for triangulation
//
// Triangulation data structure "Nodes, simple ribs и triangles"
// book "Algoritm building and analyse triangulation", A.B.Skvorcov.
// paragraph 1.2.5
//
type data struct {
nodes [3]int // indexes of triangle points
triangles [3]*data // indexes of near triangles
ribs [3]int // indexes of triangle ribs
}
func (d *data) changeClockwise() {
d.nodes[0], d.nodes[1] = d.nodes[1], d.nodes[0]
d.ribs[1], d.ribs[2] = d.ribs[2], d.ribs[1]
d.triangles[1], d.triangles[2] = d.triangles[2], d.triangles[1]
}
type Triangulation struct {
ps []Point
ds *list.List
}
func NewTp(ps ...Point) (tr *Triangulation, err error) {
if len(ps) < 3 {
err = fmt.Errorf("not enougt input points")
return
}
tr = &Triangulation{}
tr.ds = list.New()
// find border box
b := NewBB()
for i := range ps {
b.Add(ps[i])
}
//
// create pseudo-box.
// all points must be inside pseudo-box
//
// P1 P2
// o---1---o
// | /|
// | 0 / |
// | / |
// 0 2 3
// | / |
// | / 1 |
// |/ |
// o---4---o
// P0 P3
//
scale := 20.0
xSize := b.Xmax - b.Xmin
ySize := b.Ymax - b.Ymin
pps := []Point{ // pseudo-box points
Point{X: b.Xmin - scale*xSize, Y: b.Ymin - scale*ySize}, // P0
Point{X: b.Xmin - scale*xSize, Y: b.Ymax + scale*ySize}, // P1
Point{X: b.Xmax + scale*xSize, Y: b.Ymax + scale*ySize}, // P2
Point{X: b.Xmax + scale*xSize, Y: b.Ymin - scale*ySize}, // P3
}
defer func() {
for i := range pps {
tr.remove(pps[i])
}
}()
tr.ps = append(pps, ps...)
//
// create points, ribs, triangles pseudo-box
//
t0 := &data{
nodes: [3]int{0, 2, 1},
ribs: [3]int{0, 2, 1},
}
t1 := &data{
nodes: [3]int{2, 0, 3},
ribs: [3]int{3, 2, 4},
}
t0.triangles[2] = t1
t1.triangles[2] = t0
tr.ds.PushFront(t0)
tr.ds.PushFront(t1)
//
// add points in triangles
//
for i := 5; i < len(tr.ps); i++ {
if err := tr.add(i); err != nil {
return tr, err
}
}
return tr, nil
}
func (tr *Triangulation) remove(p Point) error {
return fmt.Errorf("add implementation for remove")
}
func (tr *Triangulation) add(next int) (err error) {
if debugFlag {
logger.Printf("add point #%d : %s", next, tr.ps[next])
}
state, tri := tr.findTriangle(next)
err = fmt.Errorf("Strange point #%d with state `%s` : %s", next, state, tr.ps[next].String())
switch state {
case pointInside:
err = tr.addInTriangle(tri, next)
case pointOnLine0, pointOnLine1, pointOnLine2:
err = tr.addOnLine(tri, next, state)
case pointOnCorner:
err = nil
}
return
}
func (tr *Triangulation) findTriangle(next int) (state pointTriangleState, tri *data) {
var found bool
for e := tr.ds.Front(); e != nil; e = e.Next() {
// moving triangle by triangles
tri = e.Value.(*data)
state = tr.statePointInTriangle(next, tri.nodes)
switch state {
case pointOutsideLine0, pointOutsideLine1, pointOutsideLine2:
found = false
default:
found = true
}
if found {
break
}
}
if !found {
state = pointOutside
}
return
}
func (tr *Triangulation) addOnLine(tri *data, next int, state pointTriangleState) (err error) {
return fmt.Errorf("add implementation for addOnLine")
}
func (tr *Triangulation) addInTriangle(tri *data, next int) (err error) {
return fmt.Errorf("add implementation for addInTriangle")
}
func (tr Triangulation) String() string {
var out string
out += "some"
return out
}