110 |
tris.insert(tris.begin(), t); |
tris.insert(tris.begin(), t); |
111 |
} |
} |
112 |
|
|
113 |
template <class F> void dice(F criterion) { |
template <class F> bool diceRound(F criterion) { |
|
DBG(dbg) << "Triangler: dice\n"; |
|
114 |
typedef std::pair<int, int> Edge; |
typedef std::pair<int, int> Edge; |
115 |
vector<Edge> tosplit; |
vector<Edge> tosplit; |
116 |
|
DBG(dbg) << "Triangler: dice round\n"; |
117 |
|
for(Titer t = tris.begin(); t != tris.end(); t++) { |
118 |
|
Tri &tri = *t; |
119 |
|
int spl = criterion(tri.v[0], tri.v[1], tri.v[2]); |
120 |
|
if(spl >= 0) { |
121 |
|
tosplit.push_back( Edge( tri.v[spl], tri.v[(spl+1) % 3])); |
122 |
|
} |
123 |
|
} |
124 |
|
if(!tosplit.size()) return false; |
125 |
|
for(unsigned i=0; i<tosplit.size(); i++) |
126 |
|
splitEdge(tosplit[i].first, tosplit[i].second); |
127 |
|
return true; |
128 |
|
} |
129 |
|
|
130 |
|
template <class F> void dice(F criterion) { |
131 |
|
DBG(dbg) << "Triangler: dice\n"; |
132 |
int round = 0; |
int round = 0; |
133 |
while(1) { |
while(1) { |
134 |
DBG(dbg) << "Triangler: dice round\n"; |
if(!diceRound(criterion)) return; |
|
for(Titer t = tris.begin(); t != tris.end(); t++) { |
|
|
Tri &tri = *t; |
|
|
int spl = criterion(tri.v[0], tri.v[1], tri.v[2]); |
|
|
if(spl >= 0) { |
|
|
tosplit.push_back( Edge( tri.v[spl], tri.v[(spl+1) % 3])); |
|
|
} |
|
|
} |
|
|
if(!tosplit.size()) return; |
|
|
for(unsigned i=0; i<tosplit.size(); i++) |
|
|
splitEdge(tosplit[i].first, tosplit[i].second); |
|
|
tosplit.clear(); |
|
135 |
round ++; |
round ++; |
136 |
if(round > 20) { |
if(round > 20) { |
137 |
DBG(dbg) << "OVER ROUND LIMIT! ABORTING!\n"; |
DBG(dbg) << "OVER ROUND LIMIT! ABORTING!\n"; |
139 |
} |
} |
140 |
} |
} |
141 |
} |
} |
142 |
|
template <class F> void iterateTriangles(F func) { |
143 |
|
for(Titer x = tris.begin(); x != tris.end(); x++) |
144 |
|
func( (*x).v[0], (*x).v[1], (*x).v[2]); |
145 |
|
} |
146 |
void draw() { |
void draw() { |
147 |
glBegin(GL_TRIANGLES); |
glBegin(GL_TRIANGLES); |
148 |
for(Titer x = tris.begin(); x != tris.end(); x++) { |
for(Titer x = tris.begin(); x != tris.end(); x++) { |
154 |
} |
} |
155 |
Triangles(Verts &v) : verts(v) { |
Triangles(Verts &v) : verts(v) { |
156 |
} |
} |
|
}; |
|
|
|
|
|
/** Dice a line to pieces satisfying Criterion. |
|
|
* This is a generic method to dice a given edge recursively. |
|
|
* The edge is stored in an slist object containing the abstract |
|
|
* vertices. New vertices are created by a functor. |
|
|
* |
|
|
* @param verts An object supporting (*iter, *iter, float fract) |
|
|
* @param edge The slist object. It is required that insertion won't affect iterators, |
|
|
* and that insert_after(Iter, &T) is supported. |
|
|
* @param begin Iterator pointing to the first of the two vertices to dice. |
|
|
* @param last Iterator pointing to the second of the two vertices to dice. |
|
|
* Assumed to be right after begin by the algorithm. |
|
|
* @param split A binary predicate: whether an edge between two vertices still needs splitting. |
|
|
* May also return a float as an approximation of how many split points there |
|
|
* should be, but is not currently used that way. |
|
|
* @param maxdepth The maximum number of splits to do recursively |
|
|
* @param depth INTERNAL. |
|
|
* @return Number of new vertices added to the edge. |
|
|
*/ |
|
|
template<class Verts, class Edge, class Criterion> |
|
|
int dice_line2(Verts &verts, Edge &edge, |
|
|
typename Edge::iterator begin, typename Edge::iterator last, |
|
|
Criterion split, int maxdepth, int depth=0) { |
|
|
DBG(dbg) << "dice_line "<<depth<<"\n"; |
|
|
float nspl = split(*begin, *last); |
|
|
DBG(dbg) << "dice_line split "<<nspl<<"\n"; |
|
|
if(depth >= maxdepth || nspl <= 0) { |
|
|
DBG(dbg) << "dice_line STOP "<<nspl<<"\n"; |
|
|
return 0; |
|
|
} |
|
|
nspl = (int) nspl; |
|
|
if(nspl > 1) nspl = 1; |
|
|
int ret = 0; |
|
|
typename Edge::iterator prev = begin; |
|
|
for(int i=0; i<nspl; i++) { |
|
|
DBG(dbg) << "dice_line vert "<<i<<"\n"; |
|
|
ret ++; |
|
|
int v = verts(*begin, *last, (i+1.0) / (nspl + 1.0)); |
|
|
typename Edge::iterator n = edge.insert_after(prev, v); |
|
|
ret += dice_line(verts, edge, prev, n, split, maxdepth, depth+1); |
|
|
prev = n; |
|
|
} |
|
|
|
|
|
ret += dice_line(verts, edge, prev, last, split, maxdepth, depth+1); |
|
|
DBG(dbg) << "RET dice_line "<<depth<<" "<<ret << "\n"; |
|
|
return ret; |
|
|
} |
|
|
|
|
|
template<class Verts, class Edge, class Criterion> |
|
|
int dice_line3_h(Verts &verts, Edge &edge, |
|
|
typename Edge::iterator begin, |
|
|
typename Edge::iterator half, |
|
|
typename Edge::iterator last, |
|
|
Criterion split, int maxdepth, int depth) { |
|
|
if(depth >= maxdepth) { |
|
|
DBG(dbg) << "dice_line3_h STOPDEPTH\n"; |
|
|
return 0; |
|
|
} |
|
|
int splitflag = split(*begin, *half, *last); |
|
|
int ret = 0; |
|
|
if(splitflag == 1) { |
|
|
int spv = verts(*begin, *half, .5); |
|
|
ret ++; |
|
|
typename Edge::iterator sp = edge.insert_after(begin, spv); |
|
|
ret += dice_line3_h(verts, edge, begin, sp, half, split, maxdepth, depth+1); |
|
|
} |
|
|
int esplitflag = split(*last, *half, *begin); |
|
|
if(esplitflag == 1) { |
|
|
int espv = verts(*half, *last, .5); |
|
|
ret ++; |
|
|
typename Edge::iterator esp = edge.insert_after(half, espv); |
|
|
ret += dice_line3_h(verts, edge, half, esp, last, split, maxdepth, depth+1); |
|
|
} |
|
|
return ret; |
|
|
|
|
|
} |
|
|
|
|
|
template<class Verts, class Edge, class Criterion> |
|
|
int dice_line3(Verts &verts, Edge &edge, |
|
|
typename Edge::iterator begin, typename Edge::iterator last, |
|
|
Criterion split, int maxdepth, int depth=0) { |
|
|
DBG(dbg) << "dice_line "<<depth<<"\n"; |
|
|
if(depth >= maxdepth) { |
|
|
DBG(dbg) << "dice_line STOPDEPTH\n"; |
|
|
return 0; |
|
|
} |
|
|
int halfv = verts(*begin, *last, .5); |
|
|
|
|
|
|
|
|
int splitflag = split(*begin, halfv, *last); |
|
|
if(splitflag == -1) { |
|
|
DBG(dbg) << "dice_line STOP FLAG\n"; |
|
|
return 0; |
|
|
} |
|
|
typename Edge::iterator half = edge.insert_after(begin, halfv); |
|
|
int ret = 1; |
|
|
ret += dice_line3_h(verts, edge, begin, half, last, split, maxdepth, depth + 1); |
|
|
|
|
|
DBG(dbg) << "RET dice_line "<<depth<<" "<<ret << "\n"; |
|
|
return ret; |
|
|
} |
|
|
|
|
|
|
|
|
/** A triangle whose edges have been diced. |
|
|
*/ |
|
|
template<class Edge> struct DicedTriangle { |
|
|
typedef typename Edge::iterator Iter; |
|
|
Iter ebegins[3]; |
|
|
Iter elasts[3]; |
|
|
/** Numbers of vertices between begin and last. |
|
|
*/ |
|
|
int n[3]; |
|
|
|
|
|
template<class Verts, class Criterion, class Triangler> |
|
|
void dice(Verts &verts, Triangler &t, Criterion &split, int maxdepth, int depth = 0) { |
|
|
DBG(dbg) << "Dice start "<<depth<<" "<<n[0]<<" "<<n[1]<<" "<<n[2]<<"\n" |
|
|
<< "with triangle " |
|
|
<< *ebegins[0] << " " << *elasts[0] << " " |
|
|
<< *ebegins[1] << " " << *elasts[1] << " " |
|
|
<< *ebegins[2] << " "<< *elasts[2] << "\n"; |
|
|
int maxind ; |
|
|
// Can't use max_element easily, as we need the *LAST* |
|
|
// greatest element, otherwise recurses really badly. |
|
|
if(n[2] >= n[0] && n[2] >= n[1]) { |
|
|
maxind = 2; |
|
|
} else if(n[1] >= n[2] && n[1] >= n[0]) { |
|
|
maxind = 1; |
|
|
} else { |
|
|
maxind = 0; |
|
|
} |
|
|
DBG(dbg) << "Maxind "<<maxind<<"\n"; |
|
|
|
|
|
if(n[maxind] == 0) { |
|
|
DBG(dbg) << "Do triangle " |
|
|
<< *ebegins[0] << " " << *ebegins[1] << " " << *ebegins[2] << "\n"; |
|
|
t(*ebegins[0], *ebegins[1], *ebegins[2]); |
|
|
return; |
|
|
} |
|
|
|
|
|
int otherEdge = (maxind + 1) % 3; |
|
|
int thirdEdge = (maxind + 2) % 3; |
|
|
// Hope this is the right direction ;) |
|
|
Iter mid = ebegins[maxind]; |
|
|
int nin = -1; |
|
|
for(int i=0; i<(n[maxind]+1)/2; i++) { |
|
|
mid++; |
|
|
nin ++; |
|
|
} |
|
|
DBG(dbg) << "Middle: "<<*mid<<"\n"; |
|
|
Edge newEdge; |
|
|
|
|
|
DBG(dbg) << "Creating edges "<<maxind<<" "<<otherEdge<<" "<< |
|
|
thirdEdge<<"\n"; |
|
|
newEdge.push_front(*elasts[otherEdge]); |
|
|
newEdge.push_front(*mid); |
|
|
|
|
|
DicedTriangle start; |
|
|
start.ebegins[0] = newEdge.begin(); |
|
|
start.elasts[0] = newEdge.begin(); start.elasts[0] ++; |
|
|
start.n[0] = dice_line3(verts, newEdge, start.ebegins[0], start.elasts[0], split, maxdepth, depth); |
|
|
|
|
|
start.ebegins[1] = ebegins[thirdEdge]; |
|
|
start.elasts[1] = elasts[thirdEdge]; |
|
|
start.n[1] = n[thirdEdge]; |
|
|
|
|
|
start.ebegins[2] = ebegins[maxind]; |
|
|
start.elasts[2] = mid; |
|
|
start.n[2] = nin; |
|
|
|
|
|
DicedTriangle end; |
|
|
|
|
|
DBG(dbg) << "Second edge!\n"; |
|
|
// newEdge runs in opposite direction now. |
|
|
Edge newEdge2; |
|
|
Iter i = newEdge.begin(); |
|
|
newEdge2.push_front(*i); |
|
|
end.elasts[0] = newEdge2.begin(); |
|
|
for(; i!=newEdge2.end(); i++) |
|
|
newEdge2.push_front(*i); |
|
|
|
|
|
DBG(dbg) << "Second edge done!\n"; |
|
|
|
|
|
end.ebegins[0] = newEdge2.begin(); |
|
|
// elasts set earlier |
|
|
end.n[0] = start.n[0]; |
|
|
|
|
|
end.ebegins[1] = mid; |
|
|
end.elasts[1] = elasts[maxind]; |
|
|
end.n[1] = n[maxind] - nin - 1; |
|
|
|
|
|
end.ebegins[2] = ebegins[otherEdge]; |
|
|
end.elasts[2] = elasts[otherEdge]; |
|
|
end.n[2] = n[otherEdge]; |
|
|
|
|
|
DBG(dbg) << "Recursing!\n"; |
|
|
start.dice(verts, t, split, maxdepth, depth + 1); |
|
|
end.dice(verts, t, split, maxdepth, depth + 1); |
|
|
} |
|
|
}; |
|
|
|
|
|
template<class Edge> struct InitialDicedTriangle : public DicedTriangle<Edge> { |
|
|
Edge e[3]; |
|
157 |
|
|
|
template<class Vert, class Verts, class Criterion> |
|
|
void set_and_initial_dice(Verts &verts, Vert v0, Vert v1, Vert v2, |
|
|
Criterion split, int maxdepth) { |
|
|
e[0].push_front(v1); |
|
|
e[0].push_front(v0); |
|
|
e[1].push_front(v2); |
|
|
e[1].push_front(v1); |
|
|
e[2].push_front(v0); |
|
|
e[2].push_front(v2); |
|
|
|
|
|
for(int i=0; i<3; i++) { |
|
|
ebegins[i] = e[i].begin(); |
|
|
elasts[i] = ebegins[i]; elasts[i] ++; |
|
|
n[i] = dice_line3(verts, e[i], ebegins[i], elasts[i], split, maxdepth); |
|
|
} |
|
|
} |
|
158 |
}; |
}; |
159 |
|
|
160 |
|
|
|
|
|
|
|
|
161 |
} |
} |
162 |
} |
} |
163 |
|
|