00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "qtessInputEntry.h"
00016 #include "qtessSurface.h"
00017 #include "qtessGlobals.h"
00018 #include "config_egg_qtess.h"
00019 #include "indent.h"
00020 #include "string_utils.h"
00021
00022 #include <ctype.h>
00023 #include <algorithm>
00024
00025
00026
00027
00028
00029
00030 QtessInputEntry::
00031 QtessInputEntry(const string &name) {
00032 _type = T_undefined;
00033 _num_patches = 0.0;
00034 _auto_place = QtessGlobals::_auto_place;
00035 _auto_distribute = QtessGlobals::_auto_distribute;
00036 _curvature_ratio = QtessGlobals::_curvature_ratio;
00037 if (!name.empty()) {
00038 add_node_name(name);
00039 }
00040 }
00041
00042
00043
00044
00045
00046
00047 void QtessInputEntry::
00048 operator = (const QtessInputEntry ©) {
00049 _node_names = copy._node_names;
00050 _type = copy._type;
00051 _num_tris = copy._num_tris;
00052 _num_u = copy._num_u;
00053 _num_v = copy._num_v;
00054 _per_isoparam = copy._per_isoparam;
00055 _iso_u = copy._iso_u;
00056 _iso_v = copy._iso_v;
00057 _surfaces = copy._surfaces;
00058 _num_patches = copy._num_patches;
00059 _auto_place = copy._auto_place;
00060 _auto_distribute = copy._auto_distribute;
00061 _curvature_ratio = copy._curvature_ratio;
00062 _importance = copy._importance;
00063 _constrain_u = copy._constrain_u;
00064 _constrain_v = copy._constrain_v;
00065 }
00066
00067
00068
00069
00070
00071
00072 class DoublesAlmostEqual {
00073 public:
00074 int operator ()(double a, double b) const {
00075 return fabs(a - b) < 0.00001;
00076 }
00077 };
00078
00079
00080
00081
00082
00083
00084
00085 class DoubleAlmostMatches {
00086 public:
00087 DoubleAlmostMatches(double v) : _v(v) {}
00088 int operator ()(double a) const {
00089 return fabs(a - _v) < 0.00001;
00090 }
00091 double _v;
00092 };
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102 void QtessInputEntry::
00103 set_uv(int u, int v, const string params[], int num_params) {
00104 _num_u = u;
00105 _num_v = v;
00106
00107
00108 int i;
00109 for (i = 0; i <= _num_u; i++) {
00110 _iso_u.push_back(i);
00111 }
00112 for (i = 0; i <= _num_v; i++) {
00113 _iso_v.push_back(i);
00114 }
00115
00116
00117 for (i = 0; i < num_params; i++) {
00118 const string ¶m = params[i];
00119
00120 if (param[0] == '!' && param.size() > 2) {
00121 double value;
00122 if (!string_to_double(param.substr(2), value)) {
00123 qtess_cat.warning()
00124 << "Ignoring invalid parameter: " << param << "\n";
00125 } else {
00126 switch (tolower(param[1])) {
00127 case 'u':
00128 _auto_place = false;
00129 _iso_u.erase(remove_if(_iso_u.begin(), _iso_u.end(),
00130 DoubleAlmostMatches(value)),
00131 _iso_u.end());
00132 break;
00133
00134 case 'v':
00135 _auto_place = false;
00136 _iso_v.erase(remove_if(_iso_v.begin(), _iso_v.end(),
00137 DoubleAlmostMatches(value)),
00138 _iso_v.end());
00139 break;
00140
00141 default:
00142 qtess_cat.warning()
00143 << "Ignoring invalid parameter: " << params[i] << "\n";
00144 }
00145 }
00146 } else {
00147 double value;
00148 if (!string_to_double(param.substr(1), value)) {
00149 qtess_cat.warning()
00150 << "Ignoring invalid parameter: " << param << "\n";
00151 } else {
00152 switch (tolower(param[0])) {
00153 case 'u':
00154 _auto_place = false;
00155 _iso_u.push_back(value);
00156 break;
00157
00158 case 'v':
00159 _auto_place = false;
00160 _iso_v.push_back(value);
00161 break;
00162
00163 default:
00164 qtess_cat.warning()
00165 << "Ignoring invalid parameter: " << params[i] << "\n";
00166 }
00167 }
00168 }
00169 }
00170
00171
00172 sort(_iso_u.begin(), _iso_u.end());
00173 sort(_iso_v.begin(), _iso_v.end());
00174 _iso_u.erase(unique(_iso_u.begin(), _iso_u.end(), DoublesAlmostEqual()), _iso_u.end());
00175 _iso_v.erase(unique(_iso_v.begin(), _iso_v.end(), DoublesAlmostEqual()), _iso_v.end());
00176
00177 _type = T_uv;
00178 }
00179
00180
00181
00182
00183
00184
00185
00186
00187 void QtessInputEntry::
00188 add_extra_u_isoparam(double u) {
00189 _iso_u.push_back(u);
00190 }
00191
00192
00193
00194
00195
00196
00197
00198 void QtessInputEntry::
00199 add_extra_v_isoparam(double v) {
00200 _iso_v.push_back(v);
00201 }
00202
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212 QtessInputEntry::Type QtessInputEntry::
00213 match(QtessSurface *surface) {
00214 const string &name = surface->get_name();
00215
00216 NodeNames::const_iterator nni;
00217 for (nni = _node_names.begin();
00218 nni != _node_names.end();
00219 ++nni) {
00220 const GlobPattern &pattern = (*nni);
00221 if (pattern.matches(name)) {
00222
00223 switch (_type) {
00224 case T_importance:
00225
00226
00227
00228
00229
00230 if (qtess_cat.is_debug()) {
00231 qtess_cat.debug()
00232 << "Assigning importance of " << _importance*100.0
00233 << "% to " << name << "\n";
00234 }
00235 surface->set_importance(_importance);
00236 return T_undefined;
00237
00238 case T_match_uu:
00239 case T_match_uv:
00240
00241
00242
00243
00244 if (nni == _node_names.begin() && _constrain_u==NULL) {
00245
00246 _constrain_u = surface;
00247 } else {
00248 if (_type == T_match_uu) {
00249 surface->set_match_u(&_constrain_u, true);
00250 } else {
00251 surface->set_match_v(&_constrain_u, false);
00252 }
00253 }
00254 return T_undefined;
00255
00256 case T_match_vv:
00257 case T_match_vu:
00258
00259 if (nni == _node_names.begin() && _constrain_v==NULL) {
00260
00261 _constrain_v = surface;
00262 } else {
00263 if (_type == T_match_vv) {
00264 surface->set_match_v(&_constrain_v, true);
00265 } else {
00266 surface->set_match_u(&_constrain_v, false);
00267 }
00268 }
00269 return T_undefined;
00270
00271 case T_min_u:
00272
00273 if (qtess_cat.is_debug()) {
00274 qtess_cat.debug()
00275 << "Assigning minimum of " << _num_u << " in U to "
00276 << name << "\n";
00277 }
00278 surface->set_min_u(_num_u);
00279 return T_undefined;
00280
00281 case T_min_v:
00282 if (qtess_cat.is_debug()) {
00283 qtess_cat.debug()
00284 << "Assigning minimum of " << _num_v << " in V to "
00285 << name << "\n";
00286 }
00287 surface->set_min_v(_num_v);
00288 return T_undefined;
00289
00290 default:
00291 _surfaces.push_back(surface);
00292 if (_auto_distribute) {
00293 _num_patches += surface->get_score(_curvature_ratio);
00294 } else {
00295 _num_patches += surface->count_patches();
00296 }
00297 return _type;
00298 }
00299 }
00300 }
00301
00302 return T_undefined;
00303 }
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313 int QtessInputEntry::
00314 count_tris(double tri_factor, int attempts) {
00315 int total_tris = 0;
00316 bool aim_for_tris = false;
00317
00318 if (_type == T_num_tris && _num_patches > 0.0) {
00319
00320
00321
00322 if (_auto_distribute) {
00323 set_per_score(sqrt(0.5 * (double)_num_tris / _num_patches / tri_factor));
00324 } else {
00325 set_per_isoparam(sqrt(0.5 * (double)_num_tris / _num_patches / tri_factor));
00326 }
00327 aim_for_tris = true;
00328 }
00329
00330 Surfaces::iterator si;
00331 for (si = _surfaces.begin(); si != _surfaces.end(); ++si) {
00332 QtessSurface *surface = (*si);
00333
00334 switch (_type) {
00335 case T_undefined:
00336 case T_omit:
00337 surface->omit();
00338 break;
00339
00340 case T_uv:
00341 if (!_iso_u.empty() && !_iso_v.empty() && !_auto_place) {
00342 surface->tesselate_specific(_iso_u, _iso_v);
00343 } else {
00344 surface->tesselate_uv(_num_u, _num_v, _auto_place, _curvature_ratio);
00345 }
00346 break;
00347
00348 case T_per_isoparam:
00349 surface->tesselate_per_isoparam(_per_isoparam, _auto_place, _curvature_ratio);
00350 break;
00351
00352 case T_per_score:
00353 surface->tesselate_per_score(_per_isoparam, _auto_place, _curvature_ratio);
00354 break;
00355
00356 default:
00357 break;
00358 }
00359
00360 total_tris += surface->count_tris();
00361 }
00362
00363 if (aim_for_tris && attempts < 10 &&
00364 (double)total_tris / (double)_num_tris > 1.1) {
00365
00366
00367
00368 set_num_tris(_num_tris);
00369 return count_tris(tri_factor * total_tris / _num_tris, attempts + 1);
00370 }
00371
00372 return total_tris;
00373 }
00374
00375
00376
00377
00378
00379
00380
00381
00382 void QtessInputEntry::
00383 output_extra(ostream &out, const pvector<double> &iso, char axis) {
00384 pvector<double>::const_iterator di;
00385 int expect = 0;
00386 for (di = iso.begin(); di != iso.end(); ++di) {
00387 while ((*di) > (double)expect) {
00388
00389 out << " !" << axis << expect;
00390 }
00391 if ((*di)==(double)expect) {
00392
00393 expect++;
00394 } else {
00395
00396 out << " " << axis << *di;
00397 }
00398 }
00399 }
00400
00401
00402
00403
00404
00405
00406 void QtessInputEntry::
00407 output(ostream &out) const {
00408 NodeNames::const_iterator nni;
00409 for (nni = _node_names.begin();
00410 nni != _node_names.end();
00411 ++nni) {
00412 out << (*nni) << " ";
00413 }
00414 out << ": ";
00415
00416 bool show_auto = false;
00417
00418 switch (_type) {
00419 case T_undefined:
00420 break;
00421
00422 case T_omit:
00423 out << "omit";
00424 break;
00425
00426 case T_num_tris:
00427 out << _num_tris;
00428 show_auto = true;
00429 break;
00430
00431 case T_uv:
00432 out << _num_u << " " << _num_v;
00433 output_extra(out, _iso_u, 'u');
00434 output_extra(out, _iso_v, 'v');
00435 show_auto = true;
00436 break;
00437
00438 case T_per_isoparam:
00439 case T_per_score:
00440 out << "i" << _per_isoparam;
00441 show_auto = true;
00442 break;
00443
00444 case T_importance:
00445 out << _importance * 100.0 << "%";
00446 break;
00447
00448 case T_match_uu:
00449 out << "matchuu";
00450 break;
00451
00452 case T_match_vv:
00453 out << "matchvv";
00454 break;
00455
00456 case T_match_uv:
00457 out << "matchuv";
00458 break;
00459
00460 case T_match_vu:
00461 out << "matchvu";
00462 break;
00463
00464 case T_min_u:
00465 out << "minu " << _num_u;
00466 break;
00467
00468 case T_min_v:
00469 out << "minv " << _num_v;
00470 break;
00471
00472 default:
00473 out << "Invalid!";
00474 }
00475
00476 if (show_auto) {
00477 out << " " << (_auto_place?"":"!") << "ap"
00478 << " " << (_auto_distribute?"":"!") << "ad";
00479 if (_auto_place || _auto_distribute) {
00480 out << " ar" << _curvature_ratio;
00481 }
00482 }
00483 }
00484
00485
00486
00487
00488
00489
00490 void QtessInputEntry::
00491 write(ostream &out, int indent_level) const {
00492 indent(out, indent_level) << (*this) << "\n";
00493 }