double CCopasiSpringLayout::potEdge(const CLMetabReferenceGlyph & e, const CLReactionGlyph & r) const
{
  double dist = 70;

  if (e.getRole() == CLMetabReferenceGlyph::SIDESUBSTRATE || e.getRole() == CLMetabReferenceGlyph::SIDEPRODUCT)
    dist = 40;

  const CLMetabGlyph * pMG = e.getMetabGlyph();
  double tmp = distance(pMG->getX() + pMG->getWidth() / 2, pMG->getY() + pMG->getHeight() / 2,
                        r.getX() + r.getWidth() / 2, r.getY() + r.getHeight() / 2);

  if (e.getRole() == CLMetabReferenceGlyph::MODIFIER)
    return 0.3 * pow(tmp - dist, 2);
  else
    return pow(tmp - dist, 2);
}
Beispiel #2
0
void CLayout::exportToDotFile(std::ostream & os) const
{
  os << "digraph G {\n";

  //species glyphs
  unsigned C_INT32 i, imax = mvMetabs.size();

  for (i = 0; i < imax; ++i)
    {
      writeDotNode(os, mvMetabs[i]->getKey(), mvMetabs[i]->getModelObjectDisplayName());
    }

  //reaction glyphs
  imax = mvReactions.size();

  for (i = 0; i < imax; ++i)
    {
      writeDotNode(os, mvReactions[i]->getKey() + "_S", "", 1);
      writeDotNode(os, mvReactions[i]->getKey() + "_P", "", 1);
      writeDotEdge(os, mvReactions[i]->getKey() + "_S", mvReactions[i]->getKey() + "_P", 1);

      unsigned C_INT j, jmax = mvReactions[i]->getListOfMetabReferenceGlyphs().size();

      for (j = 0; j < jmax; ++j)
        {
          CLMetabReferenceGlyph* mrg = mvReactions[i]->getListOfMetabReferenceGlyphs()[j];

          if (mrg->getRole() == CLMetabReferenceGlyph::SUBSTRATE)
            writeDotEdge(os, mrg->getMetabGlyphKey(), mvReactions[i]->getKey() + "_S");
          else if (mrg->getRole() == CLMetabReferenceGlyph::PRODUCT)
            writeDotEdge(os, mvReactions[i]->getKey() + "_P", mrg->getMetabGlyphKey());
        }
    }

  os << "}" << std::endl;
}
void CCopasiSpringLayout::finalizeState()
{
  unsigned int i;

  //update the positions of the dependent glyphs
  //this can be done here since we assume that those glyphs
  //do not affect the layout.
  std::vector<CoordinateRelation>::const_iterator it, itEnd = mFixedRelations.end();

  for (it = mFixedRelations.begin(); it != itEnd; ++it)
    it->target->setPosition(it->source->getPosition() + it->diff);

  //for now, only create curves for the reaction glyphs
  for (i = 0; i < mpLayout->getListOfReactionGlyphs().size() ; ++i)
    {
      CLReactionGlyph* pRG = mpLayout->getListOfReactionGlyphs()[i];

      //Determine the average position of substrates and products, giving less weight to side reactants
      CLPoint s, p;
      double s_c = 0; double p_c = 0;
      unsigned int j, jmax = pRG->getListOfMetabReferenceGlyphs().size();

      for (j = 0; j < jmax; ++j)
        {
          if (pRG->getListOfMetabReferenceGlyphs()[j]->getRole() == CLMetabReferenceGlyph::SUBSTRATE)
            {
              s_c += 1.0;
              s = s + pRG->getListOfMetabReferenceGlyphs()[j]->getMetabGlyph()->getBoundingBox().getCenter();
            }

          if (pRG->getListOfMetabReferenceGlyphs()[j]->getRole() == CLMetabReferenceGlyph::SIDESUBSTRATE)
            {
              s_c += 0.1;
              s = s + pRG->getListOfMetabReferenceGlyphs()[j]->getMetabGlyph()->getBoundingBox().getCenter() * 0.1;
            }

          if (pRG->getListOfMetabReferenceGlyphs()[j]->getRole() == CLMetabReferenceGlyph::PRODUCT)
            {
              p_c += 1.0;
              p = p + pRG->getListOfMetabReferenceGlyphs()[j]->getMetabGlyph()->getBoundingBox().getCenter();
            }

          if (pRG->getListOfMetabReferenceGlyphs()[j]->getRole() == CLMetabReferenceGlyph::SIDEPRODUCT)
            {
              p_c += 0.1;
              p = p + pRG->getListOfMetabReferenceGlyphs()[j]->getMetabGlyph()->getBoundingBox().getCenter() * 0.1;
            }
        }

      if (s_c > 0)
        s = s * (1 / s_c);
      else
        s = pRG->getPosition();

      if (p_c > 0)
        p = p * (1 / p_c);
      else
        p = pRG->getPosition();

      CLPoint dir = p - s; //overall direction of reaction

      if (dir.getX() == 0 && dir.getY() == 0)
        dir = CLPoint(1, 0);

      CLPoint ortho_dir = CLPoint(dir.getY(), -dir.getX());
      ortho_dir.scale(1 / sqrt(pow(ortho_dir.getX(), 2) + pow(ortho_dir.getY(), 2)));

      CLPoint reaction_s = pRG->getPosition() - (dir * 0.05);
      CLPoint reaction_p = pRG->getPosition() + (dir * 0.05);
      CLPoint reaction_m1 = pRG->getPosition() + ortho_dir * 10;
      CLPoint reaction_m2 = pRG->getPosition() - ortho_dir * 10;

      pRG->getCurve().clear();
      pRG->getCurve().addCurveSegment(CLLineSegment(reaction_s, reaction_p));

      for (j = 0; j < jmax; ++j)
        {
          //here we need to generate the curves for the MetabReferenceGlyphs.
          //we will need to consider the size of the glyphs, role of the metab in the reaction, etc.
          //For now, only a primitive implementation: TODO: improve
          CLMetabReferenceGlyph* pMRG = pRG->getListOfMetabReferenceGlyphs()[j];
          double direction;
          double modifierLength = -0.2;

          switch (pMRG->getRole())
            {
              case CLMetabReferenceGlyph::SUBSTRATE :
              case CLMetabReferenceGlyph::SIDESUBSTRATE :
              {
                direction = -0.1;
                CLPoint metabPoint = borderProjection(pMRG->getMetabGlyph(), reaction_s + dir * direction /*(modifierLength * 1.5)*/, 5);
                pMRG->getCurve().clear();
                pMRG->getCurve().addCurveSegment(CLLineSegment(reaction_s,
                                                 metabPoint,
                                                 reaction_s + dir * direction,
                                                 (reaction_s + dir * (direction * 1.5) + metabPoint) * 0.5));
              }
              break;

              case CLMetabReferenceGlyph::PRODUCT :
              case CLMetabReferenceGlyph::SIDEPRODUCT :
              {
                direction = 0.1;
                CLPoint metabPoint = borderProjection(pMRG->getMetabGlyph(), reaction_p + dir * direction /*(modifierLength * 1.5)*/, 5);
                pMRG->getCurve().clear();
                pMRG->getCurve().addCurveSegment(CLLineSegment(reaction_p,
                                                 metabPoint,
                                                 reaction_p + dir * direction,
                                                 (reaction_p + dir * (direction * 1.5) + metabPoint) * 0.5));
              }
              break;

              default:
              {
                CLPoint reactionPoint;

                if (ortho_dir.dot(pRG->getPosition() - pMRG->getMetabGlyph()->getPosition()) < 0)
                  {
                    direction = +10.0;
                    reactionPoint = reaction_m1;
                  }
                else
                  {
                    direction = -10.0;
                    reactionPoint = reaction_m2;
                  }

                CLPoint metabPoint = borderProjection(pMRG->getMetabGlyph(), reactionPoint + dir * 0 * direction /*(modifierLength * 1.5)*/, 5);
                pMRG->getCurve().clear();
                pMRG->getCurve().addCurveSegment(CLLineSegment(metabPoint,
                                                 reactionPoint,
                                                 (reactionPoint + dir * (0 * direction * 1.5) + metabPoint) * 0.5,
                                                 reactionPoint + ortho_dir * direction));
              }
            }
        }
    }

  //rearrange the text boxes
  //TODO

  //calculate bounding box for the layout, or recenter the layout
  //for (i = 0; i < mpLayout->getListOfSpeciesGlyphs().size() ; ++i)

  const CLBoundingBox &bounds =  mpLayout->calculateBoundingBox();

  mpLayout->setDimensions(CLDimensions(bounds.getPosition().getX() + bounds.getDimensions().getWidth(), bounds.getPosition().getY() + bounds.getDimensions().getHeight()));
}