void RefinementState::calcEnergy () { int i, j; float r; Vec2f d; energy = 0; for (i = _graph.vertexBegin(); i < _graph.vertexEnd(); i = _graph.vertexNext(i)) for (j = _graph.vertexBegin(); j < _graph.vertexEnd(); j = _graph.vertexNext(j)) { if (i == j) continue; d.diff(layout[i], layout[j]); r = d.lengthSqr(); if (r < 0.0001f) r = 5000000.f; else r = 1 / r; energy += r; } energy /= 2; }
// Translate branch on 0.1 of vector [v1,v2] void RefinementState::stretchBranch (const Filter &branch, const RefinementState &state, int v1_idx, int v2_idx, int val) { int i; float r, sh = 0.1f * val; const Vec2f &v1 = state.layout[v1_idx]; const Vec2f &v2 = state.layout[v2_idx]; Vec2f d; d.diff(v2, v1); r = d.length(); if (r < EPSILON) throw Error("too small edge"); d.scale(sh / r); if (branch.valid(v1_idx)) d.negate(); layout.clear_resize(state.layout.size()); for (i = _graph.vertexBegin(); i < _graph.vertexEnd(); i = _graph.vertexNext(i)) { if (!branch.valid(i)) layout[i].sum(state.layout[i], d); else layout[i] = state.layout[i]; } }
// Rotate branch around vertex v1 void RefinementState::rotateBranch (const Filter &branch, const RefinementState &state, int v_idx, float angle) { int i; float co, si; const Vec2f &v = state.layout[v_idx]; Vec2f d; angle = DEG2RAD(angle); co = cos(angle); si = sin(angle); layout.clear_resize(state.layout.size()); for (i = _graph.vertexBegin(); i < _graph.vertexEnd(); i = _graph.vertexNext(i)) { if (!branch.valid(i)) { d.diff(state.layout[i], v); d.rotate(si, co); layout[i].sum(d, v); } else layout[i] = state.layout[i]; } }
// Flip all verices from branch around (v1,v2) void RefinementState::flipBranch (const Filter &branch, const RefinementState &state, int v1_idx, int v2_idx) { int i; float r, t; const Vec2f &v1 = state.layout[v1_idx]; const Vec2f &v2 = state.layout[v2_idx]; Vec2f d; d.diff(v2, v1); r = d.lengthSqr(); if (r < 0.000000001f) throw Error("too small edge"); layout.clear_resize(state.layout.size()); for (i = _graph.vertexBegin(); i < _graph.vertexEnd(); i = _graph.vertexNext(i)) { if (!branch.valid(i)) { const Vec2f &vi = state.layout[i]; t = ((vi.x - v1.x) * d.x + (vi.y - v1.y) * d.y) / r; layout[i].set(2 * d.x * t + 2 * v1.x - vi.x, 2 * d.y * t + 2 * v1.y - vi.y); } else layout[i] = state.layout[i]; } }
void Vec2f::rotateAroundSegmentEnd (const Vec2f &a, const Vec2f &b, float angle) { Vec2f c; c.diff(a, b); c.rotate(angle); sum(b, c); }
// Calculate position by adding one unit with given angle to the segment void MoleculeLayoutGraph::_calculatePos (float phi, const Vec2f &v1, const Vec2f &v2, Vec2f &v) { float alpha; Vec2f dir; dir.diff(v2, v1); alpha = dir.tiltAngle(); alpha += phi; v.set(v1.x + cos(alpha), v1.y + sin(alpha)); }
RefinementState::RefinementState (MoleculeLayoutGraph &graph) : dist(0.f), energy(0), height(0.f), CP_INIT, TL_CP_GET(layout), _graph(graph) { } void RefinementState::calcDistance (int v1, int v2) { Vec2f d; d.diff(layout[v1], layout[v2]); dist = d.lengthSqr(); }
void MoleculeLayout::_updateDataSGroups () { // Move Data-SGroups with absolute coordinates according to new position QS_DEF(Array<int>, layout_graph_mapping); layout_graph_mapping.resize(_molecule.vertexEnd()); layout_graph_mapping.fffill(); for (int i = _layout_graph->vertexBegin(); i < _layout_graph->vertexEnd(); i = _layout_graph->vertexNext(i)) { int vi = _layout_graph->getVertexExtIdx(i); layout_graph_mapping[vi] = i; } for (int i = _molecule.sgroups.begin(); i != _molecule.sgroups.end(); i = _molecule.sgroups.next(i)) { SGroup &sg = _molecule.sgroups.getSGroup(i); if (sg.sgroup_type == SGroup::SG_TYPE_DAT) { DataSGroup &group = (DataSGroup &)sg; if (!group.relative) { Vec2f before; _molecule.getSGroupAtomsCenterPoint(group, before); Vec2f after; for (int j = 0; j < group.atoms.size(); j++) { int ai = group.atoms[j]; const LayoutVertex &vert = _layout_graph->getLayoutVertex(layout_graph_mapping[ai]); after.x += vert.pos.x; after.y += vert.pos.y; } if (group.atoms.size() != 0) after.scale(1.0f / group.atoms.size()); Vec2f delta; delta.diff(after, before); group.display_pos.add(delta); } } } }
void RenderGrid::draw () { _width = _cnvOpt.width; _height = _cnvOpt.height; _rc.fontsClear(); bool enableRefAtoms = refAtoms.size() > 0 && _factory.isItemMolecule(objs[0]); if (enableRefAtoms && refAtoms.size() != objs.size()) throw Error("Number of reference atoms should be same as the number of objects"); bool enableTitles = titles.size() > 0; if (enableTitles && titles.size() != objs.size()) throw Error("Number of titles should be same as the number of objects"); nRows = (objs.size() + nColumns - 1) / nColumns; commentSize.set(0,0); commentOffset = 0; if (comment >= 0) { _factory.getItem(comment).init(); _factory.getItem(comment).estimateSize(); commentSize.copy(_factory.getItem(comment).size); commentOffset = _cnvOpt.commentOffset; } maxsz.set(0,0); Vec2f refSizeLT, refSizeRB; Array<float> columnExtentLeft, columnExtentRight, rowExtentTop, rowExtentBottom; columnExtentLeft.clear_resize(nColumns); columnExtentRight.clear_resize(nColumns); columnExtentLeft.fill(0); columnExtentRight.fill(0); rowExtentTop.clear_resize(nRows); rowExtentBottom.clear_resize(nRows); rowExtentTop.fill(0); rowExtentBottom.fill(0); for (int i = 0; i < objs.size(); ++i) { if (enableRefAtoms) _factory.getItemMolecule(objs[i]).refAtom = refAtoms[i]; _factory.getItem(objs[i]).init(); _factory.getItem(objs[i]).setObjScale(_getObjScale(objs[i])); _factory.getItem(objs[i]).estimateSize(); if (enableRefAtoms) { const Vec2f& r = _factory.getItemMolecule(objs[i]).refAtomPos; Vec2f d; d.diff(_factory.getItemMolecule(objs[i]).size, r); refSizeLT.max(r); int col = i % nColumns; int row = i / nColumns; columnExtentLeft[col] = __max(columnExtentLeft[col], r.x); columnExtentRight[col] = __max(columnExtentRight[col], d.x); rowExtentTop[row] = __max(rowExtentTop[row], r.y); rowExtentBottom[row] = __max(rowExtentBottom[row], d.y); refSizeRB.max(d); } else { maxsz.max(_factory.getItem(objs[i]).size); } } if (enableRefAtoms) maxsz.sum(refSizeLT, refSizeRB); maxTitleSize.set(0,0); titleOffset = 0; if (enableTitles) { titleOffset = _cnvOpt.titleOffset; for (int i = 0; i < titles.size(); ++i) { _factory.getItem(titles[i]).init(); _factory.getItem(titles[i]).estimateSize(); maxTitleSize.max(_factory.getItem(titles[i]).size); } } outerMargin.x = (float)(minMarg + _cnvOpt.marginX); outerMargin.y = (float)(minMarg + _cnvOpt.marginY); _width = __min(_width, _getMaxWidth()); _height = __min(_height, _getMaxHeight()); scale = _getScale(_width, _height); if (_width < 1) _width = _getDefaultWidth(scale); if (_height < 1) _height = _getDefaultHeight(scale); _rc.initContext(_width, _height); cellsz.set(__max(maxsz.x * scale, maxTitleSize.x), maxsz.y * scale + maxTitleSize.y + titleOffset); clientArea.set(cellsz.x * nColumns + _cnvOpt.gridMarginX * (nColumns - 1), cellsz.y * nRows + _cnvOpt.gridMarginY * (nRows - 1)); _rc.init(); if (_cnvOpt.xOffset > 0 || _cnvOpt.yOffset > 0) _rc.translate((float)_cnvOpt.xOffset, (float)_cnvOpt.yOffset); _rc.translate(outerMargin.x, outerMargin.y); if (_cnvOpt.commentPos == COMMENT_POS_TOP) { _drawComment(); _rc.translate(0, (float)commentOffset); } _rc.storeTransform(); { _rc.translate((_width - clientArea.x) / 2 - outerMargin.x, (_height - commentSize.y - commentOffset - clientArea.y) / 2 - outerMargin.y); for (int i = 0; i < objs.size(); ++i) { _rc.storeTransform(); { int y = i / nColumns; int x = i % nColumns; Vec2f size(_factory.getItem(objs[i]).size); _rc.translate(x * (cellsz.x + _cnvOpt.gridMarginX), y * (cellsz.y + _cnvOpt.gridMarginY)); _rc.storeTransform(); { if (enableRefAtoms) { _rc.translate(0.5f * (cellsz.x - (columnExtentRight[x] + columnExtentLeft[x]) * scale), 0.5f * (maxsz.y - (rowExtentBottom[y]+ rowExtentTop[y])) * scale); const Vec2f r = _factory.getItemMolecule(objs[i]).refAtomPos; _rc.translate((columnExtentLeft[x] - r.x) * scale, (rowExtentTop[y] - r.y) * scale); } else { _rc.translate(0.5f * (cellsz.x - size.x * scale), 0.5f * (maxsz.y - size.y) * scale); } _rc.scale(scale); _factory.getItem(objs[i]).render(); } _rc.restoreTransform(); _rc.removeStoredTransform(); _rc.translate(0, maxsz.y * scale + titleOffset); if (enableTitles) { Vec2f titleSize(_factory.getItem(titles[i]).size); _rc.translate(_cnvOpt.titleAlign.getBboxRelativeOffset() * (cellsz.x - titleSize.x), 0.5f * (maxTitleSize.y - titleSize.y)); _factory.getItem(titles[i]).render(); } } _rc.restoreTransform(); _rc.removeStoredTransform(); } } _rc.restoreTransform(); _rc.removeStoredTransform(); if (_cnvOpt.commentPos == COMMENT_POS_BOTTOM) { _rc.translate(0, _height - commentOffset - commentSize.y - 2*outerMargin.y); _drawComment(); } }