27 : m_TimeStamp(0), m_Dataset(_dataset), m_Sensors(sensors),
28 m_Flags(0), m_PCFlags(PC_NOTHING), m_InstCount(1), m_HLNode(-1), m_ID(0)
52 if(&rhs ==
this)
return *
this;
58 for(EdgeArray::iterator e=
edges.begin(); e!=
edges.end(); e++)
60 e->setNodesList(
nodes);
90 std::dynamic_pointer_cast<Sensor>(
91 std::const_pointer_cast<Dataset>(dataset)));
127 int index =
nodes.size();
129 nodes.push_back(node);
131 nodes[index].index = index;
132 assert(
nodes[index].index == index);
140 int index =
edges.size();
141 edges.push_back(edge);
142 edges[index].index = index;
144 edges[index].fromNode().edges.push_back(index+1);
145 edges[index].toNode().edges.push_back(-index-1);
163 (
dword)ito<
nodes.size() && ifrom>=0 && ito>=0);
179 int size =
nodes.size();
180 if(from<0 || from>size-1)
throw new IOException(
"Edge is made of node indices that don't exist.");
183 if(to<0 || to>size-1)
throw new IOException(
"Edge is made of node indices that don't exist.");
189 else if(param ==
"dc")
191 else if(param ==
"rl")
193 else if(param ==
"es") {
200 throw new IOException(
"error reading edge parameter [es]");
204 throw new IOException(
"error reading edge parameters");
230 throw new IOException(
"tried to load undefined sensor");
232 }
else if(param ==
"m")
236 throw new IOException(
"error reading node parameters");
247 if(is.
getKey() ==
"sensors") {
252 }
else cerr <<
"couldn't load sensor file " 273 if(pname ==
"mass") {
275 }
else if(pname ==
"springconst") {
277 }
else if(pname ==
"grav") {
279 }
else if(pname ==
"viscousdrag") {
281 }
else if(pname ==
"damping") {
283 }
else if(pname ==
"imageforce") {
285 }
else if(pname ==
"torque") {
287 }
else if(pname ==
"name") {
291 }
else if(pname ==
"ppmm") {
293 }
else if(pname ==
"dirnode") {
321 if(phase == 3 && !is.
eof()) {
323 throw new IOException(
"Error reading model file.");
330 sprintf(msg,
"%s (interpreted line %i)", omsg, is.
getLineNumber());
340 os <<
"p name " << g.
m_Name << endl;
342 os <<
"p ppmm " << g.
m_ppmm << endl;
352 for(NodeArray::const_iterator n = g.
nodes.begin(); n != g.
nodes.end();
357 for(NodeArray::const_iterator n = g.
nodes.begin(); n != g.
nodes.end(); n++)
360 for(EdgeArray::const_iterator e = g.
edges.begin(); e != g.
edges.end(); e++)
372 cerr <<
"IOException: " << e->
getMessage() << endl
373 <<
"reading file " << filename << endl;
383 ofstream os(filename);
386 os <<
"# file '" << filename <<
"' "<<endl;
387 ParticleParam::global =
phys;
390 cerr <<
"IOException: " << e->
getMessage() << endl
391 <<
"writing file " << filename << endl;
418 for(EdgeArray::const_iterator e=
edges.begin(); e!=
edges.end(); e++)
421 adjm.
at(e->from, e->to)++;
435 for(NodeArray::const_iterator n =
nodes.begin(); n !=
nodes.end(); n++)
437 selmr.
setRow(n->getIndex());
438 selmc.
setCol(n->getIndex());
451 EdgeArray::iterator e=
edges.begin();
452 while(e!=
edges.end()) {
454 if(e->from > e->to) { from = e->from; to = e->to; }
455 else { from = e->to; to = e->from; }
457 if(adjm.
at(from, to)>0.0001) {
474 if(adjm.
at(i,j)>0.0001) {
511 EdgeArray::iterator e=
edges.begin();
512 while(e!=
edges.end()) {
513 if(e->to == nid || e->from == nid)
edges.erase(e);
515 if(e->to > nid) e->to--;
516 if(e->from > nid) e->from--;
530 for(NodeArray::iterator n=
nodes.begin(); n!=
nodes.end(); n++,idx++) {
535 for(EdgeArray::iterator e=
edges.begin(); e!=
edges.end(); e++, idx++) {
537 e->fromNode().edges.push_back(e->index+1);
538 e->toNode().edges.push_back(-e->index-1);
545 for(EdgeArray::const_iterator e=
edges.begin(); e!=
edges.end(); e++)
547 e->fromNode().glVertex();
548 e->toNode().glVertex();
552 if(drawPoints && !
nodes.empty()) {
554 glEnable(GL_POINT_SMOOTH);
557 for(NodeArray::const_iterator n=
nodes.begin(); n!=
nodes.end(); n++)
562 glDisable(GL_POINT_SMOOTH);
564 for(NodeArray::const_iterator n=
nodes.begin(); n!=
nodes.end(); n++)
566 if(n->hasState()) n->draw();
606 if(n.
edges.size()>=2) {
607 int eind1 = n.
edges[0];
609 int eind2 = n.
edges[1];
617 for (NodeArray::iterator p=
nodes.begin(); p!=
nodes.end();p++) {
625 if(smpdist < 0.000001)
return 0;
627 for(EdgeArray::iterator e=
edges.begin(); e!=
edges.end(); e++)
629 if(e->fromNode().sensor == e->toNode().sensor && e->fromNode().sensor)
631 nsens += (e->edgesensor = (int)(e->length()/smpdist));
643 for (NodeArray::iterator p=
nodes.begin(); p!=
nodes.end();p++) {
650 Point down(0.0f, -1.0f);
662 for (NodeArray::iterator p=
nodes.begin(); p!=
nodes.end();p++) {
677 for (EdgeArray::iterator s=
edges.begin(); s!=
edges.end(); s++)
679 Point d = s->fromNode();
681 float len = d.
norm();
684 f = (s->springconstant * (len - s->restlength));
686 Point vd(s->fromNode().v);
691 vd *= s->dampingconstant;
696 s->fromNode().f += f;
705 for (NodeArray::iterator p=
nodes.begin(); p!=
nodes.end();p++) {
714 for(NodeArray::iterator p=
nodes.begin(); p!=
nodes.end();p++) {
724 for(NodeArray::iterator p=
nodes.begin(); p!=
nodes.end();p++) {
725 if(!p->edges.empty()) {
729 int eind = p->edges[0];
755 if(
nodes.empty())
return;
759 std::vector<NodeDerivative> m_Deriv(
getNNodes());
764 vector<NodeDerivative>::iterator d=m_Deriv.begin();
765 for (NodeArray::iterator n=
nodes.begin();
766 n !=
nodes.end(), d != m_Deriv.end(); n++, d++) {
768 n->v += (d->dvdt*dt);
775 std::vector<NodeDerivative> m_Deriv(
getNNodes());
781 for (i=0;i<(int)
nodes.size();i++) {
782 nodes[i] += (m_Deriv[i].dpdt * (dt * 0.5));
783 nodes[i].v += (m_Deriv[i].dvdt * (dt * 0.5));
785 vector<NodeDerivative> deriv2(
getNNodes());
790 for (i=0;i<(int)
nodes.size();i++) {
791 nodes[i].setPos(ptmp[i]+
792 ((m_Deriv[i].dpdt+deriv2[i].dpdt)* (0.5*dt)));
793 nodes[i].v = ptmp[i].v+
794 ((m_Deriv[i].dvdt+deriv2[i].dvdt)*(0.5*dt));
808 std::vector<NodeDerivative> m_Deriv(
getNNodes());
810 vector<NodeDerivative> deriv(
getNNodes());
815 if(m_LastDT == 0 || deriv.size() != m_Deriv.size()) {
822 float wlast = dt - wnow;
824 for (i=0;i<(int)
nodes.size();i++) {
825 nodes[i] += (m_Deriv[i].dpdt*wlast+deriv[i].dpdt*wnow);
826 nodes[i].v += (m_Deriv[i].dvdt*wlast+deriv[i].dvdt*wnow);
841 deriv.resize(
nodes.size());
842 vector<NodeDerivative>::iterator d = deriv.begin();
843 for (NodeArray::iterator n =
nodes.begin();
844 d != deriv.end(), n !=
nodes.end();
848 d->dvdt *= (1/n->mass);
856 for (NodeArray::const_iterator n =
nodes.begin();
862 c *= (1.0f/
nodes.size());
871 static const Node dummy;
877 for(NodeArray::const_iterator n=
nodes.begin();
878 n!=
nodes.end(); n++, cind++)
880 float dist = (*n-c).norm2();
909 for(NodeArray::iterator n =
nodes.begin(); n !=
nodes.end(); n++) {
911 for(vector<int>::const_iterator edi=n->edges.begin();
912 edi!=n->edges.end(); edi++) {
913 float elen =
edges[
abs(*edi)-1].length();
914 if(minlen==-1) minlen = elen;
915 else if(minlen>elen) minlen=elen;
925 for(NodeArray::iterator n =
nodes.begin(); n !=
nodes.end(); n++) {
933 for(NodeArray::iterator n =
nodes.begin(); n !=
nodes.end(); n++) {
940 for(EdgeArray::iterator e =
edges.begin(); e !=
edges.end(); e++) {
941 e->adaptRestLength();
948 for(NodeArray::iterator n =
nodes.begin(); n !=
nodes.end(); n++) {
956 for(NodeArray::iterator n =
nodes.begin(); n !=
nodes.end(); n++) {
957 n->ef += (*n-c).flipOrtho().copyNormalized()*angle;
963 for(NodeArray::iterator n =
nodes.begin(); n !=
nodes.end(); n++) {
964 n->ef -= (*n-c)*factor;
969 float lengths=0,restlengths=0;
970 for(EdgeArray::const_iterator e =
edges.begin(); e !=
edges.end(); e++) {
971 lengths+=e->length();
972 restlengths+=e->restlength;
974 return lengths/restlengths;
975 #ifdef NOTLENGTHWEIGHTED 977 for(EdgeArray::const_iterator e =
edges.begin(); e !=
edges.end(); e++) {
978 lenrat += e->lengthRatio();
980 return lenrat/(float)
edges.size();
985 float vlengths=0,restlengths=0;
986 for(EdgeArray::const_iterator e =
edges.begin(); e !=
edges.end(); e++) {
987 register float dl = e->restlength-e->length();
989 restlengths+=e->restlength;
991 register float n =
edges.size();
992 return sqrt(vlengths*n)/(restlengths);
996 if(
edges.empty())
return 0.0;
997 float vlengths=0,restlengths=0;
999 float scscale = 1/ParticleParam::global.
springconst;
1000 for(EdgeArray::const_iterator e =
edges.begin(); e !=
edges.end(); e++) {
1001 register float dl = e->restlength-e->length()*
scale;
1004 restlengths+=e->restlength;
1006 register float n =
edges.size();
1007 return sqrt(vlengths*n)/(restlengths);
1012 for(EdgeArray::const_iterator e =
edges.begin(); e !=
edges.end(); e++) {
1013 length += e->length();
1021 if(!
nodes.empty()) {
1022 for(NodeArray::const_iterator n =
nodes.begin(); n !=
nodes.end(); n++)
1023 dist += (*n-center).norm2();
1024 dist /= (float)
nodes.size();
1033 if(
nodes.empty())
return 0;
1035 for(NodeArray::const_iterator n =
nodes.begin(); n !=
nodes.end(); n++) {
1036 register float td = (*n-center).norm2();
1037 if(dist<td) dist=td;
1053 + scaledist*scaledist);
1062 prop[2] = sd.
x; prop[3] = sd.
y;
1063 rhsprop[2] = rhssd.
x; rhsprop[3] = rhssd.
y;
1064 return (prop - rhsprop).norm();
1069 return std::numeric_limits<float>::max();
1072 for(NodeArray::const_iterator thisn =
nodes.begin(),
1073 rhsn = rhs.
nodes.begin();
1074 thisn !=
nodes.end(); thisn++, rhsn++)
1076 dist += (*thisn-*rhsn).norm2();
1085 return std::numeric_limits<float>::max();
1087 for(NodeArray::const_iterator thisn =
nodes.begin();
1088 thisn !=
nodes.end(); thisn++)
1090 float mindist = std::numeric_limits<float>::max();
1091 for(NodeArray::const_iterator rhsn = rhs.
nodes.begin();
1092 rhsn != rhs.
nodes.end(); rhsn++)
1094 register float d = (*thisn-*rhsn).norm2();
1095 if(d<mindist) mindist = d;
1097 if(kind ==
DIST_HPOINTS && mindist>dist) dist=(double)mindist;
1110 if(
nodes.empty())
return -1;
1113 float& mindist = &dist ? dist : tdist;
1115 mindist = std::numeric_limits<float>::max();
1116 for(NodeArray::const_iterator ni =
nodes.begin();
1117 ni !=
nodes.end(); ni++, cid++)
1119 register float d = (pos-*ni).norm2();
1120 if(d<mindist) { mindist = d; rid = cid; }
1122 mindist =
sqrt(mindist);
1128 for(EdgeArray::iterator e =
edges.begin(); e !=
edges.end(); e++) {
1129 e->adaptRestLength(ratio);
1135 for(EdgeArray::iterator e =
edges.begin(); e !=
edges.end(); e++) {
1136 e->adaptRestLength(ratio);
1142 for(EdgeArray::iterator e =
edges.begin(); e !=
edges.end(); e++) {
1143 e->restlength*=factor;
1147 for(NodeArray::iterator n =
nodes.begin();
1148 n !=
nodes.end(); n++)
1150 n->setPos(center + ((*n-center)*factor));
1158 for(EdgeArray::iterator e =
edges.begin(); e !=
edges.end(); e++) {
1159 if(selm.
at(e->from, e->to) > 0.001)
1160 e->restlength*=factor;
1167 corrat -= (corrat-1)*(1-ratio);
1168 for(EdgeArray::iterator e =
edges.begin(); e !=
edges.end(); e++) {
1169 e->restlength *= corrat;
1175 if(
nodes.empty()) {
if(npts) *npts = 0;
return 0.0; }
1178 for(NodeArray::const_iterator n =
nodes.begin(); n !=
nodes.end(); n++)
1180 float i=n->sensor->getWeightedValue((
int)n->x,(
int)n->y);
1186 if(nsns) fit /= (float)nsns;
1187 if(npts) *npts = nsns;
1193 if(
edges.empty()) {
if(npts) *npts = 0;
return 0.0; }
1196 for(EdgeArray::const_iterator e =
edges.begin(); e !=
edges.end(); e++) {
1197 float i=e->getSensorValue(fit, npoints);
1199 if(npoints) fit /= (float)npoints;
1200 if(npts) *npts = npoints;
1213 m_QOF = (es*nes+ns*nns)/
float(nns+nes);
1229 for(NodeArray::const_iterator n =
nodes.begin(); n !=
nodes.end(); n++)
1232 dist += (c-*n).norm2();
1243 if(!(ppmm =
m_Dataset->getPPMM()))
return;
1250 if(
nodes.empty())
return;
1258 if(nscale>0.001 && cscale>0.0000001)
1259 scale(nscale/cscale,
true);
1317 bool mergeID =
false;
1320 mergeID = mergemod.
m_ID != 0;
1321 }
else mergeID = (
m_ID==0 && mergemod.
m_ID != 0);
1337 for(NodeArray::const_iterator n =
nodes.begin(); n !=
nodes.end(); n++)
1338 if(n->hasState(state)) count++;
void clearPrintList(bool skipdefaults=true)
float getLiveliness() const
static ParticleParam global
bool writeFile(const char *filename) const
PropVec & convertPropFromMM(PropVec &prop) const
const std::string & getFilename() const
float getQualityOfFit() const
void attachSensor(sensor_cptr _sensor)
PropVec & convertPropToMM(PropVec &prop) const
void attachDataset(dataset_cptr dataset)
void rotate(float angle, const Point &c)
Implements a Node used by Model and Edge.
void calculateForces(float dt)
float getEdgeSensorFit(dword *npts=NULL) const
get average fit of sensors along edges
void mergeSensorCollection(SensorCollection *sensors)
friend ParseFile & operator>>(ParseFile &is, Model &g)
PropVec getPropertiesMM() const
return property vector using millimeter scale
const PropVec & getProperties() const
float getStdRadius(const Point ¢er) const
Returns mean squared distance from centroid.
void pushRotate(const Point &c, float angle)
bool readSensor(ParseFile &is)
read sensor from stream
void adaptDataScale(dword ppmm=0)
std::vector< Node > NodeArray
void setHLNode(int hlnode)
void adaptProportion(float ratio)
overall rest lengths sum is adapted to overall edge lengths by ratio
Point2D getPropPos(const PropVec &prop)
const Node & getDirNode() const
void calculateDerivatives(std::vector< NodeDerivative > &deriv)
dword createEdgeSensors(float dist=0.1)
auto-create appropriate edge sensors (dist*stdRadius is distance)
void rebuildIndexTables()
rebuild cross indexing between nodes and edges
float dampingconstant
damping constant
float getDirection() const
Implements an Edge with spring functionality.
dword createByAdjMat(const DMatrixf &adjm)
create edges mentioned in adjacency matrix
ParticleParam phys
physical parameter set
float getPropScale(const PropVec &prop)
std::shared_ptr< const Dataset > dataset_cptr
float norm() const
returns 2-norm aka length or absolute
std::shared_ptr< Sensor > sensor_ptr
Model(dataset_cptr _dataset=NULL, SensorCollection *sensors=NULL)
Default constructor.
void disableState(dword nstate=0xffffffff)
void scale(float factor, bool movepoints=false)
multiply all rest lengths by factor
void refModel(Model *model) const
dword connectNodes()
Connect selected nodes.
int nearestNode(const Point &pos, float &dist=*(float *)(NULL)) const
void adaptRestLength(float ratio)
adapt restlengths towards current lengths by ratio
sensor_ptr getSensor(const std::string &id)
const std::string & getValue() const
float mapAngle2PI(float a)
sensor_ptr getZeroSensor()
void attachSensorColl(SensorCollection *sc)
set reference to and from sensor collection for correct updates
SensorCollection * m_Sensors
int edgesensor
0-none, >0-use from sensor n times, <0 use to sensor
unsigned short CRC(const unsigned char *Data, unsigned int Length)
const Point getCenter() const
float getSensorFit(dword *npts=NULL) const
get average sensor value
PropVec & setPropDir(PropVec &prop, float dir)
int index
Index in the list (Model.nodes)
float getFullLength() const
Returns overall sum of edge lengths.
void reattachSensors()
get sensors from sensor collection
void attract(const Point &c, float factor)
PropVec & setPropPos(PropVec &prop, const Point2D &p)
float springconstant
spring constant
float normalize()
normalizes the vector; returns old norm
dword mergeModel(Model &mergemod)
float getStdRadius() const
float getPropDir(const PropVec &prop)
float angle(const Point2D &rhs=Point2D(1, 0)) const
EdgeArray edges
indexed list of edges
const std::string & getPath() const
const std::string & getKey() const
DMatrix< T > & abs(DMatrix< T > &mat)
dword removeEdges()
Remove edges between selected nodes.
int addNode(const Node &node)
Point2D & convertPointToMM(Point2D &pt) const
const Node & getNode(int index) const
const char * getMessage() const
int m_ParaSolver
method for solving ODE, 0-gauss, 1-midpnt
float getNodeAngle(const Node &n) const
NodeArray nodes
indexed list of nodes
void setName(const std::string &name)
const Point2D rotate(float angle) const
void reset()
reset all model information (including geometry)
float getLengthRatio() const
relation of overall edge length by overall rest length sum
float addImageForces(float dt)
friend std::ostream & operator<<(std::ostream &is, const Model &g)
dword getSelectedNodesN(dword state=Node::ST_SELECT) const
get number of selected nodes
SearcherParams & getSearchPara()
void unrefModel(Model *model) const
void adaptRestLengthSel(float ratio, const DMatrixf &selm)
adapt restlengths of selected edges towards current lengths by ratio
void adaptProperties(const PropVec &prop)
void adaptPropertiesMM(PropVec prop)
adapt to a property vector using millimeter scale
void translate(const Point &t)
const Point2D flipOrtho() const
void draw(bool drawPoints=false) const
Draw using OpenGL.
bool readNode(ParseFile &is)
read node from stream
bool readParameter(ParseFile &is)
read model parameters
int addEdge(const Edge &edge)
void removeNode(int nid)
Removes a node and its adjacent edges.
DMatrixf adjMat() const
compute undirected adjacency matrix
float distance(const Model &rhs, enum Model::DistType kind=DIST_POINTS) const
void updateParticles(float dt, int method=0)
bool hasFlags(dword flags) const
void setParseError(const std::string &msg="")
Point2D getPropSDir(const PropVec &prop)
float getLengthVariation() const
mean squared difference from restlength normalized by restlength sum
Model & operator=(const Model &rhs)
void invalidatePC(dword pcflags=PC_ALL)
MT & setCol(dword col, MT &vec)
float getMaxRadius() const
MT & setLower(const T &val=1, int offset=0)
bool readFile(const char *filename, bool fullread=true)
dword & setFlags(dword flags)
MT & setRow(dword row, MT &vec)
void clear()
remove and destroy all geometry information (nodes and edges)
DMatrixf selMaskMat() const
compute mask matrix of selected nodes
float mapAnglePI(float a)
void scaleSel(float factor, const DMatrixf &selm)
multiply all rest lengths of selected edges by factor
bool readEdge(ParseFile &is)
read edge from stream
SensorCollection & merge(SensorCollection &rhs)
PropVec & setPropScale(PropVec &prop, float pscale)
void pushLine(const std::string &line)
Point2D & convertPointFromMM(Point2D &pt) const
float getDeformation() const
normalized length variation to compensate for different sizes
dword m_InstCount
number of merged instances
sensor_ptr readSensor(ParseFile &is)
dword removeByAdjMat(DMatrixf &adjm)
remove edged not mentioned in (non-directional) adjacency matrix
void enableState(dword nstate)
sensor_ptr addSensor(const std::string &key, sensor_ptr s)
float dot(const Point2D &rhs) const
const int getLineNumber() const
float m_TimeStamp
time stamps (see. TTimeStamp)
DMatrix< T > & sqrt(DMatrix< T > &mat)
void push(const Point &t)