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())); }
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. updateFixedRelations(); //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].getFunctionalRole() == CLMetabReferenceGlyph::SUBSTRATE) { CLMetabGlyph* metabGlyph = pRG->getListOfMetabReferenceGlyphs()[j].getMetabGlyph(); if (metabGlyph != NULL) { s_c += 1.0; s = s + metabGlyph->getBoundingBox().getCenter(); } } if (pRG->getListOfMetabReferenceGlyphs()[j].getFunctionalRole() == CLMetabReferenceGlyph::SIDESUBSTRATE) { CLMetabGlyph* metabGlyph = pRG->getListOfMetabReferenceGlyphs()[j].getMetabGlyph(); if (metabGlyph != NULL) { s_c += 0.1; s = s + metabGlyph->getBoundingBox().getCenter() * 0.1; } } if (pRG->getListOfMetabReferenceGlyphs()[j].getFunctionalRole() == CLMetabReferenceGlyph::PRODUCT) { CLMetabGlyph* metabGlyph = pRG->getListOfMetabReferenceGlyphs()[j].getMetabGlyph(); if (metabGlyph != NULL) { p_c += 1.0; p = p + metabGlyph->getBoundingBox().getCenter(); } } if (pRG->getListOfMetabReferenceGlyphs()[j].getFunctionalRole() == CLMetabReferenceGlyph::SIDEPRODUCT) { CLMetabGlyph* metabGlyph = pRG->getListOfMetabReferenceGlyphs()[j].getMetabGlyph(); if (metabGlyph != NULL) { p_c += 0.1; p = p + metabGlyph->getBoundingBox().getCenter() * 0.1; } } } CLPoint position = pRG->getPosition(); if (position.getX() == 0 && position.getY() == 0 && pRG->getDimensions().getWidth() == 0 && pRG->getDimensions().getHeight() == 0 && pRG->getCurve().getNumCurveSegments() > 0) { position = pRG->getCurve().getCurveSegments()[0].getStart(); pRG->setPosition(position); } if (s_c > 0) s = s * (1 / s_c); else { s = position; } if (p_c > 0) p = p * (1 / p_c); else p = position; 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 = position - (dir * 0.05); CLPoint reaction_p = position + (dir * 0.05); CLPoint reaction_m1 = position + ortho_dir * 10; CLPoint reaction_m2 = position - 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->getFunctionalRole()) { 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 (pMRG->getMetabGlyph() && 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)); } } } } //update the curves in the general glyph for (i = 0; i < mpLayout->getListOfGeneralGlyphs().size() ; ++i) { CLGeneralGlyph* pGG = &mpLayout->getListOfGeneralGlyphs()[i]; size_t j; for (j = 0; j < pGG->getListOfReferenceGlyphs().size(); ++j) { CLReferenceGlyph* pRG = &pGG->getListOfReferenceGlyphs()[j]; if (pRG->getCurve().getNumCurveSegments() == 0) continue; CLPoint refPoint = borderProjection(pRG->getTargetGlyph(), pRG->getBoundingBox().getCenter(), 5); pRG->getCurve().clear(); pRG->getCurve().addCurveSegment(CLLineSegment(refPoint, pRG->getBoundingBox().getCenter())); } } //calculate bounding box for the layout, or recenter the layout mpLayout->calculateAndAssignBounds(); }