Create openMVS.build

This commit is contained in:
hesuicong committed 2025-09-26 10:13:00 +08:00
commit 365aa390ba
1856 files changed
+839085

No files matched your search

@@ -0,0 +1,108 @@
#include <utility>
#include <map>
#include <list>
#include "Node.h"
using namespace std;
class OwnSlotsNode: public Node
{
public:
OwnSlotsNode(void){node_type = OWNSLOTS_NODE;};
int node_type;
NodeGroup own_slot;
virtual void printNode();
virtual int qualifyNode();
void addOwnSlot(NodeGroup* ng);
void addOwnSlot(OwnSlotNode* os);
};
void OwnSlotsNode::addOwnSlot(NodeGroup* ng)
{
list<Node*>::iterator it;
for(it = ng->Sons.begin(); it!=ng->Sons.end(); ++it)
own_slot.addNode(*it);
}
void OwnSlotsNode::addOwnSlot(OwnSlotNode* os)
{
//OwnSlotNode* osn = new OwnSlotNode;
// own_slots.Sons.push_back(new OwnSlotNode);
own_slot.addNode(os);
}
void OwnSlotsNode::printNode()
{
cout<<"OwnSlotsNode: Node type is "<<node_type<<"\n";
list<Node*>::iterator it;
for(it = own_slot.Sons.begin(); it!=own_slot.Sons.end(); ++it)
(*it)->printNode();
}
int OwnSlotsNode::qualifyNode()
{return node_type;}
class ClassNode: public Node
{
public:
ClassNode(void){node_type = CLASS_NODE;};
int node_type;
OwnSlotsNode own_slots;
void addOwnSlots(OwnSlotsNode* own_slots);
virtual void printNode();
virtual int qualifyNode();
};
void ClassNode::addOwnSlots(OwnSlotsNode* sn)
{
own_slots.addOwnSlot(&sn->own_slot);
}
void ClassNode::printNode()
{
cout<<"ClassNode: Node type is "<<node_type<<"\n";
own_slots.printNode();
}
int ClassNode::qualifyNode()
{return node_type;}
class ClassesNode: public Node
{
public:
ClassesNode(void){node_type = CLASSES_NODE;};
int node_type;
NodeGroup classn;
void addClass(ClassNode* cn);
virtual void printNode();
virtual int qualifyNode();
};
void ClassesNode::addClass(ClassNode* cn)
{
classn.Sons.push_back(new ClassNode);
ClassNode* clp = (ClassNode*) classn.Sons.front();
clp->addOwnSlots(&cn->own_slots);
}
void ClassesNode::printNode()
{
cout<<"ClassesNode: Node type is "<<node_type<<"\n";
list<Node*>::iterator it;
for(it = classn.Sons.begin(); it!=classn.Sons.end(); ++it)
(*it)->printNode();
}
int ClassesNode::qualifyNode()
{return node_type;}
@@ -0,0 +1,69 @@
#include <utility>
#include <map>
#include <list>
#include "Node.h"
class InstanceNode: public Node
{
public:
InstanceNode(void){node_type = INSTANCE_NODE; id = "empty"; type= "empty";};
char* id;
char* type;
int node_type;
OwnSlotsNode own_slots;
void addOwnSlots(OwnSlotsNode* own_slots);
virtual void printNode();
virtual int qualifyNode();
};
void InstanceNode::addOwnSlots(OwnSlotsNode* sn)
{
own_slots.addOwnSlot(&sn->own_slot);
}
void InstanceNode::printNode()
{
cout<<"InstanceNode: Node node_type is "<<node_type<<"\n";
cout<<"InstanceNode: Node type is "<<type<<"\n";
cout<<"InstanceNode: Node id is "<<id<<"\n";
own_slots.printNode();
}
int InstanceNode::qualifyNode()
{return node_type;}
class InstancesNode: public Node
{
public:
InstancesNode(void){node_type = INSTANCES_NODE;};
int node_type;
NodeGroup instances;
void addInstance(InstanceNode* in);
virtual void printNode();
virtual int qualifyNode();
};
void InstancesNode::addInstance(InstanceNode* in)
{
instances.Sons.push_back(new InstanceNode);
InstanceNode* ilp = (InstanceNode*) instances.Sons.front();
ilp->addOwnSlots(&in->own_slots);
}
void InstancesNode::printNode()
{
cout<<"InstancesNode: Node type is "<<node_type<<"\n";
list<Node*>::iterator it;
for(it = instances.Sons.begin(); it!=instances.Sons.end(); ++it)
(*it)->printNode();
}
int InstancesNode::qualifyNode()
{return node_type;}
@@ -0,0 +1,78 @@
#ifndef NODE_H
#define NODE_H
#include <list>
using namespace std;
class Node
{
public:
//int node_type;
virtual ~Node(void){};
virtual void printNode()=0;
virtual int qualifyNode()=0;
};
class NodeGroup :public Node
{
public:
virtual ~NodeGroup();
typedef list<Node *>::iterator iterator;
list<Node *> Sons;
virtual void addNode(Node* nd);
virtual void printNode();
virtual int qualifyNode();
};
NodeGroup::~NodeGroup() //distruttore: disalloca tutti i figli
{
//for(iterator i=Sons.begin();i!=Sons.end();++i)
// delete (*i);
}
void NodeGroup::addNode(Node* nd)
{
Sons.push_back(nd);
}
void NodeGroup::printNode()
{}
int NodeGroup::qualifyNode()
{return 0;}
const int MAIN_NODE= 0;
const int SLOTS_NODE= 1;
const int SLOT_NODE= 2;
const int OWNSLOT_NODE= 3;
const int ENTRY_NODE= 4;
const int VALUE_NODE= 5;
const int CLASSES_NODE= 6;
const int CLASS_NODE= 7;
const int OWNSLOTS_NODE= 8;
const int INSTANCES_NODE= 9;
const int INSTANCE_NODE= 10;
enum values {VALUE_INTEGER, VALUE_FLOAT, VALUE_BOOL, VALUE_STRING};
//#define MAIN_NODE 0;
//#define SLOTS_NODE 1;
//#define SLOT_NODE 2;
//#define OWNSLOT_NODE 3;
//#define ENTRY_NODE 4;
//#define VALUE_NODE 5;
//
//#define CLASSES_NODE 6;
//#define CLASS_NODE 7;
//#define OWNSLOTS_NODE 8;
//
//#define INSTANCES_NODE 9;
//#define INSTANCE_NODE 10;
#endif
@@ -0,0 +1,151 @@
#include <utility>
#include <map>
#include <list>
#include "Node.h"
using namespace std;
class ValueNode: public Node
{
public:
ValueNode(void){node_type = VALUE_NODE;value = "empty";};
int node_type;
string value; //tra due tag
virtual void printNode();
virtual int qualifyNode();
void setValue(ValueNode vn){value = vn.value;};
void setValue(const char* cvn){value = cvn;};
};
void ValueNode::printNode()
{
cout<<"ValueNode: Node type is "<<node_type<<"\n";
cout<<"ValueNode: Node value is "<<value<<"\n";
}
int ValueNode::qualifyNode()
{return node_type;}
class EntryNode: public Node
{
public:
EntryNode(void){node_type = ENTRY_NODE; type = "empty";};
int node_type;
const char* type;
ValueNode value;
void addValue(ValueNode vn);
void setEntry(EntryNode en);
virtual void printNode();
virtual int qualifyNode();
};
void EntryNode::addValue(ValueNode vn)
{
value.setValue(vn);
}
void EntryNode::setEntry(EntryNode en)
{
type = en.type;
addValue(en.value);
}
void EntryNode::printNode()
{
cout<<"EntryNode: Node type is "<<node_type<<"\n";
cout<<"EntryNode: Node attr. type is "<<type<<"\n";
value.printNode();
}
int EntryNode::qualifyNode()
{return node_type;}
class OwnSlotNode: public Node
{
public:
OwnSlotNode(void){node_type = OWNSLOT_NODE; name = "empty";};
int node_type;
const char* name;
EntryNode entry;
virtual void printNode();
virtual int qualifyNode();
void addEntry(EntryNode en);
void setName(const char* s){name = s;};
};
void OwnSlotNode::printNode()
{
cout<<"OwnSlotNode: Node type is "<<node_type<<"\n";
cout<<"OwnSlotNode: Node name is "<<name<<"\n";
entry.printNode();
}
int OwnSlotNode::qualifyNode()
{return node_type;}
void OwnSlotNode::addEntry(EntryNode en)
{
entry.setEntry(en);
}
class SlotNode: public Node
{
public:
SlotNode(void){node_type = SLOT_NODE;};
int node_type;
NodeGroup own_slot;
virtual void printNode();
virtual int qualifyNode();
void addOwnSlot(OwnSlotNode* os);
};
void SlotNode::addOwnSlot(OwnSlotNode* os)
{
//OwnSlotNode* osn = new OwnSlotNode;
// own_slots.Sons.push_back(new OwnSlotNode);
own_slot.addNode(os);
}
void SlotNode::printNode()
{
cout<<"SlotNode: Node type is "<<node_type<<"\n";
list<Node*>::iterator it;
for(it = own_slot.Sons.begin(); it!=own_slot.Sons.end(); ++it)
(*it)->printNode();
}
int SlotNode::qualifyNode()
{return node_type;}
class SlotsNode: public Node
{
public:
SlotsNode(void){node_type = SLOTS_NODE;};
int node_type;
NodeGroup slot;
void addSlot(SlotNode* sn);
virtual void printNode();
virtual int qualifyNode();
};
void SlotsNode::addSlot(SlotNode* sn)
{
slot.Sons.push_back(new SlotNode);
SlotNode* slp = (SlotNode*) slot.Sons.front();
list<Node*>::iterator it;
for(it = sn->own_slot.Sons.begin(); it!=sn->own_slot.Sons.end(); ++it)
slp->addOwnSlot(((OwnSlotNode*)(*it)));
}
void SlotsNode::printNode()
{
cout<<"SlotsNode: Node type is "<<node_type<<"\n";
list<Node*>::iterator it;
for(it = slot.Sons.begin(); it!=slot.Sons.end(); ++it)
(*it)->printNode();
}
int SlotsNode::qualifyNode()
{return node_type;}
@@ -0,0 +1,354 @@
#include <utility>
#include <map>
#include <list>
#include <string>
#include <iostream>
#include "SlotsNode.h"
#include "ClassesNode.h"
#include "InstancesNode.h"
using namespace std;
static char* XML_SCHEMA_NAME = "protegekb";
class FacetNode: public Node
{
virtual void printNode();
virtual int qualifyNode();
};
class FacetsNode: public Node
{
NodeGroup facets;
virtual void printNode();
virtual int qualifyNode();
};
class MainNode: public Node
{
public:
MainNode(void){node_type = MAIN_NODE;};
int node_type;
list<pair<const char* , const char* > > headers;
void addHeaders(const char* str, const char* val);
virtual void printNode();
virtual int qualifyNode();
};
void MainNode::addHeaders(const char* str, const char*val)
{
headers.push_back(pair<const char*, const char*>(str,val));
}
void MainNode::printNode()
{
cout << "MainNode: node_type is " << node_type << "\n";
list<pair<const char*,const char*> >::iterator it;
for(it = headers.begin(); it!= headers.end(); ++it)
{
cout << "MainNode: First element is " << it->first << "\n";
cout << "MainNode: Second element is " << it->second << "\n";
}
}
int MainNode::qualifyNode()
{return node_type;}
class XMLTree
{
private:
static const char *DEFAULT_NAME;
string filename;
bool verbose;
public:
XMLTree(void){verbose = false;}
~XMLTree(void){}
NodeGroup root;
NodeGroup ng;
SlotNode sn;
// methods
void setName(const char *name);
void setVerboseMode(bool flag);
void initializeMain();
void finalizeMain();
void addHeaders(const char* str, const char*val);
void addSlots(SlotNode* sn);
//void addFacets();
void addClasses(ClassNode* cn);
void addInstances(InstanceNode* in);
void addNode(const char* s, int value_type, const char* name);
void printXMLTree();
};
const char * XMLTree::DEFAULT_NAME = "XmlTree.xml";
void XMLTree::setName(const char *name)
{
filename = name;
}
void XMLTree::setVerboseMode(bool flag)
{
verbose = flag;
}
void XMLTree::initializeMain()
{
MainNode* mn = new MainNode;
mn->headers.push_back(pair<const char*, const char*>("protegekb", ""));
char* s1 = "http://www.w3.org/2001/XMLSchema-instance";
char* s2 = new char[100];
sprintf(s2,"\"%s\"",s1);
mn->addHeaders(" xmlns:xsi=", s2);
s1 = "http://protege.stanford.edu/plugins/xmlbackend/protege_xml_backend.xsd";
sprintf(s2,"\"%s\"",s1);
mn->addHeaders(" xsi:noNamespaceSchemaLocation=", s2);
root.Sons.push_back(mn);
}
void XMLTree::finalizeMain()
{
addSlots(&sn);
OwnSlotsNode* ossn = new OwnSlotsNode;
ossn->addOwnSlot(&ng);
ClassNode* cn = new ClassNode;
cn->addOwnSlots(ossn);
addClasses(cn);
InstanceNode* in = new InstanceNode;
in->addOwnSlots(ossn);
addInstances(in);
MainNode* mn = new MainNode;
mn->headers.push_back(pair<const char*,const char*>("/",XML_SCHEMA_NAME));
root.Sons.push_back(mn);
}
void XMLTree::addHeaders(const char* str, const char*val)
{
MainNode* mn = dynamic_cast<MainNode *>(root.Sons.front());
mn->headers.push_back(pair<const char*,const char*>(str,val));
}
void XMLTree::addSlots(SlotNode* sn)
{
SlotsNode* sn0 = new SlotsNode; // 1 solo
sn0->addSlot(sn);
root.Sons.push_back(sn0);
}
void XMLTree::addClasses(ClassNode* cn)
{
ClassesNode* cn0 = new ClassesNode; // 1 solo
cn0->addClass(cn);
root.Sons.push_back(cn0);
}
void XMLTree::addNode(const char* s, int value_type, const char* name)
{
ValueNode* vn = new ValueNode;
EntryNode* en = new EntryNode;
OwnSlotNode* osn = new OwnSlotNode;
switch(value_type)
{
case VALUE_INTEGER:
en->type = "Integer";
break;
case VALUE_FLOAT:
en->type = "Float";
break;
case VALUE_BOOL:
en->type = "Bool";
break;
case VALUE_STRING:
en->type = "String";
break;
}
vn->setValue(s);
en->addValue(*vn);
osn->setName(name);
osn->addEntry(*en);
sn.addOwnSlot(osn);
ng.addNode(osn);
}
void XMLTree::addInstances(InstanceNode* in)
{
InstancesNode* in0 = new InstancesNode; // 1 solo
in0->addInstance(in);
root.Sons.push_back(in0);
}
void XMLTree::printXMLTree()
{
FILE *fp;
if (filename.empty())
fp = fopen(DEFAULT_NAME, "w");
else
fp = fopen(filename.c_str(), "w");
list<Node*>::iterator it;
list<Node*>::iterator it2;
list<Node*>::iterator it3;
list<pair<const char*,const char*> >::iterator lit;
MainNode* mn;
SlotsNode* sns;
SlotNode* sn;
OwnSlotNode* osn;
ClassesNode* csn;
ClassNode* cn;
InstancesNode* isn;
InstanceNode* in;
int nn = 0;
for(it = root.Sons.begin(); it!=root.Sons.end(); ++it)
{
if (verbose)
{
cout<<"Creating Node #"<< nn<<"\n";
cout<<"Node Type is "<< (*it)->qualifyNode()<<"\n";
}
switch((*it)->qualifyNode())
{
// MAIN NODE
case MAIN_NODE:
mn = dynamic_cast<MainNode *>(*it);
fprintf(fp,"<");
for(lit = mn->headers.begin(); lit!= mn->headers.end(); ++lit)
fprintf(fp,"%s%s", lit->first,lit->second );
fprintf(fp,"> \n");
break;
// SLOTS
case SLOTS_NODE:
sns = dynamic_cast<SlotsNode *>(*it);
fprintf(fp,"\t<slots>\n");
for(it2 = sns->slot.Sons.begin(); it2!=sns->slot.Sons.end(); ++it2)
{
sn = dynamic_cast<SlotNode *>(*it2);
fprintf(fp,"\t\t<slot>\n");
for(it3 = sn->own_slot.Sons.begin(); it3!=sn->own_slot.Sons.end(); ++it3)
{
osn = dynamic_cast<OwnSlotNode *>(*it3);
fprintf(fp,"\t\t\t<own-slot slot-name=\":%s\">\n",osn->name);
fprintf(fp,"\t\t\t\t<entry type=\"%s\">\n",osn->entry.type);
fprintf(fp,"\t\t\t\t\t<value>%s", osn->entry.value.value.c_str());
fprintf(fp,"</value>\n");
fprintf(fp,"\t\t\t\t</entry>\n");
fprintf(fp,"\t\t\t</own-slot>\n");
}
fprintf(fp,"\t\t</slot>\n");
}
fprintf(fp,"\t</slots>\n");
break;
// CLASSES
case CLASSES_NODE:
csn = dynamic_cast<ClassesNode *>(*it);
fprintf(fp,"\t<classes>\n");
for(it2 = csn->classn.Sons.begin(); it2!=csn->classn.Sons.end(); ++it2)
{
cn = dynamic_cast<ClassNode *>(*it2);
fprintf(fp,"\t\t<class>\n");
fprintf(fp,"\t\t\t<own-slots>\n");
for(it3 = cn->own_slots.own_slot.Sons.begin();
it3!=cn->own_slots.own_slot.Sons.end(); ++it3)
{
osn = dynamic_cast<OwnSlotNode *>(*it3);
fprintf(fp,"\t\t\t\t<own-slot slot-name=\":%s\">\n",osn->name);
fprintf(fp,"\t\t\t\t\t<entry type=\"%s\">\n",osn->entry.type);
fprintf(fp,"\t\t\t\t\t\t<value>%s", osn->entry.value.value.c_str());
fprintf(fp,"</value>\n");
fprintf(fp,"\t\t\t\t\t</entry>\n");
fprintf(fp,"\t\t\t\t</own-slot>\n");
}
fprintf(fp,"\t\t\t</own-slots>\n");
fprintf(fp,"\t\t</class>\n");
}
fprintf(fp,"\t</classes>\n");
break;
// INSTANCES
case INSTANCES_NODE:
isn = dynamic_cast<InstancesNode *>(*it);
fprintf(fp,"\t<instances>\n");
for(it2 = isn->instances.Sons.begin(); it2!=isn->instances.Sons.end(); ++it2)
{
in = dynamic_cast<InstanceNode *>(*it2);
fprintf(fp,"\t\t<instance>\n");
fprintf(fp,"\t\t\t<id>\n");
fprintf(fp,"\t\t\t%s\n", in->id);
fprintf(fp,"\t\t\t</id>\n");
fprintf(fp,"\t\t\t<type>\n");
fprintf(fp,"\t\t\t%s\n", in->type);
fprintf(fp,"\t\t\t</type>\n");
fprintf(fp,"\t\t\t<own-slots>\n");
for(it3 = in->own_slots.own_slot.Sons.begin();
it3!=in->own_slots.own_slot.Sons.end(); ++it3)
{
osn = dynamic_cast<OwnSlotNode *>(*it3);
fprintf(fp,"\t\t\t\t<own-slot slot-name=\":%s\">\n",osn->name);
fprintf(fp,"\t\t\t\t\t<entry type=\"%s\">\n",osn->entry.type);
fprintf(fp,"\t\t\t\t\t\t<value>%s", osn->entry.value.value.c_str());
fprintf(fp,"</value>\n");
fprintf(fp,"\t\t\t\t\t</entry>\n");
fprintf(fp,"\t\t\t\t</own-slot>\n");
}
fprintf(fp,"\t\t\t</own-slots>\n");
fprintf(fp,"\t\t</instance>\n");
}
fprintf(fp,"\t</instances>\n");
break;
}
++nn;
}
fclose(fp);
}
@@ -0,0 +1,53 @@
// -----------------------------------------------------------------------------------------------
#ifndef _DEFS_H
#define _DEFS_H
// -----------------------------------------------------------------------------------------------
// command line parameters
#define CMD_LINE_ARG_HIST 'H'
#define CMD_LINE_ARG_VERTEX_SAMPLE 'V'
#define CMD_LINE_ARG_EDGE_SAMPLE 'E'
#define CMD_LINE_ARG_FACE_SAMPLE 'F'
#define CMD_LINE_ARG_SAMPLE_TYPE 'S'
#define CMD_LINE_ARG_MONTECARLO_SAMPLING 'M'
#define CMD_LINE_ARG_SUBDIVISION_SAMPLING 'S'
#define CMD_LINE_ARG_SIMILAR_TRIANGLES_SAMPLING 'T'
#define CMD_LINE_ARG_N_SAMPLES 'N'
#define CMD_LINE_ARG_SAMPLES_PER_AREA_UNIT 'A'
#define CMD_LINE_ARG_SAVE_DISPLACEMENT 'O'
#define CMD_LINE_ARG_SAVE_ERROR_AS_COLOUR 'C'
// error messages
#define MSG_ERR_N_ARGS " Usage:\n\n" \
" trimeshinfo <mesh> [options]\n\n" \
" Options:\n\n" \
" -q Quiet (disable verbose mode that is enabled by default)\n" \
" -x Enable XML output\n" \
" -h Enable HTML output\n" \
" -s <filename> Save the clean mesh\n\n"
#define MSG_ERR_MESH_LOAD "error loading the input meshes.\n"
#define MSG_ERR_INVALID_OPTION "unable to parse option '%s'\n"
#define MSG_ERR_FILE_OPEN "unable to open the output file.'n"
#define MSG_ERR_UNKNOWN_FORMAT "unknown file format '%s'.\n"
// global constants
#define NO_SAMPLES_PER_FACE 10
#define N_SAMPLES_EDGE_TO_FACE_RATIO 0.1
#define BBOX_FACTOR 0.1
#define INFLATE_PERCENTAGE 0.02
#define MIN_SIZE 125 /* 125 = 5^3 */
#define N_HIST_BINS 256
#define PRINT_EVERY_N_ELEMENTS 1000
#define FILE_EXT_SMF "smf"
#define FILE_EXT_PLY "ply"
// strings
#define STR_HIST_FILENAME_DEFAULT "hist.txt"
#define STR_NEW_MESH_FILENAME_DEFAULT "error.ply"
#define STR_NEW_MESH_FILENAME_DEFAULT_2 "error_colour.ply"
// -----------------------------------------------------------------------------------------------
#endif
// -----------------------------------------------------------------------------------------------
@@ -0,0 +1,53 @@
VCGLib http://vcg.sf.net o o
Visual and Computer Graphics Library o o
_ O _
Copyright(C) 2005-2006 \/)\/
Visual Computing Lab http://vcg.isti.cnr.it /\/|
ISTI - Italian National Research Council |
\
TriMeshInfo 1.22 2006/10/30
All rights reserved.
2006/10/30 Release 1.22
Better support of off and obj files.
Now it can parse also slightly incorrect
files reporting warnings without blocking.
2006/03/27 Release 1.21
Now trimeshinfo support OFF,STL,OBJ and PLY format
Added normal, color and texture information
Fix mesh info data initialization
2005/12/21 Release 1.2
Fix orientability and genus computation.
Re-design output (add HTML info support).
2005/09/28 Release 1.02
Added possibility of saving File in OFF format
Changed main file name from main.cpp intp trimeshinfo.cpp to uniform with other projects.
Fixed some errors in counting edges and holes routines.
2005/2/16 Release 1.01
Added new functionality to the application:
- Volume (Computed only for Closed Manifold Datasets)
- Color (Computed only if the information is embedded in the model)
- Genus (Computed only for Manifold Datasets)
- Number of Duplicated Vertices
- Self-Intersection (Currently computed only for Datasets with less than 3M faces)
Modified output layout.
2005/01/19 Release 1.0
First working version.
@@ -0,0 +1,87 @@
VCGLib http://www.vcglib.net o o
Visual and Computer Graphics Library o o
_ O _
Copyright(C) 2004-2006 \/)\/
Visual Computing Lab http://vcg.isti.cnr.it /\/|
ISTI - Italian National Research Council |
\
TriMeshInfo 1.22 2006/10/30
All rights reserved.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License (http://www.gnu.org/licenses/gpl.txt)
for more details.
--- Synopsis ---
TriMeshInfo is a tool designed to inspect 3D models and retrieve all the
topological related information. It can be used to automate the process
of decoding 3D mesh inherent properties and ease data classification
and retrieval.
For each analyzed dataset the following information are extracted:
* Number of Vertices
* Number of Faces
* Number of Edges
* Number of Connected Components
* Number of Boundaries
* Number of Isolated Vertices (i.e. Unreferenced)
* Number of Duplicated vertices (duplicated vertices are referenced vertices
which have the same positon in the space)
* Manifold
* Genus (computed only for Manifold Datasets)
* Self-Intersection (currently computed only for Datasets with less than 3M faces)
* Orientability
* Orientation
* Regularity (We consider REGULAR those meshes that have 6 incident edges
for each internal vertex, and 4 incident edges for each vertex on the
boundary. In all other cases we consider the mesh irregular.)
* Volume
* Attribute present on mesh (colors, texture coords etc);
The application has no graphical interface but works as the "Metro" tool on command line.
TriMeshInfo is written in C++ and makes use of the VCG library.
The tool supports the following file formats:
- PLY
- OFF (http://www.geomview.org/docs/html/geomview_41.html#SEC44)
- STL (http://astronomy.swin.edu.au/~pbourke/dataformats/stl/)
- OBJ (http://www.eg-models.de/formats/Format_Obj.html)
--- Command-line Reference ---
Usage:
TriMeshInfo <mesh> [options]
Valid options are the following:
-q Quiet (disable verbose mode that is enabled by default)
-x Enable XML output
-h Enable HTML output
-s <filename> Save the clean mesh
The HTML output creates in the directory where TriMeshInfo is launched a file
called "result.html". This file contains an hmtl table with the retrieved
mesh information.
If this file is just present in the working directory the output of the TriMeshInfo
is added to the existing table. In this way it is possible to summarize the results
obtained from several meshes.
If you choose to save the "clean" mesh, the mesh without its unreferenced vertices
and with the duplicated vertices merged is saved.
@@ -0,0 +1,870 @@
/****************************************************************************
* VCGLib o o *
* Visual and Computer Graphics Library o o *
* _ O _ *
* Copyright(C) 2005 \/)\/ *
* Visual Computing Lab /\/| *
* ISTI - Italian National Research Council | *
* \ *
* All rights reserved. *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, or *
* (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License (http://www.gnu.org/licenses/gpl.txt) *
* for more details. *
* *
****************************************************************************/
/****************************************************************************
History
$Log: not supported by cvs2svn $
Revision 1.41 2007/03/08 22:49:35 cignoni
Changed the include order and the order in which cleaning filters are applied.
Revision 1.40 2006/05/16 21:55:28 cignoni
Updated to the new remove zero area syntax
Revision 1.39 2006/03/29 09:27:07 cignoni
Added managemnt of non critical errors
Revision 1.38 2006/03/29 08:17:56 corsini
fix typo
Revision 1.37 2006/03/27 07:15:59 cignoni
Added LoadMask
Revision 1.36 2006/02/28 14:54:10 corsini
Fix load mask initialization
Revision 1.35 2006/02/09 16:12:27 corsini
Add normal, color, texture information
Revision 1.34 2006/02/06 12:59:12 corsini
Fix mesh info structure initialization
Revision 1.33 2006/01/27 14:18:07 corsini
fix boolean entry type
Revision 1.32 2006/01/27 14:17:10 corsini
remove junk code
Revision 1.31 2006/01/27 13:35:51 corsini
fix signed/unsigned mismatch
Revision 1.30 2006/01/26 16:29:21 corsini
fix typo
Revision 1.29 2005/12/29 12:27:35 cignoni
Splitted IsComplexManifold in IsTwoManifoldFace and IsTwoManifoldVertex
Revision 1.28 2005/12/21 14:11:59 corsini
Out the number of self intersection
Revision 1.27 2005/12/21 13:26:58 corsini
Re-add save xml feature
Revision 1.26 2005/12/21 13:10:10 corsini
Move duplicated vertices routine
Modify genus computation call
Revision 1.25 2005/12/20 14:44:10 corsini
Modify html table
Revision 1.24 2005/12/20 13:29:41 corsini
Remove unuseful Clear function
Revision 1.23 2005/12/19 15:00:53 corsini
Disable xml output temporarily
Revision 1.22 2005/12/19 11:35:13 corsini
Add html output support
Revision 1.21 2005/12/16 11:16:36 corsini
Add manifold check to some properties
Revision 1.20 2005/12/15 11:20:00 corsini
Add vertex-face topology
Revision 1.19 2005/12/14 14:05:37 corsini
Adjust comments
Revision 1.18 2005/12/14 12:15:37 corsini
Re-add clean mesh saving feature
Revision 1.17 2005/12/13 15:46:30 corsini
Restructuring code
Revision 1.16 2005/12/12 12:09:08 cignoni
Changed names of clean function and tested inertia.h
Revision 1.15 2005/12/12 11:29:21 corsini
Minor changes
Revision 1.14 2005/12/12 10:48:16 corsini
Fix indentation
Revision 1.13 2005/11/17 00:42:03 cignoni
Changed include order
removed clean::initialize
Revision 1.12 2005/11/16 16:45:51 rita_borgo
Minor changes
Revision 1.11 2005/11/16 15:59:46 cignoni
Changed name of the component from <Flag> to <BitFlags>
Revision 1.10 2005/11/14 09:21:07 cignoni
Heavily restructured the code of Trimeshinfo.
Now divided the collecting part from the reporting one (xml and ascii)
Revision 1.9 2005/11/04 15:37:57 rita_borgo
Removed Debug option
Revision 1.8 2005/10/11 16:03:40 rita_borgo
Moved all the main functions inside clean.h
Revision 1.7 2005/09/30 15:48:46 rita_borgo
Fixed manifold Test
Revision 1.6 2005/09/30 14:13:01 rita_borgo
Problem: Text not aligned
Revision 1.5 2005/09/30 13:29:40 rita_borgo
Fixed Manifold Test
Revision 1.4 2005/09/29 14:48:15 rita_borgo
Fixed code related to creation of the XML file
Revision 1.3 2005/09/28 13:57:09 rita_borgo
Fixed some printout not alligned
Revision 1.2 2005/09/28 10:46:04 rita_borgo
Added possibility of saving File in OFF format
Revision 1.1 2005/09/20 10:15:27 rita_borgo
Changed file name to uniform with other solution projects,
before was main.cpp
Revision 1.8 2005/02/15 12:26:06 rita_borgo
Minor changes to self-intersection
Revision 1.7 2005/02/07 15:44:31 rita_borgo
Fixed Color and Volume
Revision 1.6 2005/02/01 17:37:53 rita_borgo
Fixed Volume and Color
Revision 1.5 2005/01/18 16:33:12 rita_borgo
Added OFF file Option
Revision 1.4 2005/01/17 18:19:00 rita_borgo
Added new routines.
Self-intersection first release
Revision 1.2 2005/01/03 16:13:09 rita_borgo
Added Standard comments
****************************************************************************/
// Standard headers
#include <iostream>
#include <fstream>
#include <vector>
#include <string>
#include <stack>
using namespace std;
// VCG headers
#include <vcg/simplex/vertex/base.h>
#include <vcg/simplex/vertex/component.h>
#include <vcg/simplex/face/base.h>
#include <vcg/simplex/face/component.h>
#include <vcg/complex/complex.h>
#include <vcg/complex/algorithms/update/topology.h>
#include <vcg/complex/algorithms/update/edges.h>
#include <vcg/complex/algorithms/update/bounding.h>
#include <vcg/complex/algorithms/update/flag.h>
#include <vcg/complex/algorithms/clean.h>
#include <vcg/space/intersection/triangle_triangle3.h>
#include <vcg/math/histogram.h>
#include <wrap/io_trimesh/import.h>
#include <wrap/io_trimesh/export.h>
#include <vcg/simplex/face/pos.h>
#include <vcg/complex/algorithms/inertia.h>
#include "XMLTree.h"
#include <vcg/space/index/grid_static_ptr.h>
#include "defs.h"
using namespace vcg;
class CVertex;
class CFace;
struct MyTypes: public UsedTypes< Use<CVertex>::AsVertexType,Use<CFace>::AsFaceType>{};
class CVertex : public Vertex< MyTypes, vertex::VFAdj, vertex::Coord3f,vertex::BitFlags, vertex::Normal3f > {};
class CFace : public Face< MyTypes, face::FFAdj, face::VFAdj, face::VertexRef, face::Normal3f, face::BitFlags, face::Mark > {};
class CMesh : public vcg::tri::TriMesh< vector<CVertex>, vector<CFace> > {};
typedef CMesh::VertexPointer VertexPointer;
typedef CMesh::VertexIterator VertexIterator;
typedef Point3<CMesh::ScalarType> Point3x;
typedef vector<Point3x> Hole;
typedef CMesh::VertexPointer VertexPointer;
typedef CMesh::VertexIterator VertexIterator;
typedef CMesh::FaceContainer FaceContainer;
typedef CMesh::ScalarType ScalarType;
struct MeshInfo
{
string FileName;
bool hasVNormal;
bool hasFNormal;
bool hasVColor;
bool hasFColor;
bool hasTexture;
int vn,fn;
bool VManifold;
bool FManifold;
int count_e,boundary_e,count_fd,count_uv,numholes;
int BEdges;
float Volume;
int numcomponents,Genus;
bool Regular,Semiregular;
bool Orientable,Oriented;
int dv;
bool SelfIntersect;
std::vector<CMesh::FaceType *> intersections;
};
static const int HTML_LINES = 31;
static const char * HTML_TABLE[HTML_LINES]=
{
"<html>",
" <head>",
" <meta http-equiv=\"content-type\" content=\"text/html; charset=ISO-8859-1\">",
" <title>description.html</title>",
" </head>",
" <body>",
" <span style=\"font-weight: bold;\"></span>",
" <h2>TriMeshInfo V.1.2 - Results</h2>",
" <hr style=\"width: 100%; height: 2px;\"><br>",
" <table",
" style=\"width: 100%; text-align: center; margin-left: auto; margin-right: auto;\" ",
" border=\"1\" cellpadding=\"2\" cellspacing=\"2\">",
" <tbody>",
" <tr>",
" <td>Name</td>",
" <td>Vertices</td>",
" <td>Faces</td>",
" <td>Edges</td>",
" <td>Holes/<br>Boundaries</td>",
" <td>Connected<br>Components</td>",
" <td>Isolated<br>Vertices</td>",
" <td>Duplicated<br>Vertices</td>",
" <td>Self<br>Interesection</td>",
" <td>Manifold</td>",
" <td>Orientable/<br>Oriented</td>",
" <td>Genus</td>",
" </tr>",
" </tbody>",
" </table>",
" </body>",
"</html>"
};
int OpenMesh(const char *filename, CMesh &m)
{
printf(" Mesh loading...");
int mask = 0;
tri::io::Importer<CMesh>::LoadMask(filename,mask);
int err = tri::io::Importer<CMesh>::Open(m, filename);
if (err)
{
if(tri::io::Importer<CMesh>::ErrorCritical(err))
{
printf("\n Error during loading %s: '%s'\n",filename,
tri::io::Importer<CMesh>::ErrorMsg(err));
exit(-1);
}
else
{
printf("\n Non Critical Troubles during loading %s: '%s'\n",filename,
tri::io::Importer<CMesh>::ErrorMsg(err));
}
}
else
printf(" done.\n\n");
return mask;
}
void initMeshInfo(MeshInfo &mi)
{
mi.vn = 0;
mi.fn = 0;
mi.hasVColor = false;
mi.hasFColor = false;
mi.hasFNormal = false;
mi.hasVNormal = false;
mi.hasTexture = false;
mi.VManifold = false;
mi.FManifold = false;
mi.count_e = 0;
mi.boundary_e = 0;
mi.count_fd = 0;
mi.count_uv = 0;
mi.numholes = 0;
mi.BEdges = 0;
mi.Volume = 0;
mi.numcomponents = 0;
mi.Genus = 0;
mi.Regular = false;
mi.Semiregular = false;
mi.Orientable = false;
mi.Oriented = false;
mi.dv = 0;
mi.SelfIntersect = false;
// mi.FileName has a constructor
// mi.intersections has a constructor
}
void PrintMeshInfo(MeshInfo &mi)
{
printf(" *** Mesh information ***\n\n");
printf(" Mesh: '%s' \n", mi.FileName.c_str());
printf(" Number of vertices: %d \n", mi.vn);
printf(" Number of faces: %d \n", mi.fn);
printf(" Number of edges: %d \n", mi.count_e);
printf(" Number of internal edges: %d \n", mi.count_e-mi.boundary_e);
printf(" Number of boundary edges: %i \n", mi.boundary_e);
printf(" Number of degenerated faces: %d\n", mi.count_fd);
printf(" Number of unreferenced vertices: %d\n",mi.count_uv);
printf(" Number of duplicated vertices found: %d\n", mi.dv);
printf(" Number of holes/boundaries: %d \n", mi.numholes);
if (mi.hasVNormal)
printf(" Has Per-Vertex Normal: YES\n");
else
printf(" Has Per-Vertex Normal: NO\n");
if (mi.hasFNormal)
printf(" Has Per-Face Normal: YES\n");
else
printf(" Has Per-Face Normal: NO\n");
if (mi.hasVColor)
printf(" Has Per-Vertex Color: YES\n");
else
printf(" Has Per-Vertex Color: NO\n");
if (mi.hasFColor)
printf(" Has Per-Face Color: YES\n");
else
printf(" Has Per-Face Color: NO\n");
if (mi.hasTexture)
printf(" Has Texture information: YES\n");
else
printf(" Has Texture information: NO\n");
if ((mi.VManifold && mi.FManifold )&&(mi.Oriented)&&(!mi.numholes))
printf(" Volume: %f \n", mi.Volume);
else
printf(" Volume: UNDEFINED (a closed oriented manifold is required)\n");
printf(" Number of connected components: %d\n", mi.numcomponents);
// Orientation
if (!mi.VManifold && mi.FManifold)
{
printf(" Orientable Mesh: NO\n");
printf(" Oriented Mesh: NO\n");
}
else
{
if (mi.Orientable)
printf(" Orientable Mesh: YES\n");
else
printf(" Orientable Mesh: NO\n");
if (mi.Oriented)
printf(" Oriented Mesh: YES\n");
else
printf(" Oriented Mesh: NO\n");
}
// Manifold
if (mi.VManifold && mi.FManifold )
printf(" Manifold: YES\n");
else
printf(" Manifold: NO\n");
// Genus
if (mi.VManifold && mi.FManifold)
printf(" Genus: %d \n", mi.Genus);
else
printf(" Genus: N/A \n");
// Mesh Type
if (mi.Regular)
printf(" Mesh Type: REGULAR\n");
else if (mi.Semiregular)
printf(" Mesh Type: SEMIREGULAR\n");
else
printf(" Mesh Type: IRREGULAR\n");
// Further details
if (mi.SelfIntersect)
printf(" Self Intersection: %d\n", mi.intersections.size());
else
printf(" Self Intersection: NONE.\n");
}
void SaveXMLInfo(MeshInfo &mi)
{
XMLTree doc;
doc.initializeMain();
char s[256];
sprintf(s,"%d",mi.vn);
doc.addNode(s, VALUE_INTEGER, "Number of Vertices");
sprintf(s,"%d",mi.fn);
doc.addNode(s, VALUE_INTEGER, "Number of Faces");
if(mi.VManifold && mi.FManifold)
doc.addNode("false", VALUE_BOOL,"Manifold");
else
doc.addNode("true", VALUE_BOOL,"Manifold");
sprintf(s,"%d",mi.count_e);
doc.addNode(s, VALUE_INTEGER,"Number of Edges");
sprintf(s,"%d",mi.count_fd);
doc.addNode(s, VALUE_INTEGER,"Number of Degenerated Faces");
sprintf(s,"%d",mi.count_uv);
doc.addNode(s, VALUE_INTEGER,"Number of unreferenced vertices");
sprintf(s,"%d",mi.numholes);
doc.addNode(s, VALUE_INTEGER, "Number of Holes");
sprintf(s,"%d",mi.BEdges);
doc.addNode(s, VALUE_INTEGER, "Number of Border Edges");
if (mi.hasVColor)
doc.addNode("true", VALUE_BOOL, "Per-Vertex Color Information");
else
doc.addNode("false", VALUE_BOOL, "Per-Vertex Color Information");
if (mi.hasFColor)
doc.addNode("true", VALUE_BOOL, "Per-Face Color Information");
else
doc.addNode("false", VALUE_BOOL, "Per-Face Color Information");
if (mi.hasVNormal)
doc.addNode("true", VALUE_BOOL, "Per-Vertex Normal");
else
doc.addNode("false", VALUE_BOOL, "Per-Vertex Normal");
if (mi.hasFNormal)
doc.addNode("true", VALUE_BOOL, "Per-Face Normal");
else
doc.addNode("false", VALUE_BOOL, "Per-Face Normal");
if (mi.hasTexture)
doc.addNode("true", VALUE_BOOL, "Texture Information");
else
doc.addNode("false", VALUE_BOOL, "Texture Information");
sprintf(s,"%f",mi.Volume);
doc.addNode(s, VALUE_FLOAT,"Volume");
sprintf(s,"%d",mi.numcomponents);
doc.addNode(s, VALUE_INTEGER,"Number of Connected Components");
sprintf(s,"%d",mi.Genus);
doc.addNode(s, VALUE_INTEGER,"Genus");
if (mi.Regular)
doc.addNode("REGULAR", VALUE_STRING,"Type of Mesh");
else if (mi.Semiregular)
doc.addNode("SEMIREGULAR", VALUE_STRING,"Type of Mesh");
else
doc.addNode("IRREGULAR", VALUE_STRING,"Type of Mesh");
if (!mi.VManifold && mi.FManifold)
{
doc.addNode("NO", VALUE_STRING,"Orientable Mesh");
doc.addNode("NO", VALUE_STRING,"Oriented Mesh");
}
else
{
doc.addNode(mi.Orientable?"Yes":"No", VALUE_STRING,"Orientable Mesh");
doc.addNode(mi.Oriented?"Yes":"No", VALUE_STRING,"Oriented Mesh");
}
sprintf(s,"%d",mi.dv);
doc.addNode(s, VALUE_INTEGER,"Duplicated Vertices");
doc.addNode(mi.SelfIntersect?"Yes":"No", VALUE_STRING,"Self Intersection");
doc.finalizeMain();
// save xml tree
string filename = mi.FileName;
int l = static_cast<int>(filename.size());
int index = static_cast<int>(filename.find_first_of('.'));
filename.erase(index, l - index);
filename.append(".xml");
doc.setName(filename.c_str());
doc.printXMLTree();
}
void SaveMeshInfoHtmlTable(fstream &fout, MeshInfo &mi)
{
fout << " <tr>" << std::endl;
fout << " <td>" << mi.FileName << "</td>" << std::endl;
fout << " <td>" << mi.vn << "</td>" << std::endl;
fout << " <td>" << mi.fn << "</td>" << std::endl;
fout << " <td>" << mi.count_e << "</td>" << std::endl;
if (mi.VManifold && mi.FManifold)
fout << " <td>" << mi.numholes << "</td>" << std::endl;
else
fout << " <td>N/A</td>" << std::endl;
fout << " <td>" << mi.numcomponents << "</td>" << std::endl;
fout << " <td>" << mi.count_uv << "</td>" << std::endl;
fout << " <td>" << mi.dv << "</td>" << std::endl;
if (mi.SelfIntersect)
fout << " <td>" << static_cast<unsigned int>(mi.intersections.size())
<< "</td>" << std::endl;
else
fout << " <td>None</td>" << std::endl;
if(mi.VManifold && mi.FManifold)
fout << " <td>Yes</td>" << std::endl;
else
fout << " <td>No</td>" << std::endl;
if ((mi.Orientable)&&(mi.Oriented))
fout << " <td>Yes / Yes</td>" << std::endl;
else if ((mi.Orientable)&&(!mi.Oriented))
fout << " <td>Yes / No</td>" << std::endl;
else if (!mi.Orientable)
fout << " <td>No / No</td>" << std::endl;
if (mi.VManifold && mi.FManifold)
fout << " <td>" << mi.Genus << "</td>" << std::endl;
else
fout << " <td>N/A</td>" << std::endl;
fout << " </tr>" << std::endl;
}
void SaveHtmlInfo(MeshInfo &mi)
{
char buff[1024];
bool flagInsert = false;
ifstream fin;
fstream fout;
// Try to open
fin.open("result.html");
long pos;
if (fin.is_open())
{
while (!fin.eof())
{
pos = fin.tellg();
fin.getline(buff, 1024);
string str(buff);
if (str == " </tbody>")
break;
}
flagInsert = true;
}
fin.close();
if (flagInsert)
fout.open("result.html", ios::in | ios::out);
else
fout.open("result.html", ios::out);
if (!fout.is_open())
{
printf("\n Impossible to write the HTML output file.\n");
}
else
{
if (flagInsert)
{
// Insert the mesh information into an existing table
fout.seekp(pos, ios::beg);
SaveMeshInfoHtmlTable(fout, mi);
for (int i = HTML_LINES - 4; i < HTML_LINES; i++)
fout << HTML_TABLE[i] << std::endl;
}
else
{
// Create a new table
for (int i = 0; i < HTML_LINES - 4; i++)
fout << HTML_TABLE[i] << std::endl;
SaveMeshInfoHtmlTable(fout, mi);
for (int i = HTML_LINES - 4; i < HTML_LINES; i++)
fout << HTML_TABLE[i] << std::endl;
}
}
fout.close();
}
int main(int argc, char ** argv)
{
CMesh m;
bool saveCleanMeshFlag = false; // Save the clean mesh
bool verboseFlag = true; // Verbose mode on/off
bool XmlFlag= false; // XML output enabled/disabled
bool HtmlFlag = false; // HTML output enabled/disabled
string SaveName;
MeshInfo mi;
initMeshInfo(mi);
printf("\n -------------------------------\n"
" TriMeshInfo V.1.23 \n"
" http://vcg.isti.cnr.it\n"
" release date: "__DATE__"\n"
" -------------------------------\n\n\n");
// Parsing arguments
///////////////////////////////////////////////
if (argc <= 1)
{
printf(MSG_ERR_N_ARGS);
exit(-1);
}
mi.FileName = argv[1];
int i = 2;
while (i < argc)
{
if (argv[i][0] == '-')
{
switch(argv[i][1])
{
case 'q' :
// Quiet mode, disable verbose mode
verboseFlag = false;
break;
case 's':
// Save the clean mesh with the name specified
saveCleanMeshFlag = true;
// Check clean mesh name (minimal check)
if (i+1 >= argc)
{
printf(" Invalid output mesh name.\n\n");
exit(-1);
}
else if (argv[i+1][0] != '-')
SaveName = argv[i+1];
else
{
printf(" Invalid output mesh name.\n\n");
exit(-1);
}
i++;
break;
case 'x' :
// Enable XML output
XmlFlag = true;
break;
case 'h' :
// Enable HTML output
HtmlFlag = true;
break;
default:
printf(MSG_ERR_INVALID_OPTION, argv[i]);
exit(0);
break;
}
}
i++;
};
// Mesh loading
//////////////////////////////////////////
int load_mask = OpenMesh(mi.FileName.c_str(), m);
if (load_mask & vcg::tri::io::Mask::IOM_VERTNORMAL)
mi.hasVNormal = true;
else
mi.hasVNormal = false;
if (load_mask & vcg::tri::io::Mask::IOM_FACENORMAL)
mi.hasFNormal = true;
else
mi.hasFNormal = false;
if (load_mask & vcg::tri::io::Mask::IOM_VERTCOLOR)
mi.hasVColor = true;
else
mi.hasVColor = false;
if (load_mask & vcg::tri::io::Mask::IOM_FACECOLOR)
mi.hasFColor = true;
else
mi.hasFColor = false;
if( (load_mask & vcg::tri::io::Mask::IOM_VERTTEXCOORD) ||
(load_mask & vcg::tri::io::Mask::IOM_WEDGTEXCOORD) )
mi.hasTexture = true;
else
mi.hasTexture = false;
// Mesh processing
//////////////////////////////////////////
printf(" Mesh processing...\n\n");
// Number of vertices
mi.vn = m.vn;
// Number of faces
mi.fn = m.fn;
// DUPLICATED VERTICES
mi.dv = tri::Clean<CMesh>::RemoveDuplicateVertex(m);
// DEGENERATED FACES => (faces with area zero)
mi.count_fd = tri::Clean<CMesh>::RemoveDegenerateFace(m);
mi.count_fd += tri::Clean<CMesh>::RemoveFaceOutOfRangeArea<false>(m,0);
// UNREFERENCED VERTEX
mi.count_uv = tri::Clean<CMesh>::RemoveUnreferencedVertex(m);
// Update topology (face-to-face)
tri::UpdateTopology<CMesh>::FaceFace(m);
tri::UpdateTopology<CMesh>::VertexFace(m);
// IS MANIFOLD?
mi.VManifold = tri::Clean<CMesh>::CountNonManifoldVertexFF(m)>0;
mi.FManifold = tri::Clean<CMesh>::CountNonManifoldEdgeFF(m)>0;
// COUNT EDGES
tri::Clean<CMesh>::CountEdges(m, mi.count_e, mi.boundary_e);
// HOLES COUNT
if(mi.VManifold && mi.FManifold)
{
mi.numholes = tri::Clean<CMesh>::CountHoles(m);
tri::Clean<CMesh>::CountEdges(m, mi.BEdges,mi.numholes);
}
// CONNECTED COMPONENTS
mi.numcomponents = tri::Clean<CMesh>::CountConnectedComponents(m);
// ORIENTATION
if (mi.VManifold && mi.FManifold)
tri::Clean<CMesh>::IsOrientedMesh(m, mi.Oriented, mi.Orientable);
else
{
mi.Oriented = false;
mi.Orientable = false;
}
// Rebuild Vertex-Face topology
tri::UpdateTopology<CMesh>::VertexFace(m);
// VOLUME (require a closed oriented manifold)
if ((mi.VManifold && mi.FManifold)&&(mi.Oriented)&&(!mi.numholes))
{
tri::Inertia<CMesh> mm;
mm.Compute(m);
mi.Volume = mm.Mass();
// the sign of the volume depend on the mesh orientation
if (mi.Volume < 0.0)
mi.Volume = -mi.Volume;
}
// GENUS
if(mi.VManifold && mi.FManifold)
mi.Genus = tri::Clean<CMesh>::MeshGenus(m, mi.numholes,
mi.numcomponents, mi.count_e);
// REGULARITY
if (mi.VManifold && mi.FManifold)
tri::Clean<CMesh>::IsRegularMesh(m, mi.Regular, mi.Semiregular);
else
{
mi.Regular = false;
mi.Semiregular = false;
}
// SELF INTERSECTION
mi.SelfIntersect = tri::Clean<CMesh>::SelfIntersections(m, mi.intersections);
// Mesh Information Output
//////////////////////////////////////////
// Print mesh information
if(verboseFlag)
PrintMeshInfo(mi);
// Save mesh information in XML format
if(XmlFlag)
SaveXMLInfo(mi);
// Save mesh information in HTML format
if (HtmlFlag)
SaveHtmlInfo(mi);
// Save the clean mesh
if (saveCleanMeshFlag)
{
printf(" Save the 'clean' mesh...");
tri::io::Exporter<CMesh>::Save(m, SaveName.c_str());
printf(" done.\n\n");
}
mi.intersections.clear();
return 0;
}
@@ -0,0 +1,9 @@
TARGET = trimeshinfo
LIBPATH +=
DEPENDPATH += .
INCLUDEPATH += . ../..
CONFIG += console stl
TEMPLATE = app
HEADERS +=
SOURCES += trimeshinfo.cpp ../../wrap/ply/plylib.cpp