Commit e9894aec authored by Bob Obara's avatar Bob Obara

ENH: Added the ability to sort Mesh-based Descriptive Phrases

- Mesh-based Descriptive Phrases can now be sorted by on their titles.  This means that by default
Meshes are listed in the order they are generated (oldest first)

Also refactored all of the existing Descriptive Phrase comparison functions that were used for sorting.
The DescriptivePhrase class now holds static methods for comparing Descriptive Phrases based on their titles as well
as based on Model Information they refer to.
parent 165c0d81
......@@ -170,5 +170,116 @@ bool DescriptivePhrase::isPropertyValueType() const
phType == STRING_PROPERTY_VALUE;
}
bool DescriptivePhrase::compareByModelInfo(const DescriptivePhrasePtr& a,
const DescriptivePhrasePtr& b)
{
static const int sortOrder[] = {
1, // ENTITY_LIST
0, // ENTITY_SUMMARY
2, // ARRANGEMENT_LIST
3, // ATTRIBUTE_LIST
4, // MODEL_INCLUDES_ENTITY
5, // MODEL_EMBEDDED_IN_MODEL
6, // CELL_INCLUDES_CELL
7, // CELL_EMBEDDED_IN_CELL
8, // CELL_HAS_SHELL
9, // CELL_HAS_USE
10, // SHELL_HAS_CELL
11, // SHELL_HAS_USE
12, // USE_HAS_CELL
13, // USE_HAS_SHELL
15, // FLOAT_PROPERTY_LIST
16, // STRING_PROPERTY_LIST
14, // INTEGER_PROPERTY_LIST
18, // ENTITY_HAS_FLOAT_PROPERTY
19, // ENTITY_HAS_STRING_PROPERTY
17, // ENTITY_HAS_INTEGER_PROPERTY
20, // ENTITY_HAS_ATTRIBUTE
22, // FLOAT_PROPERTY_VALUE
23, // STRING_PROPERTY_VALUE
21, // INTEGER_PROPERTY_VALUE
24, // ENTITY_HAS_SUBPHRASES
25 // INVALID_DESCRIPTION
};
// I. Sort by phrase type.
DescriptivePhraseType pta = a->phraseType();
DescriptivePhraseType ptb = b->phraseType();
if (pta != ptb)
{
return sortOrder[pta] < sortOrder[ptb];
}
// II. Sort by entity type/dimension
// II.a. Entity type
BitFlags eta = a->relatedEntity().entityFlags() & ENTITY_MASK;
BitFlags etb = b->relatedEntity().entityFlags() & ENTITY_MASK;
if (eta != etb)
{
switch (eta)
{
case CELL_ENTITY: // 0x0100
return etb == MODEL_ENTITY ? false : true;
case USE_ENTITY: // 0x0200
return etb == MODEL_ENTITY || etb < USE_ENTITY ? false : true;
case SHELL_ENTITY: // 0x0400
return etb == MODEL_ENTITY || etb < SHELL_ENTITY ? false : true;
case GROUP_ENTITY: // 0x0800
return etb == MODEL_ENTITY || etb < SHELL_ENTITY ? false : true;
case MODEL_ENTITY: // 0x1000
return true;
case INSTANCE_ENTITY: // 0x2000
return false;
default:
return eta < etb ? true : false;
}
}
// II.b. Dimension
eta = a->relatedEntity().entityFlags() & ANY_DIMENSION;
etb = b->relatedEntity().entityFlags() & ANY_DIMENSION;
if (eta != etb)
return eta < etb;
// III. Sort by title, with care taken when differences are numeric values.
return compareByTitle(a, b);
}
bool DescriptivePhrase::compareByTitle(const DescriptivePhrasePtr& a,
const DescriptivePhrasePtr& b)
{
std::string ta(a->title());
std::string tb(b->title());
if (ta.empty())
return true;
if (tb.empty())
return false;
std::string::size_type minlen = ta.size() < tb.size() ? ta.size() : tb.size();
std::string::size_type i;
for (i = 0; i < minlen; ++i)
if (ta[i] != tb[i])
break; // Stop at the first difference between ta and tb.
// Shorter strings are less than longer versions with the same start:
if (i == minlen)
return ta.size() < tb.size() ? true : false;
// Both ta & tb have some character present and different.
bool da = isdigit(ta[i]) ? true : false;
bool db = isdigit(tb[i]) ? true : false;
if (da && !db)
return true; // digits come before other things
if (!da && db)
return false; // non-digits come after digits
if (!da && !db)
return ta[i] < tb[i];
// Now, both ta and tb differ with some numeric value.
// Convert to a number and compare the numbers.
double na = atof(ta.substr(i).c_str());
double nb = atof(tb.substr(i).c_str());
return na < nb;
}
} // model namespace
} // smtk namespace
......@@ -143,6 +143,24 @@ public:
SubphraseGeneratorPtr findDelegate();
virtual bool isPropertyValueType() const;
/**\brief Detailed Comparison method for Model Entity DescriptivePhrases
*
* This can be used to help sort DescriptivePhrases for Model Entities.
* The sorting is based on Entity Type, Entity Dimension and Title
*/
static bool compareByModelInfo(const DescriptivePhrasePtr& a,
const DescriptivePhrasePtr& b);
/**\brief Ttile-based Comparison method for DescriptivePhrases
*
* This can be used to help sort DescriptivePhrases based on their
* titles.
*/
static bool compareByTitle(const DescriptivePhrasePtr& a,
const DescriptivePhrasePtr& b);
protected:
DescriptivePhrase();
......
......@@ -30,109 +30,6 @@ namespace smtk
namespace model
{
static bool SpecialEntityNameSort(const DescriptivePhrasePtr& a, const DescriptivePhrasePtr& b)
{
static const int sortOrder[] = {
1, // ENTITY_LIST
0, // ENTITY_SUMMARY
2, // ARRANGEMENT_LIST
3, // ATTRIBUTE_LIST
4, // MODEL_INCLUDES_ENTITY
5, // MODEL_EMBEDDED_IN_MODEL
6, // CELL_INCLUDES_CELL
7, // CELL_EMBEDDED_IN_CELL
8, // CELL_HAS_SHELL
9, // CELL_HAS_USE
10, // SHELL_HAS_CELL
11, // SHELL_HAS_USE
12, // USE_HAS_CELL
13, // USE_HAS_SHELL
15, // FLOAT_PROPERTY_LIST
16, // STRING_PROPERTY_LIST
14, // INTEGER_PROPERTY_LIST
18, // ENTITY_HAS_FLOAT_PROPERTY
19, // ENTITY_HAS_STRING_PROPERTY
17, // ENTITY_HAS_INTEGER_PROPERTY
20, // ENTITY_HAS_ATTRIBUTE
22, // FLOAT_PROPERTY_VALUE
23, // STRING_PROPERTY_VALUE
21, // INTEGER_PROPERTY_VALUE
24, // ENTITY_HAS_SUBPHRASES
25 // INVALID_DESCRIPTION
};
// I. Sort by phrase type.
DescriptivePhraseType pta = a->phraseType();
DescriptivePhraseType ptb = b->phraseType();
if (pta != ptb)
{
return sortOrder[pta] < sortOrder[ptb];
}
// II. Sort by entity type/dimension
// II.a. Entity type
BitFlags eta = a->relatedEntity().entityFlags() & ENTITY_MASK;
BitFlags etb = b->relatedEntity().entityFlags() & ENTITY_MASK;
if (eta != etb)
{
switch (eta)
{
case CELL_ENTITY: // 0x0100
return etb == MODEL_ENTITY ? false : true;
case USE_ENTITY: // 0x0200
return etb == MODEL_ENTITY || etb < USE_ENTITY ? false : true;
case SHELL_ENTITY: // 0x0400
return etb == MODEL_ENTITY || etb < SHELL_ENTITY ? false : true;
case GROUP_ENTITY: // 0x0800
return etb == MODEL_ENTITY || etb < SHELL_ENTITY ? false : true;
case MODEL_ENTITY: // 0x1000
return true;
case INSTANCE_ENTITY: // 0x2000
return false;
default:
return eta < etb ? true : false;
}
}
// II.b. Dimension
eta = a->relatedEntity().entityFlags() & ANY_DIMENSION;
etb = b->relatedEntity().entityFlags() & ANY_DIMENSION;
if (eta != etb)
return eta < etb;
// III. Sort by title, with care taken when differences are numeric values.
std::string ta(a->title());
std::string tb(b->title());
if (ta.empty())
return true;
if (tb.empty())
return false;
std::string::size_type minlen = ta.size() < tb.size() ? ta.size() : tb.size();
std::string::size_type i;
for (i = 0; i < minlen; ++i)
if (ta[i] != tb[i])
break; // Stop at the first difference between ta and tb.
// Shorter strings are less than longer versions with the same start:
if (i == minlen)
return ta.size() < tb.size() ? true : false;
// Both ta & tb have some character present and different.
bool da = isdigit(ta[i]) ? true : false;
bool db = isdigit(tb[i]) ? true : false;
if (da && !db)
return true; // digits come before other things
if (!da && db)
return false; // non-digits come after digits
if (!da && !db)
return ta[i] < tb[i];
// Now, both ta and tb differ with some numeric value.
// Convert to a number and compare the numbers.
double na = atof(ta.substr(i).c_str());
double nb = atof(tb.substr(i).c_str());
return na < nb;
}
EntityTypeSubphrases::EntityTypeSubphrases()
{
m_directlimit = 100;
......@@ -168,7 +65,7 @@ DescriptivePhrases EntityTypeSubphrases::subphrases(DescriptivePhrase::Ptr src)
// Now sort the list
if (shouldSort)
{
std::sort(result.begin(), result.end(), SpecialEntityNameSort);
std::sort(result.begin(), result.end(), DescriptivePhrase::compareByModelInfo);
}
return result;
......
......@@ -30,106 +30,6 @@ namespace smtk
namespace model
{
static bool SpecialEntityNameSort(const DescriptivePhrasePtr& a, const DescriptivePhrasePtr& b)
{
static const int sortOrder[] = {
1, // ENTITY_LIST
0, // ENTITY_SUMMARY
2, // ARRANGEMENT_LIST
3, // ATTRIBUTE_LIST
4, // MODEL_INCLUDES_ENTITY
5, // MODEL_EMBEDDED_IN_MODEL
6, // CELL_INCLUDES_CELL
7, // CELL_EMBEDDED_IN_CELL
8, // CELL_HAS_SHELL
9, // CELL_HAS_USE
10, // SHELL_HAS_CELL
11, // SHELL_HAS_USE
12, // USE_HAS_CELL
13, // USE_HAS_SHELL
15, // FLOAT_PROPERTY_LIST
16, // STRING_PROPERTY_LIST
14, // INTEGER_PROPERTY_LIST
18, // ENTITY_HAS_FLOAT_PROPERTY
19, // ENTITY_HAS_STRING_PROPERTY
17, // ENTITY_HAS_INTEGER_PROPERTY
20, // ENTITY_HAS_ATTRIBUTE
22, // FLOAT_PROPERTY_VALUE
23, // STRING_PROPERTY_VALUE
21, // INTEGER_PROPERTY_VALUE
24, // ENTITY_HAS_SUBPHRASES
25 // INVALID_DESCRIPTION
};
// I. Sort by phrase type.
DescriptivePhraseType pta = a->phraseType();
DescriptivePhraseType ptb = b->phraseType();
if (pta != ptb)
return sortOrder[pta] < sortOrder[ptb];
// II. Sort by entity type/dimension
// II.a. Entity type
BitFlags eta = a->relatedEntity().entityFlags() & ENTITY_MASK;
BitFlags etb = b->relatedEntity().entityFlags() & ENTITY_MASK;
if (eta != etb)
{
switch (eta)
{
case CELL_ENTITY: // 0x0100
return etb == MODEL_ENTITY ? false : true;
case USE_ENTITY: // 0x0200
return etb == MODEL_ENTITY || etb < USE_ENTITY ? false : true;
case SHELL_ENTITY: // 0x0400
return etb == MODEL_ENTITY || etb < SHELL_ENTITY ? false : true;
case GROUP_ENTITY: // 0x0800
return etb == MODEL_ENTITY || etb < SHELL_ENTITY ? false : true;
case MODEL_ENTITY: // 0x1000
return true;
case INSTANCE_ENTITY: // 0x2000
return false;
default:
return eta < etb ? true : false;
}
}
// II.b. Dimension
eta = a->relatedEntity().entityFlags() & ANY_DIMENSION;
etb = b->relatedEntity().entityFlags() & ANY_DIMENSION;
if (eta != etb)
return eta < etb;
// III. Sort by title, with care taken when differences are numeric values.
std::string ta(a->title());
std::string tb(b->title());
if (ta.empty())
return true;
if (tb.empty())
return false;
std::string::size_type minlen = ta.size() < tb.size() ? ta.size() : tb.size();
std::string::size_type i;
for (i = 0; i < minlen; ++i)
if (ta[i] != tb[i])
break; // Stop at the first difference between ta and tb.
// Shorter strings are less than longer versions with the same start:
if (i == minlen)
return ta.size() < tb.size() ? true : false;
// Both ta & tb have some character present and different.
bool da = isdigit(ta[i]) ? true : false;
bool db = isdigit(tb[i]) ? true : false;
if (da && !db)
return true; // digits come before other things
if (!da && db)
return false; // non-digits come after digits
if (!da && !db)
return ta[i] < tb[i];
// Now, both ta and tb differ with some numeric value.
// Convert to a number and compare the numbers.
double na = atof(ta.substr(i).c_str());
double nb = atof(tb.substr(i).c_str());
return na < nb;
}
SimpleModelSubphrases::SimpleModelSubphrases()
: m_abridgeUses(true)
......@@ -166,7 +66,7 @@ DescriptivePhrases SimpleModelSubphrases::subphrases(DescriptivePhrase::Ptr src)
// Now sort the list
if (shouldSort)
{
std::sort(result.begin(), result.end(), SpecialEntityNameSort);
std::sort(result.begin(), result.end(), DescriptivePhrase::compareByModelInfo);
}
return result;
......
......@@ -298,7 +298,13 @@ void SubphraseGenerator::meshesOfModel(
{
std::vector<smtk::mesh::CollectionPtr> meshCollections =
mod.manager()->meshes()->associatedCollections(mod);
addMeshPhrases(meshCollections, src, this->directLimit(), result);
// We need to sort the meshes before we add them to the result since if
// we sort the result itself we could be intermixing the mesh and model
// information
DescriptivePhrases meshPhrases;
addMeshPhrases(meshCollections, src, this->directLimit(), meshPhrases);
std::sort(meshPhrases.begin(), meshPhrases.end(), DescriptivePhrase::compareByTitle);
result.insert(result.end(), meshPhrases.begin(), meshPhrases.end());
}
void SubphraseGenerator::prototypeOfInstance(
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment