20 #include "mirtk/String.h" 21 #include "mirtk/Stream.h" 22 #include "mirtk/Array.h" 120 Token(TokenEnum token) : _Token(token) {}
121 Token(
char c) : _Token(TokenEnum(c)) {}
122 Token(
double number) : _Token(NUMBER), _Number(number),
123 _Integer(static_cast<int>(number)) {}
124 Token(
string name) : _Token(NAME), _Name(name) {}
126 Token(
const Token &token)
128 _Token (token._Token),
129 _Number (token._Number),
130 _Integer(token._Integer),
134 Token &operator =(
const Token &token)
136 _Token = token._Token;
137 _Number = token._Number;
138 _Integer = token._Integer;
143 bool operator ==(TokenEnum token)
const {
return _Token == token; }
144 bool operator !=(TokenEnum token)
const {
return _Token != token; }
149 Token NextToken(istream &in,
bool skip_ws =
true)
156 if (!in.get(c))
return END;
157 }
while (::isspace(c));
159 if (!in.get(c))
return END;
179 case '0':
case '1':
case '2':
case '3':
case '4':
180 case '5':
case '6':
case '7':
case '8':
case '9':
183 bool before_decimal_point = (c !=
'.');
185 if (isdigit(c) || (c ==
'.' && before_decimal_point)) {
186 if (c ==
'.') before_decimal_point =
false;
188 }
else if (c ==
'e' || c ==
'E') {
189 bool is_next_token =
false;
190 string exponent(1, c);
193 if (c ==
'-' || c ==
'+') {
197 is_next_token =
true;
200 is_next_token =
true;
202 }
else if (!isdigit(c)) {
203 is_next_token =
true;
205 if (!is_next_token) {
216 is_next_token =
true;
219 for (
auto it = exponent.rbegin(); it != exponent.rend(); ++it) {
233 in.setstate(std::ios::failbit);
239 if (!in.get(c2))
return c;
241 if (!::isalnum(c2) && c2 !=
'_')
return c;
243 while (in.get(c) && (isalnum(c) || c ==
'_')) name += c;
250 while (in.get(c) && (isalnum(c) || c ==
'_')) name += c;
255 cerr <<
"Invalid character in objective function description: \"" << c
256 <<
"\" (ASCII code " << int(c) <<
")" << endl;
265 double Number(istream &in, Token &token)
268 while (token == MINUS || token == PLUS) {
269 if (token == MINUS) w *= -1.0;
270 token = NextToken(in);
272 if (token == NUMBER) {
274 token = NextToken(in);
275 if (token != DIV)
return w;
276 token = NextToken(in);
277 if (token != NUMBER) {
279 cerr <<
"Expected number after / in energy formula" << endl;
282 double d = token._Number;
285 cerr <<
"Division by zero in energy formula!" << endl;
288 token = NextToken(in);
298 return (static_cast<double>(static_cast<int>(number)) == number);
303 Array<int> InputIndex(istream &in, Token &token,
const string &name,
304 DataType type,
int max_index)
308 const char *type_name;
314 type_name =
"images";
315 id_name =
"image identifier";
319 type_name =
"point set";
320 id_name =
"point set identifier";
323 cerr <<
"RegistrationEnergyParser::InputIndex: Invalid data type identifier: " << type << endl;
327 if (token != NAME || token._Name.substr(0, 1).find_first_of(c) != 0)
return index;
329 if (token._Name.size() == 1) {
330 token = NextToken(in);
333 cerr <<
"Expected single index or ( after input identifier of similarity term: " << name << endl;
336 token = NextToken(in);
337 bool inside_square_brackets = (token == LB);
338 if (inside_square_brackets) token = NextToken(in);
341 if (token == NAME && token._Name ==
"end") {
343 token = NextToken(in);
344 if (token == MINUS) {
345 token = NextToken(in);
346 if (token != NUMBER || !
IsInteger(token._Number) || token._Integer < 0) {
348 cerr <<
"Expected positive integer after 'end-' in input identifier of similarity term: " << name << endl;
351 start = -token._Integer;
352 token = NextToken(in);
354 }
else if (token == NUMBER &&
IsInteger(token._Number)) {
355 start = token._Integer;
356 token = NextToken(in);
359 cerr <<
"Expected input index or 'end' in identifier argument list of similarity term: " << name << endl;
364 if (token == COLON) {
365 token = NextToken(in);
366 if (token == NAME && token._Name ==
"end") {
368 token = NextToken(in);
369 if (token == MINUS) {
370 token = NextToken(in);
371 if (token != NUMBER || !
IsInteger(token._Number) || token._Integer < 0) {
373 cerr <<
"Expected positive integer after 'end-' in input identifier of similarity term: " << name << endl;
376 end = -token._Integer;
377 token = NextToken(in);
379 }
else if (token == NUMBER) {
380 if (!
IsInteger(token._Number) || token._Integer < 0) {
382 cerr <<
"Expected positive integer after : in input identifier of similarity term: " << name << endl;
385 end = token._Integer;
386 token = NextToken(in);
389 cerr <<
"Expected input index, 'end' or increment after : in input identifier of similarity term: " << name << endl;
392 if (token == COLON) {
395 token = NextToken(in);
396 if (token == NAME && token._Name ==
"end") {
398 token = NextToken(in);
399 if (token == MINUS) {
400 token = NextToken(in);
401 if (token != NUMBER || !
IsInteger(token._Number) || token._Integer < 0) {
403 cerr <<
"Expected positive integer after 'end-' in input identifier of similarity term: " << name << endl;
406 end = -token._Integer;
407 token = NextToken(in);
409 }
else if (token == NUMBER) {
410 if (!
IsInteger(token._Number) || token._Integer < 0) {
412 cerr <<
"Expected positive integer after : in input identifier of similarity term: " << name << endl;
415 end = token._Integer;
416 token = NextToken(in);
419 cerr <<
"Expected input index or 'end' after second : in input identifier of similarity term: " << name << endl;
424 if (end < 0) end += max_index + 1;
425 if (start < 1 || end < start || inc == 0) {
427 cerr <<
"Invalid index (range) in input identifier of energy term: " << name << endl;
430 if (start > max_index || end > max_index) {
432 cerr <<
"Not enough input " << type_name <<
" or invalid index (range) in " << id_name <<
" of similarity term: " << name << endl;
435 for (
int i = start - 1; i < end; i += inc) index.push_back(i);
437 if (!inside_square_brackets) {
439 cerr <<
"Found ] without matching [ in input identifier of similarity term: " << name << endl;
442 inside_square_brackets =
false;
443 token = NextToken(in);
444 }
else if (token == END) {
446 cerr <<
"Expected ] after input index (range) in input identifier of similarity term: " << name << endl;
449 }
while (inside_square_brackets);
452 cerr <<
"Expected ) after input index (range) in input identifier of similarity term: " << name << endl;
455 token = NextToken(in);
458 if (
FromString(token._Name.c_str() + 1, i) && i > 0 &&
459 token._Name == (token._Name.substr(0, 1) +
ToString(i))) {
462 cerr <<
"Not enought input " << type_name <<
" or invalid index in " << id_name <<
" of similarity term: " << name << endl;
465 index.push_back(i - 1);
466 token = NextToken(in);
469 cerr <<
"Not enough input " << type_name <<
" or invalid " << id_name <<
" " << token._Name <<
" in argument list of similarity term: " << name << endl;
481 static string Substitute(
const string &s,
const char *var, T value)
483 size_t pos = s.find(var);
484 if (pos == string::npos)
return s;
485 return s.substr(0, pos) +
ToString(value) + s.substr(pos + strlen(var));
492 string TermName(
const string &str,
const ImageSimilarityInfo &info,
int i = -1)
const 497 if (i > -1) name =
Substitute(name,
"{i}", i + 1);
503 string TermName(
const string &str,
const PointSetDistanceInfo &info,
int i = -1)
const 508 if (i > -1) name =
Substitute(name,
"{i}", i + 1);
514 string TermName(
const string &str,
const PointSetConstraintInfo &info,
int i = -1)
const 519 if (info._RefPointSetIndex > -1) {
520 name =
Substitute(name,
"{s}", info._RefPointSetIndex + 1);
521 }
else if (info._RefImageIndex > -1) {
522 name =
Substitute(name,
"{s}", info._RefImageIndex + 1);
524 if (i > -1) name =
Substitute(name,
"{i}", i + 1);
532 double weight = Number(in, token);
534 token = NextToken(in);
538 cerr <<
"Expected similarity or constraint name after optional weight value" << endl;
542 string name = token._Name;
543 TransformationInfo target_transformation;
544 TransformationInfo source_transformation;
545 Array<int> target_index;
546 Array<int> source_index;
547 bool source_is_image =
false;
554 enum { SIM, PDM, PCM, CM , MSDE };
555 bool term_is_[] = {
false,
false,
false,
false,
false };
565 const string lname =
ToLower(name);
566 term_is_[PCM ] = (IFT_Begin < measure && measure < IFT_End);
567 term_is_[SIM ] = ((lname ==
"sim") ||
FromString(name.c_str(), similarity));
568 term_is_[PDM ] = ((lname ==
"pdm") ||
FromString(name.c_str(), pdm));
569 term_is_[CM ] = (
FromString(name.c_str(), constraint));
571 if (!term_is_[SIM] && !term_is_[PDM] && !term_is_[PCM] && !term_is_[CM] && !term_is_[MSDE]) {
573 cerr <<
"Unknown energy term: " << name << endl;
577 bool default_measure = (term_is_[SIM] && lname ==
"sim") ||
578 (term_is_[PDM] && lname ==
"pdm");
581 token = NextToken(in);
583 token = NextToken(in,
false);
585 bool var_name =
false;
586 while (token == NAME || token == NUMBER || token == SPACE || token == COLON ||
587 token == PLUS || token == MINUS || token == MUL || token == DIV ||
588 token == CARET || token == CIRC || token == LCB || token == RCB) {
589 if (token == SPACE) name +=
' ';
590 else if (token == COLON) name +=
':';
591 else if (token == PLUS) name +=
'+';
592 else if (token == MINUS) name +=
'-';
593 else if (token == MUL) name +=
'*';
594 else if (token == DIV) name +=
'/';
595 else if (token == CARET) name +=
'^';
596 else if (token == CIRC) name +=
'o';
597 else if (token == NUMBER) name +=
ToString(token._Number);
598 else if (token == LCB) {
600 cerr <<
"Expected closing } in custom energy term name" << name << endl;
605 }
else if (token == RCB) {
607 cerr <<
"Found closing } without opening { in custom energy term name: " << name << endl;
612 }
else if (token == NAME) {
615 cerr <<
"Internal error: Unhandled token in energy term name" << endl;
618 token = NextToken(in,
false);
621 cerr <<
"Missing closing } in custom energy term name: " << name << endl;
626 cerr <<
"Expected closing ] after custom energy term name: " << name << endl;
629 token = NextToken(in);
634 token = NextToken(in);
638 if (token._Name ==
"T") {
639 token = NextToken(in);
641 if (!term_is_[CM] && !term_is_[MSDE]) {
643 cerr <<
"Transformation identifier cannot be only argument of energy term \"" << name <<
"\"," << endl;
644 cerr <<
"which is not a (known) transformation constraint (i.e., regularization term)." << endl;
648 if (token == CARET) {
649 token = NextToken(in);
650 if (token != NUMBER && token != MINUS && token != PLUS) {
652 cerr <<
"Expected exponent after ^ of transformation composition in argument list of energy term: " << name << endl;
655 target_transformation = Number(in, token);
657 target_transformation = 1.0;
661 cerr <<
"Expected function composition sign (o) after transformation identifier in argument list of energy term: " << name << endl;
664 token = NextToken(in);
665 term_is_[CM ] =
false;
666 term_is_[MSDE] =
false;
670 if ((term_is_[CM] || term_is_[MSDE]) && token == RP) {
672 term_is_[SIM] =
false;
673 term_is_[PDM] =
false;
674 term_is_[PCM] =
false;
676 }
else if (!(target_index = InputIndex(in, token, name, IMAGE, nimages)).empty()) {
678 if (!term_is_[SIM]) {
680 cerr <<
"Image identifier cannot be argument of energy term \"" << name <<
"\"," << endl;
681 cerr <<
"which is not a (known) pairwise image similarity term." << endl;
684 term_is_[PDM] =
false;
685 term_is_[CM] =
false;
686 term_is_[MSDE] =
false;
688 if (target_transformation) {
690 cerr <<
"Invalid function composition (o) of first image in argument list of fiducial registration error: " << name << endl;
691 cerr <<
"Note that the (source) image is transformed using the notation I2 o T, not T o I2!" << endl;
696 token = NextToken(in);
697 if (token != NAME || token._Name !=
"T") {
699 cerr <<
"Expected transformation after function composition sign (o) in argument list of similarity term: " << name << endl;
702 token = NextToken(in);
703 if (token == CARET) {
704 token = NextToken(in);
705 if (token != NUMBER && token != MINUS && token != PLUS) {
707 cerr <<
"Expected exponent after ^ of transformation composition in argument list of similarity term: " << name << endl;
710 target_transformation = Number(in, token);
712 target_transformation = 1.0;
716 if (token != COMMA) {
718 cerr <<
"Expected separating , after first image identifier in argument list of similarity term: " << name << endl;
721 token = NextToken(in);
722 if (token == NAME) source_index = InputIndex(in, token, name, IMAGE, nimages);
723 if (source_index.empty()) {
725 cerr <<
"Expected second image identifier after , of argument list of similarity term: " << name << endl;
729 token = NextToken(in);
730 if (token != NAME || token._Name !=
"T") {
732 cerr <<
"Expected transformation after function composition sign (o) in argument list of similarity term: " << name << endl;
735 token = NextToken(in);
736 if (token == CARET) {
737 token = NextToken(in);
738 if (token != NUMBER && token != MINUS && token != PLUS) {
740 cerr <<
"Expected exponent after ^ of transformation composition in argument list of similarity term: " << name << endl;
743 source_transformation = Number(in, token);
745 source_transformation = 1.0;
749 if (target_transformation.IsIdentity() && source_transformation.IsIdentity()) {
750 source_transformation = 1.0;
752 source_is_image =
true;
754 }
else if (!(target_index = InputIndex(in, token, name, POLYDATA, npsets)).empty()) {
756 if (!term_is_[PDM] && !term_is_[PCM]) {
758 cerr <<
"Point set identifier cannot be argument of energy term \"" << name <<
"\"," << endl;
759 cerr <<
"which is neither a (known) pairwise point set distance or internal force term." << endl;
763 term_is_[SIM] =
false;
764 term_is_[CM] =
false;
765 term_is_[MSDE] =
false;
769 cerr <<
"Invalid function composition (o) of point set in argument list of energy term: " << name << endl;
770 cerr <<
"Note that data sets are transformed using the notation T o S1, not S1 o T!" << endl;
775 if (!term_is_[PCM]) {
777 cerr <<
"Point set identifier cannot be argument of energy term \"" << name <<
"\"," << endl;
778 cerr <<
"which is not a (known) internal point set force term." << endl;
781 term_is_[PDM] =
false;
783 if (target_transformation.IsIdentity()) {
784 target_transformation = 1.0;
788 if (token != COMMA) {
790 cerr <<
"Expected separating , after first point set identifier in argument list of point set energy term: " << name << endl;
793 token = NextToken(in);
796 cerr <<
"Expected transformation or second input identifier after , of argument list of point set energy term: " << name << endl;
799 source_index = InputIndex(in, token, name, POLYDATA, npsets);
800 if (source_index.empty()) {
802 source_index = InputIndex(in, token, name, IMAGE, nimages);
803 if (source_index.empty()) {
805 if (token == NAME && token._Name ==
"T") {
806 cerr <<
"Expected second input identifier after , of argument list of point set constraint term: " << name << endl;
807 cerr <<
"Note that second data set is only used to define reference time frame to which the first" << endl;
808 cerr <<
"point set is transformed to and therefore no transformation of the second data set is allowed." << endl;
810 cerr <<
"Expected second input identifier after , of argument list of point set constraint term: " << name << endl;
814 source_is_image =
true;
816 if (token != NAME || token._Name !=
"T") {
818 cerr <<
"Expected (optionally transformed) second input identifier after , of argument list of point set energy term: " << name << endl;
821 token = NextToken(in);
822 if (token == CARET) {
823 token = NextToken(in);
824 if (token != NUMBER && token != MINUS && token != PLUS) {
826 cerr <<
"Expected exponent after ^ of transformation composition in argument list of point set energy term: " << name << endl;
829 source_transformation = Number(in, token);
831 source_transformation = 1.0;
835 cerr <<
"Expected function composition sign (o) after transformation identifier in argument list of point set energy term: " << name << endl;
838 token = NextToken(in);
839 if (token == NAME) source_index = InputIndex(in, token, name, POLYDATA, npsets);
840 if (source_index.empty()) {
842 cerr <<
"Expected point set identifier after function composition sign (o) in argument list of point set distance: " << name << endl;
849 cerr <<
"Invalid function composition (o) of second data set in argument list of point set energy term: " << name << endl;
851 cerr <<
"Note that (source) point sets are transformed using the notation T^-1 o S2, not S2 o T^-1!" << endl;
856 if (target_transformation.IsIdentity() && source_transformation.IsIdentity()) {
857 target_transformation = 1.0;
864 if (term_is_[SIM]) cerr <<
"image";
865 if (term_is_[PDM] || term_is_[PCM]) {
866 if (term_is_[SIM]) cerr <<
" or ";
869 if (term_is_[CM] || term_is_[MSDE]) {
870 if (term_is_[SIM] || term_is_[PDM] || term_is_[PCM]) cerr <<
" or ";
871 cerr <<
"transformation";
873 cerr <<
" identifier as argument of energy term: " << name << endl;
879 cerr <<
"Expected closing ) after argument list of energy term: " << name << endl;
882 token = NextToken(in);
884 if (target_index.empty() && source_index.empty()) {
885 if (!term_is_[CM] && !term_is_[MSDE]) {
888 if (term_is_[SIM]) cerr <<
"image";
889 if (term_is_[PDM] || term_is_[PCM]) {
890 if (term_is_[SIM]) cerr <<
" or ";
893 cerr <<
" identifiers as argument of energy term: " << name << endl;
896 term_is_[SIM] =
false;
897 term_is_[PDM] =
false;
898 term_is_[PCM] =
false;
904 if (term_is_[PDM] || term_is_[PCM] || term_is_[CM] || term_is_[MSDE]) {
906 cerr <<
"Ambiguous energy term: " << name << endl;
909 if (target_index.size() == 0 || source_index.size() == 0) {
911 cerr <<
"Missing image identifier in argument list of similarity term: " << name << endl;
914 if (!source_is_image) {
916 cerr <<
"Only images allowed as inputs of the image dissimilarity term: " << name << endl;
920 if (target_index.size() > 1) {
921 if (source_index.size() != 1 && source_index.size() != target_index.size()) {
923 cerr <<
"Mismatch of image index ranges in argument list of similarity term: " << name << endl;
926 weight /= target_index.size();
927 for (
size_t t = 0; t < target_index.size(); ++t) {
928 size_t s = (source_index.size() == 1 ? 0 : t);
929 ImageSimilarityInfo info;
941 if (target_index.size() != 1) {
943 cerr <<
"Mismatch of image index ranges in argument list of similarity term: " << name << endl;
946 weight /= source_index.size();
947 for (
size_t s = 0; s < source_index.size(); ++s) {
948 ImageSimilarityInfo info;
965 if (term_is_[SIM] || term_is_[PCM] || term_is_[CM] || term_is_[MSDE]) {
967 cerr <<
"Ambiguous energy term: " << name << endl;
970 if (target_index.size() == 0 || source_index.size() == 0) {
972 cerr <<
"Missing point set identifier in argument list of point set distance term: " << name << endl;
975 if (source_is_image) {
977 cerr <<
"Only point sets allowed as inputs of the point set distance term: " << name << endl;
981 if (target_index.size() > 1) {
982 if (source_index.size() != 1 && source_index.size() != target_index.size()) {
984 cerr <<
"Mismatch of point set index ranges in argument list of point set distance term: " << name << endl;
987 weight /= target_index.size();
988 for (
size_t t = 0; t < target_index.size(); ++t) {
989 size_t s = (source_index.size() == 1 ? 0 : t);
990 PointSetDistanceInfo info;
1002 if (target_index.size() != 1) {
1004 cerr <<
"Mismatch of point set index ranges in argument list of point set distance term: " << name << endl;
1007 weight /= source_index.size();
1008 for (
size_t s = 0; s < source_index.size(); ++s) {
1009 PointSetDistanceInfo info;
1024 if (term_is_[PCM]) {
1026 if (term_is_[SIM] || term_is_[PDM] || term_is_[CM] || term_is_[MSDE]) {
1028 cerr <<
"Ambiguous energy term: " << name << endl;
1031 if (target_index.size() == 0) {
1033 cerr <<
"Missing point set identifier in argument list of internal point set force term: " << name << endl;
1037 if (source_index.size() > 0) {
1038 if (target_index.size() > 1) {
1039 if (source_index.size() != 1 && source_index.size() != target_index.size()) {
1041 cerr <<
"Mismatch of input index ranges in argument list of point set constraint term: " << name << endl;
1044 weight /= target_index.size();
1045 for (
size_t t = 0; t < target_index.size(); ++t) {
1046 size_t s = (source_index.size() == 1 ? 0 : t);
1047 PointSetConstraintInfo info;
1052 if (source_is_image) {
1053 info._RefPointSetIndex = -1;
1054 info._RefImageIndex = source_index[s];
1056 info._RefPointSetIndex = source_index[s];
1057 info._RefImageIndex = -1;
1063 if (target_index.size() != 1) {
1065 cerr <<
"Mismatch of input index ranges in argument list of point set constraint term: " << name << endl;
1068 weight /= source_index.size();
1069 for (
size_t s = 0; s < source_index.size(); ++s) {
1070 PointSetConstraintInfo info;
1075 if (source_is_image) {
1076 info._RefPointSetIndex = -1;
1077 info._RefImageIndex = source_index[s];
1079 info._RefPointSetIndex = source_index[s];
1080 info._RefImageIndex = -1;
1087 weight /= target_index.size();
1088 for (
size_t t = 0; t < target_index.size(); ++t) {
1089 PointSetConstraintInfo info;
1094 info._RefPointSetIndex = -1;
1095 info._RefImageIndex = -1;
1106 if (term_is_[SIM] || term_is_[PDM] || term_is_[PCM] || term_is_[MSDE]) {
1108 cerr <<
"Ambiguous energy term: " << name << endl;
1112 ConstraintInfo info;
1120 if (term_is_[MSDE]) {
1122 if (term_is_[SIM] || term_is_[PDM] || term_is_[PCM] || term_is_[CM]) {
1124 cerr <<
"Ambiguous energy term: " << name << endl;
1128 _Filter->TargetTransformationErrorName(name);
1129 _Filter->TargetTransformationErrorWeight(weight);
1133 if (!term_is_[SIM] && !term_is_[PDM] && !term_is_[PCM] && !term_is_[CM] && !term_is_[MSDE]) {
1135 cerr <<
"Unknown enery term: " << name << endl;
1153 istringstream formula(energy_formula);
1164 token = NextToken(formula);
1165 while (token != END) {
string _Name
Name of constraint.
TransformationInfo _TargetTransformation
Target transformation identifier.
int NumberOfImages() const
Number of input images.
int _SourceIndex
Index of source data set.
EnergyMeasure _Measure
Type of internal forces.
TransformationInfo _Transformation
Point set transformation identifier.
TransformationInfo _SourceTransformation
Source transformation identifier.
string TermName(const string &str, const ImageSimilarityInfo &info, int i=-1) const
Name of image dissimilarity term.
static string Substitute(const string &s, const char *var, T value)
Substitute single substring by given value.
TransformationInfo _SourceTransformation
Source transformation identifier.
void ParseEnergyTerm(istream &in, Token &token, int nimages, int npsets)
Parse and store information about next energy term.
Mean squared deviation from given deformation.
int NumberOfPointSets() const
Number of input point sets.
bool _DefaultSign
Whether to use default sign of similarity.
Array< ConstraintInfo > _ConstraintInfo
Parsed constraint(s)
bool IsInteger(const char *str)
Check if given string is an integer value.
int _TargetIndex
Index of target data set.
string ToLower(const string &)
Convert string to lowercase letters.
TransformationInfo _TargetTransformation
Target transformation identifier.
double _Weight
Weight of constraint.
double _Weight
Weight of similarity term.
void ParseEnergyFormula(const string &energy_formula, int nimages=-1, int npsets=-1)
Parse energy function.
int _TargetIndex
Index of target image.
RegistrationEnergyParser(GenericRegistrationFilter *filter)
Constructor.
MIRTKCU_API bool operator==(const float1 &a, const float1 &b)
Check two 1D vectors for equality.
string TermName(const string &str, const PointSetConstraintInfo &info, int i=-1) const
Name of point set constraint term.
Array< PointSetConstraintInfo > _PointSetConstraintInfo
Unused.
string ToString(const EnergyMeasure &value, int w, char c, bool left)
Convert energy measure enumeration value to string.
bool FromString(const char *str, EnergyMeasure &value)
Convert energy measure string to enumeration value.
EnergyMeasure
Enumeration of all available energy terms.
string _Name
Name of constraint.
Array< PointSetDistanceInfo > _PointSetDistanceInfo
Unused.
string _Name
Name of polydata distance term.
int _PointSetIndex
Index of input point set object.
int _SourceIndex
Index of source image.
string _Name
Name of similarity term.
SimilarityMeasure _Measure
Type of similarity measure.
ConstraintMeasure _Measure
Type of constraint.
PointSetDistanceMeasure _Measure
Measure of polydata distance.
double _Weight
Weight of constraint.
bool _DefaultSign
Whether to use default sign of distance measure.
Array< ImageSimilarityInfo > _ImageSimilarityInfo
Parsed similarity measure(s)
double _Weight
Weight of polydata distance term.
string TermName(const string &str, const PointSetDistanceInfo &info, int i=-1) const
Name of point set distance term.