COPASI API  4.16.103
CCopasiSpringLayout.cpp
Go to the documentation of this file.
1 // Copyright (C) 2010 - 2014 by Pedro Mendes, Virginia Tech Intellectual
2 // Properties, Inc., University of Heidelberg, and The University
3 // of Manchester.
4 // All rights reserved.
5 
6 #include <iostream>
7 #include <map>
8 
10 #include <layout/CLGlyphs.h>
11 #include <layout/CLReactionGlyph.h>
12 #include <layout/CLayout.h>
13 
14 #include <model/CCompartment.h>
15 #include <model/CReaction.h>
16 #include <model/CMetab.h>
17 
19 
20 /*
21 
22 void CCopasiSpringLayout::ReactionNode::updateFromState(const std::vector<double> & vars, CCopasiSpringLayout * li)
23 {
24  if (a != -1) //the node has to get its state itself
25  {
26  x = vars[a];
27  y = vars[b];
28  }
29 
30  //here we could add other updates that need to be done when the state was changed
31 
32  //the angle is for now calculated. It may be a state variable in the future
33  //first the substrates
34  double sx=0; double sy=0; unsigned int count=0;
35  unsigned int i, imax=mEdges.size();
36  for (i=0; i<imax; ++i)
37  if (mEdges[i].role==Edge::SUBSTRATE)
38  {
39  sx+=li->mSpeciesNodes[mEdges[i].sindex].x;
40  sy+=li->mSpeciesNodes[mEdges[i].sindex].y;
41  ++count;
42  }
43  if (count) sx /= count; else sx=x;
44  if (count) sy /= count; else sy=y;
45 
46  double px=0; double py=0; count=0;
47  for (i=0; i<imax; ++i)
48  if (mEdges[i].role==Edge::PRODUCT)
49  {
50  px+=li->mSpeciesNodes[mEdges[i].sindex].x;
51  py+=li->mSpeciesNodes[mEdges[i].sindex].y;
52  ++count;
53  }
54  if (count) px /= count; else px=x;
55  if (count) py /= count; else py=y;
56 
57  double l = sqrt((px-sx)*(px-sx)+(py-sy)*(py-sy));
58  if (l==0)
59  {dx=1; dy=0;}
60  else
61  {
62  dx = (px-sx)/l;
63  dy = (py-sy)/l;
64  }
65 
66  //angle
67 }
68  */
69 
70 //*******************************************
71 
73  : mpLayout(NULL)
74 {
75  if (ppp == NULL)
76  {
77  // backward compatible
78  ppp = new Parameters();
79  }
80 
81  initFromLayout(layout, ppp);
82 }
83 
85 {
86  mpLayout = layout;
87  mpPar = ppp;
88 
89  if (!mpLayout) return false;
90 
91  if (!ppp) return false;
92 
93  mCompartmentMap.clear();
94 
95  //store the compartment glyph for each species glyph (if it exists)
96  unsigned int i;
97 
98  for (i = 0; i < mpLayout->getListOfMetaboliteGlyphs().size() ; ++i)
99  {
100  CMetab* metab = dynamic_cast<CMetab*>(mpLayout->getListOfMetaboliteGlyphs()[i]->getModelObject());
101  CLCompartmentGlyph* tmp = NULL;
102 
103  if (metab)
104  {
105  unsigned int j;
106 
107  for (j = 0; j < mpLayout->getListOfCompartmentGlyphs().size(); ++j)
108  if (mpLayout->getListOfCompartmentGlyphs()[j]->getModelObjectKey() == metab->getCompartment()->getKey())
109  {
111  break;
112  }
113  }
114 
116  }
117 
118  //store the compartment glyph for each reaction glyph (if it exists)
119  for (i = 0; i < mpLayout->getListOfReactionGlyphs().size() ; ++i)
120  {
122  }
123 
124  //create the list of constant positional relations
125  //we assume that text glyphs are always moved with the glyph they refer to.
126  //(i.e. the are not layed out independently)
127  mFixedRelations.clear();
128 
129  for (i = 0; i < mpLayout->getListOfTextGlyphs().size(); ++i)
130  {
131  CoordinateRelation tmp;
132  tmp.target = mpLayout->getListOfTextGlyphs()[i];
133  tmp.source = mpLayout->getListOfTextGlyphs()[i]->getGraphicalObject();
134 
135  if (tmp.source)
136  {
137  tmp.diff = tmp.target->getPosition() - tmp.source->getPosition();
138  mFixedRelations.push_back(tmp);
139  }
140  }
141 
142  return true;
143 }
144 
146 {
147  CLCompartmentGlyph* pCG = NULL;
148 
149  //r.compartmentIndex = mSpeciesNodes[r.getEdges()[0].sindex].compartmentIndex;
150  unsigned int i;
151 
152  for (i = 0; i < r.getListOfMetabReferenceGlyphs().size(); ++i)
153  {
154  std::map<CLBase*, CLCompartmentGlyph*>::const_iterator mapIt = mCompartmentMap.find(r.getListOfMetabReferenceGlyphs()[i]->getMetabGlyph());
155 
156  if (mapIt == mCompartmentMap.end())
157  {
158  //there is no information in the map. Should not happen.
159 #ifdef COPASI_DEBUG
160  std::cout << "No compartment info for a species glyph!!!" << std::endl;
161 #endif
162  continue;
163  }
164 
165  if (! mapIt->second)
166  continue; //the species glyph is not linked to a compartment
167 
168  if (!pCG) //this is the first compartment
169  {
170  pCG = mapIt->second;
171  continue;
172  }
173 
174  if (pCG != mapIt->second) //there are at least two different compartments
175  {
176  pCG = NULL;
177  break;
178  }
179  }
180 
181  return pCG;
182 }
183 
185 {
186  //delete current variables
187  mInitialState.clear();
188  mVarDescription.clear();
189  mMassVector.clear();
190 
191  unsigned int i;
192 
193  // add variables for the coordinates of all metabs
194  for (i = 0; i < mpLayout->getListOfMetaboliteGlyphs().size() ; ++i)
195  {
197  }
198 
199  // add variables for the coordinates of all reaction glyphs
200  for (i = 0; i < mpLayout->getListOfReactionGlyphs().size() ; ++i)
201  {
203  }
204 
205  // add variables for the coordinates of all general glyphs
206  for (i = 0; i < mpLayout->getListOfGeneralGlyphs().size() ; ++i)
207  {
209  }
210 
211  // add variables for text glyphs that are not fixed to anything.
212  //TODO
213 
214  return true;
215 }
216 
218 {
219  if (!cg)
220  return;
221 
222  VariableDescription desc;
223  desc.isAngle = false;
224 
225  int first_index = mInitialState.size();
226 
227  //x position
228  mInitialState.push_back(cg->getX());
229  mVarDescription.push_back(desc);
230  mMassVector.push_back(0.01);
231 
232  //y position
233  mInitialState.push_back(cg->getY());
234  mVarDescription.push_back(desc);
235  mMassVector.push_back(0.01);
236 
237  //width
238  mInitialState.push_back(cg->getWidth());
239  mVarDescription.push_back(desc);
240  mMassVector.push_back(0.01);
241 
242  //height
243  mInitialState.push_back(cg->getHeight());
244  mVarDescription.push_back(desc);
245  mMassVector.push_back(0.01);
246 
247  mUpdateActions.push_back(UpdateAction(UpdateAction::COMPARTMENT_4V, cg, first_index, first_index + 1, first_index + 2, first_index + 3));
248 }
249 
251 {
252  if (!pGO)
253  return;
254 
255  bool side = false; //TODO: find out if it is a side reactant
256 
257  VariableDescription desc;
258  desc.isAngle = false;
259 
260  int first_index = mInitialState.size();
261 
262  //x position
263  mInitialState.push_back(pGO->getX());
264  mVarDescription.push_back(desc);
265  mMassVector.push_back(side ? 0.1 : 1.0);
266 
267  //y position
268  mInitialState.push_back(pGO->getY());
269  mVarDescription.push_back(desc);
270  mMassVector.push_back(side ? 0.1 : 1.0);
271 
272  mUpdateActions.push_back(UpdateAction(UpdateAction::POSITION_2V, pGO, first_index, first_index + 1));
273 }
274 
276 {
277  if (!rg)
278  return;
279 
280  VariableDescription desc;
281  desc.isAngle = false;
282 
283  int first_index = mInitialState.size();
284 
285  C_FLOAT64 xxx, yyy;
286 
287  //first look if the glyph is described by a curve
288  if (rg->getCurve().getNumCurveSegments())
289  {
290  unsigned int numsegs = rg->getCurve().getNumCurveSegments();
291  xxx = 0.5 * (rg->getCurve().getCurveSegments()[0].getStart().getX()
292  + rg->getCurve().getCurveSegments()[numsegs - 1].getEnd().getX());
293  yyy = 0.5 * (rg->getCurve().getCurveSegments()[0].getStart().getY()
294  + rg->getCurve().getCurveSegments()[numsegs - 1].getEnd().getY());
295  }
296  else
297  {
298  xxx = rg->getX() + 0.5 * rg->getWidth();
299  yyy = rg->getY() + 0.5 * rg->getHeight();
300  }
301 
302  //x position
303  mInitialState.push_back(xxx);
304  mVarDescription.push_back(desc);
305  mMassVector.push_back(1.0);
306 
307  //y position
308  mInitialState.push_back(yyy);
309  mVarDescription.push_back(desc);
310  mMassVector.push_back(1.0);
311 
312  mUpdateActions.push_back(UpdateAction(UpdateAction::REACTION_2V, rg, first_index, first_index + 1));
313 }
314 
315 bool CCopasiSpringLayout::setState(const std::vector<double> & vars)
316 {
317  if (vars.size() < mVarDescription.size())
318  return false;
319 
320  std::vector<UpdateAction>::const_iterator it, itEnd = mUpdateActions.end();
321 
322  for (it = mUpdateActions.begin(); it != itEnd; ++it)
323  {
324  switch (it->mAction)
325  {
327  ((CLCompartmentGlyph*)(it->mpTarget))->setX(vars[it->mIndex1]);
328  ((CLCompartmentGlyph*)(it->mpTarget))->setY(vars[it->mIndex2]);
329  ((CLCompartmentGlyph*)(it->mpTarget))->setWidth(vars[it->mIndex3]);
330  ((CLCompartmentGlyph*)(it->mpTarget))->setHeight(vars[it->mIndex4]);
331  break;
332 
334  ((CLGraphicalObject*)(it->mpTarget))->setX(vars[it->mIndex1]);
335  ((CLGraphicalObject*)(it->mpTarget))->setY(vars[it->mIndex2]);
336  break;
337 
339  ((CLReactionGlyph*)(it->mpTarget))->setX(vars[it->mIndex1]);
340  ((CLReactionGlyph*)(it->mpTarget))->setY(vars[it->mIndex2]);
341  break;
342 
343  default:
344 #ifdef COPASI_DEBUG
345  std::cout << "Unknown Action!!!" << std::endl;
346 #endif
347  break;
348  };
349  }
350 
351  //If we assume that the position of the dependent (text) glyphs can have an influence
352  //on the layout we need to update them here.
353  //Currently we assume that is not the case and the update will be done in finalizeState();
354 
355  return true;
356 }
357 
359 {
360  unsigned int i;
361 
362  //update the positions of the dependent glyphs
363  //this can be done here since we assume that those glyphs
364  //do not affect the layout.
365  std::vector<CoordinateRelation>::const_iterator it, itEnd = mFixedRelations.end();
366 
367  for (it = mFixedRelations.begin(); it != itEnd; ++it)
368  it->target->setPosition(it->source->getPosition() + it->diff);
369 
370  //for now, only create curves for the reaction glyphs
371  for (i = 0; i < mpLayout->getListOfReactionGlyphs().size() ; ++i)
372  {
374 
375  //Determine the average position of substrates and products, giving less weight to side reactants
376  CLPoint s, p;
377  double s_c = 0; double p_c = 0;
378  unsigned int j, jmax = pRG->getListOfMetabReferenceGlyphs().size();
379 
380  for (j = 0; j < jmax; ++j)
381  {
383  {
384  s_c += 1.0;
385  s = s + pRG->getListOfMetabReferenceGlyphs()[j]->getMetabGlyph()->getBoundingBox().getCenter();
386  }
387 
389  {
390  s_c += 0.1;
391  s = s + pRG->getListOfMetabReferenceGlyphs()[j]->getMetabGlyph()->getBoundingBox().getCenter() * 0.1;
392  }
393 
395  {
396  p_c += 1.0;
397  p = p + pRG->getListOfMetabReferenceGlyphs()[j]->getMetabGlyph()->getBoundingBox().getCenter();
398  }
399 
401  {
402  p_c += 0.1;
403  p = p + pRG->getListOfMetabReferenceGlyphs()[j]->getMetabGlyph()->getBoundingBox().getCenter() * 0.1;
404  }
405  }
406 
407  if (s_c > 0)
408  s = s * (1 / s_c);
409  else
410  s = pRG->getPosition();
411 
412  if (p_c > 0)
413  p = p * (1 / p_c);
414  else
415  p = pRG->getPosition();
416 
417  CLPoint dir = p - s; //overall direction of reaction
418 
419  if (dir.getX() == 0 && dir.getY() == 0)
420  dir = CLPoint(1, 0);
421 
422  CLPoint ortho_dir = CLPoint(dir.getY(), -dir.getX());
423  ortho_dir.scale(1 / sqrt(pow(ortho_dir.getX(), 2) + pow(ortho_dir.getY(), 2)));
424 
425  CLPoint reaction_s = pRG->getPosition() - (dir * 0.05);
426  CLPoint reaction_p = pRG->getPosition() + (dir * 0.05);
427  CLPoint reaction_m1 = pRG->getPosition() + ortho_dir * 10;
428  CLPoint reaction_m2 = pRG->getPosition() - ortho_dir * 10;
429 
430  pRG->getCurve().clear();
431  pRG->getCurve().addCurveSegment(CLLineSegment(reaction_s, reaction_p));
432 
433  for (j = 0; j < jmax; ++j)
434  {
435  //here we need to generate the curves for the MetabReferenceGlyphs.
436  //we will need to consider the size of the glyphs, role of the metab in the reaction, etc.
437  //For now, only a primitive implementation: TODO: improve
439  double direction;
440  //double modifierLength = -0.2;
441 
442  switch (pMRG->getRole())
443  {
446  {
447  direction = -0.1;
448  CLPoint metabPoint = borderProjection(pMRG->getMetabGlyph(), reaction_s + dir * direction /*(modifierLength * 1.5)*/, 5);
449  pMRG->getCurve().clear();
450  pMRG->getCurve().addCurveSegment(CLLineSegment(reaction_s,
451  metabPoint,
452  reaction_s + dir * direction,
453  (reaction_s + dir * (direction * 1.5) + metabPoint) * 0.5));
454  }
455  break;
456 
459  {
460  direction = 0.1;
461  CLPoint metabPoint = borderProjection(pMRG->getMetabGlyph(), reaction_p + dir * direction /*(modifierLength * 1.5)*/, 5);
462  pMRG->getCurve().clear();
463  pMRG->getCurve().addCurveSegment(CLLineSegment(reaction_p,
464  metabPoint,
465  reaction_p + dir * direction,
466  (reaction_p + dir * (direction * 1.5) + metabPoint) * 0.5));
467  }
468  break;
469 
470  default:
471  {
472  CLPoint reactionPoint;
473 
474  if (ortho_dir.dot(pRG->getPosition() - pMRG->getMetabGlyph()->getPosition()) < 0)
475  {
476  direction = +10.0;
477  reactionPoint = reaction_m1;
478  }
479  else
480  {
481  direction = -10.0;
482  reactionPoint = reaction_m2;
483  }
484 
485  CLPoint metabPoint = borderProjection(pMRG->getMetabGlyph(), reactionPoint + dir * 0 * direction /*(modifierLength * 1.5)*/, 5);
486  pMRG->getCurve().clear();
487  pMRG->getCurve().addCurveSegment(CLLineSegment(metabPoint,
488  reactionPoint,
489  (reactionPoint + dir * (0 * direction * 1.5) + metabPoint) * 0.5,
490  reactionPoint + ortho_dir * direction));
491  }
492  }
493  }
494  }
495 
496  //update the curves in the general glyph
497  for (i = 0; i < mpLayout->getListOfGeneralGlyphs().size() ; ++i)
498  {
500 
501  size_t j;
502 
503  for (j = 0; j < pGG->getListOfReferenceGlyphs().size(); ++j)
504  {
506 
507  if (pRG->getCurve().getNumCurveSegments() == 0) continue;
508 
509  CLPoint refPoint = borderProjection(pRG->getTargetGlyph(), pRG->getBoundingBox().getCenter(), 5);
510  pRG->getCurve().clear();
511  pRG->getCurve().addCurveSegment(CLLineSegment(refPoint, pRG->getBoundingBox().getCenter()));
512  }
513  }
514 
515  //calculate bounding box for the layout, or recenter the layout
517 }
518 
520 {
521  CLPoint center = go->getBoundingBox().getCenter();
522  CLPoint diff = p - center;
523 
524  CLPoint ret;
525 
526  if (fabs(diff.getX()) * (fabs(go->getHeight()) * 0.5 + d) > fabs(diff.getY()) * (fabs(go->getWidth()) * 0.5 + d))
527  {
528  double f = (fabs(go->getWidth()) * 0.5 + d) / fabs(diff.getX());
529  ret = center + diff * f;
530  }
531  else
532  {
533  double f = (fabs(go->getHeight()) * 0.5 + d) / fabs(diff.getY());
534  ret = center + diff * f;
535  }
536 
537  return ret;
538 }
539 
540 //*************************************
541 
543 {
544  double tmp;
545  tmp = bound_distance(a.getX() + a.getWidth() / 2, a.getY() + a.getHeight() / 2,
546  b.getX() + b.getWidth() / 2, b.getY() + b.getHeight() / 2, 200);
547 
548  if (tmp < 1) tmp = 1;
549 
550  return /*a.charge*b.charge*/ 1 / tmp; //TODO: reintroduce the charge
551 }
552 
554 {
555  double tmp = bound_distance(a.getX() + a.getWidth() / 2, a.getY() + a.getHeight() / 2,
556  b.getX() + b.getWidth() / 2, b.getY() + b.getHeight() / 2, 200);
557 
558  if (tmp < 1) tmp = 1;
559 
560  return /*a.charge*b.charge*/ 1 / tmp; //TODO: reintroduce the charge
561 }
562 
564 {
565  double tmp = bound_distance(a.getX() + a.getWidth() / 2, a.getY() + a.getHeight() / 2,
566  b.getX() + b.getWidth() / 2, b.getY() + b.getHeight() / 2, 200);
567 
568  if (tmp < 1) tmp = 1;
569 
570  return /*a.charge*b.charge*/ 1 / tmp; //TODO: reintroduce the charge
571 }
572 
574 {
575  double dist = mpPar->values[1];
576 
578  dist = mpPar->values[3];
579 
580  const CLMetabGlyph * pMG = e.getMetabGlyph();
581  double tmp = distance(pMG->getX() + pMG->getWidth() / 2, pMG->getY() + pMG->getHeight() / 2,
582  r.getX() + r.getWidth() / 2, r.getY() + r.getHeight() / 2);
583 
585  return mpPar->values[4] * pow(tmp - dist, 2);
586  else
587  return mpPar->values[2] * pow(tmp - dist, 2);
588 }
589 
591 {
592  const CLMetabGlyph * pMG1 = e1.getMetabGlyph();
593  const CLMetabGlyph * pMG2 = e2.getMetabGlyph();
594  double tmp = distance(pMG1->getX() + pMG1->getWidth() / 2, pMG1->getY() + pMG1->getHeight() / 2,
595  pMG2->getX() + pMG2->getWidth() / 2, pMG2->getY() + pMG2->getHeight() / 2);
596 
597  return pow(tmp - dist, 2);
598 }
599 
601 {
602  double dist = 30;
603 
604  const CLGraphicalObject * pMG = e.getTargetGlyph();
605  double tmp = distance(pMG->getX() + pMG->getWidth() / 2, pMG->getY() + pMG->getHeight() / 2,
606  r.getX() + r.getWidth() / 2, r.getY() + r.getHeight() / 2);
607 
608  return pow(tmp - dist, 2);
609 }
610 
611 /*
612 
613 double CCopasiSpringLayout::potReaction(const ReactionNode & r) const
614 {
615  double ret=0;
616 
617  double r_angle=r.dy>0?acos(r.dx):-acos(r.dx);
618 
619  unsigned int i, imax=r.getEdges().size();
620  for (i=0; i<imax; ++i)
621  {
622  double s_angle = (mSpeciesNodes[r.getEdges()[i].sindex].x-r.x)>0
623  ? atan((mSpeciesNodes[r.getEdges()[i].sindex].y-r.y)/(mSpeciesNodes[r.getEdges()[i].sindex].x-r.x))
624  : 3.1415+atan((mSpeciesNodes[r.getEdges()[i].sindex].y-r.y)/(mSpeciesNodes[r.getEdges()[i].sindex].x-r.x))
625  ;
626 
627  if (r.getEdges()[i].role==Edge::SUBSTRATE)
628  {
629  ret+=cos(s_angle-r_angle);
630  }
631  if (r.getEdges()[i].role==Edge::PRODUCT)
632  {
633  ret-=cos(s_angle-r_angle);
634  }
635  if (r.getEdges()[i].role==Edge::MODIFIER)
636  {
637  ret+=cos(2*(s_angle-r_angle));
638  }
639  }
640  */
641 /* for (i=0; i<imax; ++i)
642  {
643  if (r.getEdges()[i].role==Edge::SUBSTRATE)
644  {
645  ret+=(mSpeciesNodes[r.getEdges()[i].sindex].x-r.x)*r.dx
646  +(mSpeciesNodes[r.getEdges()[i].sindex].y-r.y)*r.dy;
647  }
648  if (r.getEdges()[i].role==Edge::PRODUCT)
649  {
650  ret+=-(mSpeciesNodes[r.getEdges()[i].sindex].x-r.x)*r.dx
651  -(mSpeciesNodes[r.getEdges()[i].sindex].y-r.y)*r.dy;
652  }
653  }*/
654 
655 /*
656  return ret;
657 }
658 
659  */
661 {
662  double tmp = 0;
663  double dist = fabs((s.getX() + 0.5 * s.getWidth()) - (c.getX() + 0.5 * c.getWidth()));
664 
665  if (dist > (0.5 * c.getWidth() - 50))
666  tmp += pow(dist - 0.5 * c.getWidth() + 50, 2);
667 
668  dist = fabs((s.getY() + 0.5 * s.getHeight()) - (c.getY() + 0.5 * c.getHeight()));
669 
670  if (dist > (0.5 * c.getHeight() - 50))
671  tmp += pow(dist - 0.5 * c.getHeight() + 50, 2);
672 
673  return tmp /**s.charge*/; //TODO reintroduce charge
674 }
675 
677 {
678  double tmp = 0;
679  double dist = fabs((r.getX() + 0.5 * r.getWidth()) - (c.getX() + 0.5 * c.getWidth()));
680 
681  if (dist > (0.5 * c.getWidth() - 50))
682  tmp += pow(dist - 0.5 * c.getWidth() + 50, 2);
683 
684  dist = fabs((r.getY() + 0.5 * r.getHeight()) - (c.getY() + 0.5 * c.getHeight()));
685 
686  if (dist > (0.5 * c.getHeight() - 50))
687  tmp += pow(dist - 0.5 * c.getHeight() + 50, 2);
688 
689  return tmp /**s.charge*/; //TODO reintroduce charge
690 }
691 
692 /*
693 
694 double CCopasiSpringLayout::potCompartmentCompartment(const CLCompartmentGlyph & c1, const CLCompartmentGlyph & c2) const
695 {
696  double tmp=0;
697  double distx=fabs(c1.x-c2.x) - (0.5*c1.w + 0.5*c2.w+20);
698  double disty=fabs(c1.y-c2.y) - (0.5*c1.h + 0.5*c2.h+20);
699  double dist = distx > disty ? distx : disty;
700 
701  if (dist < 0)
702  tmp+= -dist;
703  return tmp;
704 }
705  */
706 
708 {
709  //here we need to add the different effects that contribute to the potential
710 
711  double tmp = 0;
712 
713  //repulsion between species nodes
714  unsigned int i, j;
715 
716  for (i = 0; i < mpLayout->getListOfMetaboliteGlyphs().size() - 1; ++i)
717  for (j = i + 1; j < mpLayout->getListOfMetaboliteGlyphs().size(); ++j)
718  {
719  if (i != j)
721  }
722 
723  // only if we have reactions!
725  {
726  //repulsion between species nodes and reaction nodes
727  for (i = 0; i < mpLayout->getListOfMetaboliteGlyphs().size(); ++i)
728  for (j = 0; j < mpLayout->getListOfReactionGlyphs().size(); ++j)
729  {
731  }
732 
733  //repulsion between reaction nodes
734  for (i = 0; i < mpLayout->getListOfReactionGlyphs().size() - 1; ++i)
735  for (j = i + 1; j < mpLayout->getListOfReactionGlyphs().size(); ++j)
736  {
737  if (i != j)
739  }
740  }
741 
742  //spring force for species references
743  for (i = 0; i < mpLayout->getListOfReactionGlyphs().size(); ++i)
744  {
746 
747  for (j = 0; j < pRG->getListOfMetabReferenceGlyphs().size(); ++j)
748  {
749  tmp += potEdge(*pRG->getListOfMetabReferenceGlyphs()[j], *pRG);
750 
751  //second order
753 
755  continue;
756 
757  double dist = role == CLMetabReferenceGlyph::SUBSTRATE ? mpPar->values[1] : mpPar->values[3];
758  size_t k;
759 
760  for (k = 0; k < pRG->getListOfMetabReferenceGlyphs().size(); ++k)
761  {
762  CLMetabReferenceGlyph::Role role2 = pRG->getListOfMetabReferenceGlyphs()[k]->getRole();
763 
765  continue;
766 
767  dist += role2 == CLMetabReferenceGlyph::PRODUCT ? mpPar->values[1] : mpPar->values[3];
768 
770  }
771  }
772  }
773 
774  for (i = 0; i < mpLayout->getListOfGeneralGlyphs().size(); ++i)
775  {
777 
778  for (j = 0; j < pRG->getListOfReferenceGlyphs().size(); ++j)
779  {
780  tmp += potGeneralEdge(*pRG->getListOfReferenceGlyphs()[j], *pRG);
781  }
782  }
783 
784  /*
785  //forces at reaction nodes
786  for (i=0; i<mReactionNodes.size(); ++i)
787  {
788  tmp += 3000* potReaction(mReactionNodes[i]);
789  }
790  */
791 
792  //force to keep species in compartment
793  for (i = 0; i < mpLayout->getListOfMetaboliteGlyphs().size(); ++i)
794  {
796  std::map<CLBase*, CLCompartmentGlyph*>::const_iterator mapIt = mCompartmentMap.find(tmpMG);
797 
798  if (mapIt == mCompartmentMap.end())
799  {
800  //there is no information in the map. Should not happen.
801 #ifdef COPASI_DEBUG
802  std::cout << "No compartment info for a species glyph!!!" << std::endl;
803 #endif
804  continue;
805  }
806 
807  CLCompartmentGlyph* tmpCG = mapIt->second;
808 
809  if (tmpCG) //the species glyph is inside a compartment glyph
810  tmp += mpPar->values[6] * potSpeciesCompartment(*tmpMG, *tmpCG);
811  }
812 
813  //force to keep reaction nodes in compartment
814  for (i = 0; i < mpLayout->getListOfReactionGlyphs().size(); ++i)
815  {
817  std::map<CLBase*, CLCompartmentGlyph*>::const_iterator mapIt = mCompartmentMap.find(tmpRG);
818 
819  if (mapIt == mCompartmentMap.end())
820  {
821  //there is no information in the map. Should not happen.
822 #ifdef COPASI_DEBUG
823  std::cout << "No compartment info for a reaction glyph!!!" << std::endl;
824 #endif
825  continue;
826  }
827 
828  CLCompartmentGlyph* tmpCG = mapIt->second;
829 
830  if (tmpCG) //the reaction glyph is inside a compartment glyph
831  tmp += mpPar->values[7] * potReactionCompartment(*tmpRG, *tmpCG);
832  }
833 
834  /*
835 
836  //force to shrink compartments
837  for (i=0; i<mCompartmentNodes.size(); ++i)
838  {
839  tmp += 0.2*(fabs(mCompartmentNodes[i].w-100)+fabs(mCompartmentNodes[i].h-100));
840  }
841 
842  //repulsion between compartments
843  for (i=0; i<mCompartmentNodes.size(); ++i)
844  for (j=0; j<mCompartmentNodes.size(); ++j)
845  {
846  if (i!=j)
847  tmp += 100*potCompartmentCompartment(mCompartmentNodes[i], mCompartmentNodes[j]);
848  }
849 
850  //centering force
851  for (i=0; i<mCompartmentNodes.size(); ++i)
852  {
853  tmp += 10*(fabs(mCompartmentNodes[i].x)+fabs(mCompartmentNodes[i].y));
854  }
855  */
856  return tmp;
857 }
858 
859 const std::vector<double> & CCopasiSpringLayout::getInitialValues() const
860 {
861  return mInitialState;
862 }
863 
864 const std::vector<CCopasiSpringLayout::UpdateAction>& CCopasiSpringLayout::getUpdateActions() const
865 {
866  return mUpdateActions;
867 }
868 
870 {
871  double x = pContainer->getPosition().getX()
872  + pRandom->getRandomCC() * (pContainer->getDimensions().getWidth() - pGl->getDimensions().getWidth());
873  double y = pContainer->getPosition().getY()
874  + pRandom->getRandomCC() * (pContainer->getDimensions().getHeight() - pGl->getDimensions().getHeight());
875  pGl->setPosition(CLPoint(x, y));
876 }
877 
879 {
880  double x = pRandom->getRandomCC() * (pContainer->getWidth() - pGl->getDimensions().getWidth());
881  double y = pRandom->getRandomCC() * (pContainer->getHeight() - pGl->getDimensions().getHeight());
882  pGl->setPosition(CLPoint(x, y));
883 }
884 
885 void placeTextGlyphs(CLayout* pLayout)
886 {
887  size_t i;
888 
889  for (i = 0; i < pLayout->getListOfTextGlyphs().size(); ++i)
890  {
891  CLTextGlyph* pTG = pLayout->getListOfTextGlyphs()[i];
893 
894  if (!pGO)
895  continue;
896 
897  pTG->setPosition(CLPoint(pGO->getX() + 2, pGO->getY() + 2));
898  }
899 }
900 
901 /**
902  * This function produces a random layout. It first shufles around
903  * metab glyphs and reaction centers, and finally corrects all ars
904  */
906 {
908 
909  size_t i;
910 
911  //compartment glyphs
912 
913  //metab glyphs
914  for (i = 0; i < mpLayout->getListOfMetaboliteGlyphs().size(); ++i)
915  {
916  CLMetabGlyph* pMetabGlyph = mpLayout->getListOfMetaboliteGlyphs()[i];
917  const CMetab* pMetab = dynamic_cast<const CMetab*>(pMetabGlyph->getModelObject());
918 
919  if (!pMetab)
920  continue;
921 
922  //find the compartment glyph
923  const CCompartment* pComp = pMetab->getCompartment();
924 
925  if (!pComp)
926  continue;
927 
928  const CLCompartmentGlyph* pCompGlyph = NULL;
929  size_t j;
930 
931  for (j = 0; j < mpLayout->getListOfCompartmentGlyphs().size(); ++j)
932  if (mpLayout->getListOfCompartmentGlyphs()[j]->getModelObjectKey()
933  == pComp->getKey())
934  {
935  pCompGlyph = mpLayout->getListOfCompartmentGlyphs()[j];
936  break;
937  }
938 
939  if (pCompGlyph)
940  randomlyPlaceGlyphInCompartmentGlyph(pMetabGlyph, pCompGlyph, pRandom);
941  else
942  randomlyPlaceGlyphInDimensions(pMetabGlyph, &mpLayout->getDimensions(), pRandom);
943  }
944 
945  //reaction glyphs
946  for (i = 0; i < mpLayout->getListOfReactionGlyphs().size(); ++i)
947  {
948  CLReactionGlyph* pReactionGlyph = mpLayout->getListOfReactionGlyphs()[i];
949  CLPoint center(0, 0);
950  size_t count;
951 
952  for (count = 0; count < pReactionGlyph->getListOfMetabReferenceGlyphs().size(); ++count)
953  center = center + pReactionGlyph->getListOfMetabReferenceGlyphs()[count]
954  ->getMetabGlyph()->getBoundingBox().getCenter();
955 
956  center = center * (1.0 / pReactionGlyph->getListOfMetabReferenceGlyphs().size());
957  center = center + CLPoint(pRandom->getRandomCC() * 20 - 10, pRandom->getRandomCC() * 20 - 10);
958 
959  pReactionGlyph->setPosition(center);
960 
961  /*if (pCompGlyph)
962  randomlyPlaceGlyphInCompartmentGlyph(pMetabGlyph, pCompGlyph);
963  else
964  randomlyPlaceGlyphInDimensions(pMetabGlyph, &mpCurrentLayout->getDimensions());*/
965  }
966 
968  delete pRandom;
969 
970  finalizeState();
971 }
972 
974 {
975 public:
976  unsigned int mNumItems;
977  double mAreaSum;
978 
980  : mNumItems(0),
981  mAreaSum(0.0)
982  {}
983 
984  void add(double area)
985  {
986  ++mNumItems;
987  mAreaSum += area;
988  }
989 };
990 
992  CCopasiContainer *parent,
993  const std::set<const CCompartment*>& compartments,
994  const std::set<const CReaction*>& reactions,
995  const std::set<const CMetab*>& metabs,
996  const std::set<const CMetab*>& sideMetabs,
997  Parameters* mParams
998 )
999 {
1000  CLayout *pResult = new CLayout("Layout", parent);
1001 
1002  double fontSize = 16.0;
1003  double fontHeight = fontSize * 1.5;
1004 
1005  // create a species glyph for each species in metabs
1006 
1007  std::map<const CCompartment*, CompartmentInfo> compInfo;
1008  std::map<const CMetab*, CLMetabGlyph*> metabMap;
1009 
1010  std::set<const CMetab*>::const_iterator metabIt;
1011 
1012  for (metabIt = metabs.begin(); metabIt != metabs.end(); ++metabIt)
1013  {
1014  if (sideMetabs.find(*metabIt) != sideMetabs.end())
1015  continue;
1016 
1017  //estimate the size of the glyph
1018  double width = (double)((*metabIt)->getObjectName().length() * fontSize);
1019  double height = (double)fontHeight;
1020 
1021  if (width < height)
1022  {
1023  width = height;
1024  }
1025 
1026  //create the glyph
1027  CLMetabGlyph* pMetabGlyph = new CLMetabGlyph;
1028  pMetabGlyph->setDimensions(CLDimensions(width + 4, height + 4));
1029  pMetabGlyph->setModelObjectKey((*metabIt)->getKey());
1030 
1031  pResult->addMetaboliteGlyph(pMetabGlyph);
1032  metabMap[*metabIt] = pMetabGlyph;
1033 
1034  //create the text glyph for the label
1035  CLTextGlyph* pTextGlyph = new CLTextGlyph;
1036  pTextGlyph->setDimensions(CLDimensions(width, height));
1037  pTextGlyph->setGraphicalObjectKey(pMetabGlyph->getKey());
1038  pTextGlyph->setModelObjectKey((*metabIt)->getKey());
1039 
1040  pResult->addTextGlyph(pTextGlyph);
1041 
1042  //add up the sizes for the compartment
1043  const CCompartment* pComp = NULL;
1044 
1045  if (compartments.find((*metabIt)->getCompartment()) != compartments.end())
1046  pComp = (*metabIt)->getCompartment();
1047 
1048  compInfo[pComp].add((width + 4) * (height + 4));
1049  }
1050 
1051  //now the reaction glyphs
1052  std::set<const CReaction*>::const_iterator reactIt;
1053 
1054  for (reactIt = reactions.begin(); reactIt != reactions.end(); ++reactIt)
1055  {
1056  CLReactionGlyph* pReactionGlyph = new CLReactionGlyph;
1057  //pResult->setDimensions(CLDimensions(width, height));
1058  pReactionGlyph->setModelObjectKey((*reactIt)->getKey());
1059  //pReactionGlyph->getCurve().addCurveSegment(CLLineSegment(CLPoint(x, y),
1060  // CLPoint(x + length, y)));
1061  bool isReversible = (*reactIt)->isReversible();
1062  pResult->addReactionGlyph(pReactionGlyph);
1063 
1064  //now add the species reference glyphs.
1065 
1066  //substrates
1067  const CCopasiVector < CChemEqElement >& substrates = (*reactIt)->getChemEq().getSubstrates();
1068  bool substrateExists = false;
1070 
1071  for (elIt = substrates.begin(); elIt != substrates.end(); ++elIt)
1072  {
1073  const CMetab* pMetab = (*elIt)->getMetabolite();
1074 
1075  if (!pMetab)
1076  continue;
1077 
1078  CLMetabGlyph* pMetabGlyph = NULL;
1079  CLMetabReferenceGlyph::Role role; // = CLMetabReferenceGlyph::SUBSTRATE;
1080 
1081  //is it a side reactant? If yes, create a new metab glyph
1082  if (sideMetabs.find(pMetab) != sideMetabs.end())
1083  {
1084  //estimate the size of the glyph
1085  double width = (double)((pMetab)->getObjectName().length() * fontSize);
1086  double height = (double)fontHeight;
1087 
1088  if (width < height)
1089  {
1090  width = height;
1091  }
1092 
1093  //create the glyph
1094  pMetabGlyph = new CLMetabGlyph;
1095  pMetabGlyph->setDimensions(CLDimensions(width + 4, height + 4));
1096  pMetabGlyph->setModelObjectKey(pMetab->getKey());
1097  //TODO: mark as duplicate
1098  pResult->addMetaboliteGlyph(pMetabGlyph);
1099 
1100  //create the text glyph for the label
1101  CLTextGlyph* pTextGlyph = new CLTextGlyph;
1102  pTextGlyph->setDimensions(CLDimensions(width, height));
1103  pTextGlyph->setGraphicalObjectKey(pMetabGlyph->getKey());
1104  pTextGlyph->setModelObjectKey(pMetab->getKey());
1105 
1106  pResult->addTextGlyph(pTextGlyph);
1107 
1108  //add up the sizes for the compartment
1109  const CCompartment* pComp = NULL;
1110 
1111  if (compartments.find(pMetab->getCompartment()) != compartments.end())
1112  pComp = pMetab->getCompartment();
1113 
1114  compInfo[pComp].add((width + 4) * (height + 4));
1115 
1116  role = isReversible
1119  }
1120  else
1121  {
1122  //find the existing metab glyph
1123  std::map<const CMetab*, CLMetabGlyph*>::const_iterator mmIt;
1124  mmIt = metabMap.find(pMetab);
1125 
1126  if (mmIt != metabMap.end())
1127  pMetabGlyph = mmIt->second;
1128 
1129  role = isReversible
1132  }
1133 
1134  if (!pMetabGlyph)
1135  continue;
1136 
1138  //pResult->setModelObjectKey(modelobjectkey);
1139  pRefGlyph->setMetabGlyphKey(pMetabGlyph->getKey());
1140  pRefGlyph->setRole(role);
1141  pReactionGlyph->addMetabReferenceGlyph(pRefGlyph);
1142  substrateExists = true;
1143  } //substrates
1144 
1145  // if we have no substrates, add a dummy / invisible node for now
1146  if (!substrateExists)
1147  {
1148  CLMetabGlyph* pMetabGlyph = new CLMetabGlyph;
1149  pMetabGlyph->setDimensions(CLDimensions(1, 1));
1150  pMetabGlyph->setObjectRole("invisible");
1151  pResult->addMetaboliteGlyph(pMetabGlyph);
1152 
1154  //pResult->setModelObjectKey(modelobjectkey);
1155  pRefGlyph->setMetabGlyphKey(pMetabGlyph->getKey());
1156  pRefGlyph->setRole(CLMetabReferenceGlyph::SUBSTRATE); //TODO side substr?
1157  pReactionGlyph->addMetabReferenceGlyph(pRefGlyph);
1158  }
1159 
1160  //products
1161  const CCopasiVector < CChemEqElement >& products = (*reactIt)->getChemEq().getProducts();
1162  bool productExists = false;
1163 
1164  for (elIt = products.begin(); elIt != products.end(); ++elIt)
1165  {
1166  const CMetab* pMetab = (*elIt)->getMetabolite();
1167 
1168  if (!pMetab)
1169  continue;
1170 
1171  CLMetabGlyph* pMetabGlyph = NULL;
1172  CLMetabReferenceGlyph::Role role; // = CLMetabReferenceGlyph::SUBSTRATE;
1173 
1174  //is it a side reactant? If yes, create a new metab glyph
1175  if (sideMetabs.find(pMetab) != sideMetabs.end())
1176  {
1177  //estimate the size of the glyph
1178  double width = (double)((pMetab)->getObjectName().length() * fontSize);
1179  double height = (double)fontHeight;
1180 
1181  if (width < height)
1182  {
1183  width = height;
1184  }
1185 
1186  //create the glyph
1187  pMetabGlyph = new CLMetabGlyph;
1188  pMetabGlyph->setDimensions(CLDimensions(width + 4, height + 4));
1189  pMetabGlyph->setModelObjectKey(pMetab->getKey());
1190  //TODO: mark as duplicate
1191  pResult->addMetaboliteGlyph(pMetabGlyph);
1192 
1193  //create the text glyph for the label
1194  CLTextGlyph* pTextGlyph = new CLTextGlyph;
1195  pTextGlyph->setDimensions(CLDimensions(width, height));
1196  pTextGlyph->setGraphicalObjectKey(pMetabGlyph->getKey());
1197  pTextGlyph->setModelObjectKey(pMetab->getKey());
1198 
1199  pResult->addTextGlyph(pTextGlyph);
1200 
1201  //add up the sizes for the compartment
1202  const CCompartment* pComp = NULL;
1203 
1204  if (compartments.find(pMetab->getCompartment()) != compartments.end())
1205  pComp = pMetab->getCompartment();
1206 
1207  compInfo[pComp].add((width + 4) * (height + 4));
1208 
1210  }
1211  else
1212  {
1213  //find the existing metab glyph
1214  std::map<const CMetab*, CLMetabGlyph*>::const_iterator mmIt;
1215  mmIt = metabMap.find(pMetab);
1216 
1217  if (mmIt != metabMap.end())
1218  pMetabGlyph = mmIt->second;
1219 
1221  }
1222 
1223  if (!pMetabGlyph)
1224  continue;
1225 
1227  //pResult->setModelObjectKey(modelobjectkey);
1228  pRefGlyph->setMetabGlyphKey(pMetabGlyph->getKey());
1229  pRefGlyph->setRole(role);
1230  pReactionGlyph->addMetabReferenceGlyph(pRefGlyph);
1231  productExists = true;
1232  } //products
1233 
1234  // if we have no substrates, add a dummy / invisible node for now
1235  if (!productExists)
1236  {
1237  CLMetabGlyph* pMetabGlyph = new CLMetabGlyph;
1238  pMetabGlyph->setDimensions(CLDimensions(1, 1));
1239  pMetabGlyph->setObjectRole("invisible");
1240  pResult->addMetaboliteGlyph(pMetabGlyph);
1241 
1243  //pResult->setModelObjectKey(modelobjectkey);
1244  pRefGlyph->setMetabGlyphKey(pMetabGlyph->getKey());
1245  pRefGlyph->setRole(CLMetabReferenceGlyph::PRODUCT); //TODO side substr?
1246  pReactionGlyph->addMetabReferenceGlyph(pRefGlyph);
1247  }
1248 
1249  //modifiers
1250  const CCopasiVector < CChemEqElement >& modifiers = (*reactIt)->getChemEq().getModifiers();
1251 
1252  for (elIt = modifiers.begin(); elIt != modifiers.end(); ++elIt)
1253  {
1254  const CMetab* pMetab = (*elIt)->getMetabolite();
1255 
1256  if (!pMetab)
1257  continue;
1258 
1259  CLMetabGlyph* pMetabGlyph = NULL;
1260  CLMetabReferenceGlyph::Role role; // = CLMetabReferenceGlyph::SUBSTRATE;
1261 
1262  //is it a side reactant? If yes, create a new metab glyph
1263  if (sideMetabs.find(pMetab) != sideMetabs.end())
1264  {
1265  //estimate the size of the glyph
1266  double width = (double)((pMetab)->getObjectName().length() * fontSize);
1267  double height = (double)fontHeight;
1268 
1269  if (width < height)
1270  {
1271  width = height;
1272  }
1273 
1274  //create the glyph
1275  pMetabGlyph = new CLMetabGlyph;
1276  pMetabGlyph->setDimensions(CLDimensions(width + 4, height + 4));
1277  pMetabGlyph->setModelObjectKey(pMetab->getKey());
1278  //TODO: mark as duplicate
1279  pResult->addMetaboliteGlyph(pMetabGlyph);
1280 
1281  //create the text glyph for the label
1282  CLTextGlyph* pTextGlyph = new CLTextGlyph;
1283  pTextGlyph->setDimensions(CLDimensions(width, height));
1284  pTextGlyph->setGraphicalObjectKey(pMetabGlyph->getKey());
1285  pTextGlyph->setModelObjectKey(pMetab->getKey());
1286 
1287  pResult->addTextGlyph(pTextGlyph);
1288 
1289  //add up the sizes for the compartment
1290  const CCompartment* pComp = NULL;
1291 
1292  if (compartments.find(pMetab->getCompartment()) != compartments.end())
1293  pComp = pMetab->getCompartment();
1294 
1295  compInfo[pComp].add((width + 4) * (height + 4));
1296 
1297  role = CLMetabReferenceGlyph::MODIFIER; //TODO SIDEMODIFIER???
1298  }
1299  else
1300  {
1301  //find the existing metab glyph
1302  std::map<const CMetab*, CLMetabGlyph*>::const_iterator mmIt;
1303  mmIt = metabMap.find(pMetab);
1304 
1305  if (mmIt != metabMap.end())
1306  pMetabGlyph = mmIt->second;
1307 
1309  }
1310 
1311  if (!pMetabGlyph)
1312  continue;
1313 
1315  //pResult->setModelObjectKey(modelobjectkey);
1316  pRefGlyph->setMetabGlyphKey(pMetabGlyph->getKey());
1317  pRefGlyph->setRole(role);
1318  pReactionGlyph->addMetabReferenceGlyph(pRefGlyph);
1319  } //modifiers
1320  } //reactions
1321 
1322  //rules
1323  size_t i;
1324 
1325  for (i = 0; i < pResult->getListOfMetaboliteGlyphs().size(); ++i)
1326  {
1327  const CLMetabGlyph* pMetabGlyph = pResult->getListOfMetaboliteGlyphs()[i];
1328  const CMetab* pMetab = dynamic_cast<const CMetab*>(pMetabGlyph->getModelObject());
1329 
1330  if (!pMetab)
1331  continue;
1332 
1333  if (pMetab->getStatus() == CModelEntity::ODE || pMetab->getStatus() == CModelEntity::ASSIGNMENT)
1334  {
1335  CLGeneralGlyph* pGG = new CLGeneralGlyph;
1336  pGG->setDimensions(CLDimensions(10, 10));
1337  pGG->setObjectRole("rule");
1338 
1339  pResult->addGeneralGlyph(pGG);
1340 
1341  CLReferenceGlyph* pRefGlyph = new CLReferenceGlyph;
1342  pRefGlyph->setDimensions(CLDimensions(10, 10));
1343  pRefGlyph->setTargetGlyphKey(pMetabGlyph->getKey());
1344  pRefGlyph->setRole("rule connection");
1345  pGG->addReferenceGlyph(pRefGlyph);
1346  }
1347  }
1348 
1349  //after all other glyphs are created, create the compartment glyphs
1350  double xxx = 0;
1351  std::set<const CCompartment*>::const_iterator compIt;
1352 
1353  for (compIt = compartments.begin(); compIt != compartments.end(); ++compIt)
1354  {
1355  double compSize = 10000;
1356  std::map<const CCompartment*, CompartmentInfo>::const_iterator ccIt;
1357  ccIt = compInfo.find(*compIt);
1358 
1359  if (ccIt != compInfo.end())
1360  {
1361  //some glyphs are placed inside this compartment glyph
1362  compSize = ccIt->second.mAreaSum * 40;
1363  }
1364 
1365  //create the glyph
1366  CLCompartmentGlyph* pCompGlyph = new CLCompartmentGlyph;
1367  pCompGlyph->setModelObjectKey((*compIt)->getKey());
1368  pCompGlyph->setDimensions(CLDimensions(CLDimensions(sqrt(compSize), sqrt(compSize))));
1369  pCompGlyph->setPosition(CLPoint(xxx, 5));
1370  xxx += sqrt(compSize) + 10;
1371 
1372  pResult->addCompartmentGlyph(pCompGlyph);
1373  }
1374 
1375  //
1376  // double sss = sqrt(compInfo[NULL].mAreaSum * 40);
1377  //
1378  // // determine and set the layout dimensions
1379  // CLBoundingBox box = pResult->calculateBoundingBox();
1380  // if (box.getDimensions().getWidth() < sss)
1381  // box.getDimensions().setWidth(sss);
1382  //
1383  // if (box.getDimensions().getHeight() < sss)
1384  // box.getDimensions().setHeight(sss);
1385  //
1386  // pResult->setDimensions(CLDimensions(box.getDimensions().getWidth() + 30.0, box.getDimensions().getHeight() + 30.0));
1387 
1388  // randomize
1389  CCopasiSpringLayout l(pResult, mParams);
1390  l.randomize();
1391 
1392  // determine and set the layout dimensions
1393  CLBoundingBox box = pResult->calculateBoundingBox();
1394  pResult->setDimensions(CLDimensions(box.getDimensions().getWidth() + 30.0, box.getDimensions().getHeight() + 30.0));
1395 
1396  return pResult;
1397 }
void addReactionGlyph(CLReactionGlyph *glyph)
Definition: CLayout.cpp:251
bool initFromLayout(CLayout *layout, Parameters *ppp)
performs all initializations that are later needed to calculate the potential
const CCopasiVector< CLTextGlyph > & getListOfTextGlyphs() const
Definition: CLayout.h:120
const C_FLOAT64 & getWidth() const
Definition: CLBase.h:211
static unsigned C_INT32 getSystemSeed()
Definition: CRandom.cpp:136
CCopasiSpringLayout(CLayout *layout, Parameters *ppp=NULL)
void addGeneralGlyph(CLGeneralGlyph *glyph)
Definition: CLayout.cpp:263
const CLBoundingBox & getBoundingBox() const
void addReferenceGlyph(CLReferenceGlyph *glyph)
virtual const std::vector< UpdateAction > & getUpdateActions() const
std::vector< double > mInitialState
virtual size_t size() const
const C_FLOAT64 & getX() const
iterator begin()
const std::vector< CLLineSegment > & getCurveSegments() const
Definition: CLCurve.h:154
void addMetabReferenceGlyph(CLMetabReferenceGlyph *glyph)
void setDimensions(const CLDimensions &d)
Definition: CLayout.h:77
void randomlyPlaceGlyphInDimensions(CLGraphicalObject *pGl, const CLDimensions *pContainer, CRandom *pRandom)
void setDimensions(const CLDimensions &d)
double potSecondOrderEdge(const CLMetabReferenceGlyph &e1, const CLMetabReferenceGlyph &e2, double &dist) const
const CLPoint & getPosition() const
static double distance(const double &x1, const double &y1, const double &x2, const double &y2)
CLGraphicalObject * getTargetGlyph() const
double potEdge(const CLMetabReferenceGlyph &e, const CLReactionGlyph &r) const
void setTargetGlyphKey(const std::string &k)
Definition: CMetab.h:178
void addMetaboliteGlyph(CLMetabGlyph *glyph)
Definition: CLayout.cpp:245
const CCopasiVector< CLCompartmentGlyph > & getListOfCompartmentGlyphs() const
Definition: CLayout.h:81
virtual const std::string & getKey() const
void setModelObjectKey(const std::string &k)
const CLDimensions & getDimensions() const
Definition: CLBase.h:266
void addTextGlyph(CLTextGlyph *glyph)
Definition: CLayout.cpp:257
double potSpeciesCompartment(const CLMetabGlyph &s, const CLCompartmentGlyph &c) const
std::vector< UpdateAction > mUpdateActions
this is the list of all update actions that have to be performed during setState(); ...
double potGeneralEdge(const CLReferenceGlyph &e, const CLGeneralGlyph &r) const
CLPoint borderProjection(CLGraphicalObject *go, const CLPoint &p, double d)
iterator end()
static CRandom * createGenerator(CRandom::Type type=CRandom::mt19937, unsigned C_INT32 seed=0)
Definition: CRandom.cpp:49
void addPositionVariables(CLGraphicalObject *pGO)
create variables for the position of a species glyph
virtual C_FLOAT64 getRandomCC()
Definition: CRandom.cpp:235
const C_FLOAT64 & getX() const
Definition: CLBase.h:83
Definition: CLBase.h:54
virtual const std::string & getKey() const
static CLayout * createLayout(CCopasiContainer *parent, const std::set< const CCompartment * > &compartments, const std::set< const CReaction * > &reactions, const std::set< const CMetab * > &metabs, const std::set< const CMetab * > &sideMetabs, Parameters *mParams=NULL)
void calculateAndAssignBounds()
Definition: CLayout.cpp:955
void placeTextGlyphs(CLayout *pLayout)
const CCopasiVector< CLMetabGlyph > & getListOfMetaboliteGlyphs() const
Definition: CLayout.h:94
const CCopasiVector< CLReferenceGlyph > & getListOfReferenceGlyphs() const
C_FLOAT64 dot(const CLPoint &rhs) const
Definition: CLBase.h:135
void addCompartmentVariables(CLCompartmentGlyph *cg)
create variables for size and position of a compartment glyph
void addCurveSegment(const CLLineSegment &ls)
Definition: CLCurve.cpp:101
CLBoundingBox calculateBoundingBox() const
Definition: CLayout.cpp:684
void setGraphicalObjectKey(const std::string &k)
Definition: CLGlyphs.cpp:338
CLPoint getCenter() const
Definition: CLBase.h:269
virtual double getPotential()
CLMetabGlyph * getMetabGlyph() const
std::vector< CoordinateRelation > mFixedRelations
a list of fixed positon relations between objects. Should be constructed in initFromLayout() ...
double potReactionReaction(const CLReactionGlyph &a, const CLReactionGlyph &b) const
std::vector< double > mMassVector
const CCopasiVector< CLGeneralGlyph > & getListOfGeneralGlyphs() const
Definition: CLayout.h:133
void setPosition(const CLPoint &p)
const CArrayAnnotation * pResult
const C_FLOAT64 & getWidth() const
void addCompartmentGlyph(CLCompartmentGlyph *glyph)
Definition: CLayout.cpp:239
static double bound_distance(const double &x1, const double &y1, const double &x2, const double &y2, const double &max)
CLGraphicalObject * getGraphicalObject() const
Definition: CLGlyphs.cpp:262
this describes one update action that has to be performed during setState()
void setMetabGlyphKey(const std::string &k)
const C_FLOAT64 & getY() const
Definition: CLBase.h:84
const C_FLOAT64 & getY() const
CCopasiObject * getModelObject() const
double potReactionCompartment(const CLReactionGlyph &r, const CLCompartmentGlyph &c) const
void setObjectRole(const std::string &role)
const C_FLOAT64 & getHeight() const
Definition: CLBase.h:212
#define C_FLOAT64
Definition: copasi.h:92
std::map< CLBase *, CLCompartmentGlyph * > mCompartmentMap
this map contains information about the compartment glyph a given glyph is located in ...
double potSpeciesSpecies(const CLMetabGlyph &a, const CLMetabGlyph &b) const
void setRole(const std::string &r)
void scale(const double &scaleFactor)
Definition: CLBase.h:95
virtual const std::vector< double > & getInitialValues() const
double potSpeciesReaction(const CLMetabGlyph &a, const CLReactionGlyph &b) const
void add(double area)
const CCopasiVector< CLMetabReferenceGlyph > & getListOfMetabReferenceGlyphs() const
void addReactionVariables(CLReactionGlyph *rg)
create variables for the position of a reaction glyph
const CModelEntity::Status & getStatus() const
void randomlyPlaceGlyphInCompartmentGlyph(CLGraphicalObject *pGl, const CLGraphicalObject *pContainer, CRandom *pRandom)
const CLDimensions & getDimensions() const
const C_FLOAT64 & getHeight() const
const CCompartment * getCompartment() const
Definition: CMetab.cpp:222
const CLCurve & getCurve() const
size_t getNumCurveSegments() const
Definition: CLCurve.h:168
void clear()
Definition: CLCurve.cpp:112
const CCopasiVector< CLReactionGlyph > & getListOfReactionGlyphs() const
Definition: CLayout.h:107
virtual bool setState(const std::vector< double > &vars)
const CLDimensions & getDimensions() const
Definition: CLayout.h:76
CLCompartmentGlyph * findCompartmentForReactionNode(CLReactionGlyph &r)
std::vector< VariableDescription > mVarDescription