Example #1
0
// 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];
   }
}
Example #2
0
void _getBounds (RenderParams& params, BaseMolecule &mol, Vec2f &min, Vec2f &max, float &scale)
{
   // Compute average bond length
   float avg_bond_length = 1;
   if (mol.edgeCount() > 0)
   {
      float bond_length_sum = 0;
      for (int i = mol.edgeBegin(); i != mol.edgeEnd(); i = mol.edgeNext(i))
      {
         const Edge& edge = mol.getEdge(i);
         const Vec3f &p1 = mol.getAtomXyz(edge.beg);
         const Vec3f &p2 = mol.getAtomXyz(edge.end);
         bond_length_sum += Vec3f::dist(p1, p2);
      }
      avg_bond_length = bond_length_sum / mol.edgeCount();
   }

   float bond_length = 1;
   if (params.cnvOpt.bondLength > 0)
      bond_length = params.cnvOpt.bondLength / 100.0f;

   scale = bond_length / avg_bond_length;

   for (int i = mol.vertexBegin(); i != mol.vertexEnd(); i = mol.vertexNext(i))
   {
      Vec3f &p = mol.getAtomXyz(i);
      Vec2f p2(p.x, p.y);

      if (i == mol.vertexBegin())
         min = max = p2;
      else
      {
         min.min(p2);
         max.max(p2);
      }
   }

   min.scale(scale);
   max.scale(scale);
}
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);
         }
      }
   }
}
Example #4
0
void Metalayout::adjustMol (BaseMolecule& mol, const Vec2f& min, const Vec2f& pos)
{
   float scaleFactor = getScaleFactor();

   // Compute center points for the data sgroups
   QS_DEF(Array<Vec2f>, data_centers);
   data_centers.resize(mol.data_sgroups.end());
   for (int i = mol.data_sgroups.begin(); i < mol.data_sgroups.end(); i = mol.data_sgroups.next(i))
   {
      BaseMolecule::DataSGroup &group = mol.data_sgroups[i];
      if (!group.relative)
         mol.getSGroupAtomsCenterPoint(group, data_centers[i]);
   }

   for (int i = mol.vertexBegin(); i < mol.vertexEnd(); i = mol.vertexNext(i))
   {
      Vec2f v;
      Vec2f::projectZ(v, mol.getAtomXyz(i));
      v.sub(min);
      v.scale(scaleFactor);
      v.add(pos);
      v.y = -v.y;
      mol.setAtomXyz(i, v.x, v.y, 0);
   }  

   // Adjust data-sgroup label positions with absolute coordinates
   for (int i = mol.data_sgroups.begin(); i < mol.data_sgroups.end(); i = mol.data_sgroups.next(i))
   {
      BaseMolecule::DataSGroup &group = mol.data_sgroups[i];
      if (!group.relative)
      {
         Vec2f new_center;
         mol.getSGroupAtomsCenterPoint(group, new_center);
         group.display_pos.add(new_center);
         group.display_pos.sub(data_centers[i]);
      }
   }
}
Example #5
0
void RenderParamCdxmlInterface::_renderMols (RenderParams& params)
{
   MoleculeCdxmlSaver saver(*params.rOpt.output);

   Array<BaseMolecule*> mols;
   Array<int> ids;

   if (params.mols.size() != 0)
      for (int i = 0; i < params.mols.size(); ++i)
         mols.push(params.mols[i]);
   else if (params.mol.get() != 0)
      mols.push(params.mol.get());

   Vec2f offset(0, 0);
   Array<float> column_widths;
   column_widths.resize(params.cnvOpt.gridColumnNumber);
   column_widths.fill(0);

   Array<float> title_widths;
   title_widths.resize(mols.size());
   title_widths.fill(0);

   Array<float> key_widths;
   key_widths.resize(mols.size());
   key_widths.fill(0);

   Array<float> prop_widths;
   prop_widths.resize(mols.size());
   prop_widths.fill(0);

   Array<Pos> positions;
   positions.resize(mols.size());

   Array<float> title_heights;
   title_heights.resize(mols.size());
   title_heights.fill(0);

   for (int mol_idx = 0; mol_idx < mols.size(); ++mol_idx)
   {
      int column = mol_idx % params.cnvOpt.gridColumnNumber;

      Pos &p = positions[mol_idx];
      _getBounds(params, mols[mol_idx]->asMolecule(), p.str_min, p.str_max, p.scale);

      float width = p.str_max.x - p.str_min.x;

      // Check titles width
      if (mol_idx < params.titles.size())
      {
         const Array<char> &title = params.titles[mol_idx];
        
         
         if (title.size() > 0)
         {
            int longest_line = _getLongestLine(title);

            // On average letters has width 6
            float letter_width = params.rOpt.titleFontFactor / 1.5f;

            float title_width = longest_line * letter_width / MoleculeCdxmlSaver::BOND_LENGTH;
            title_widths[mol_idx] = title_width;
            width = __max(width, title_width);
         }
      }
      if (params.rOpt.cdxml_context.get() != NULL) {
         RenderCdxmlContext& context = params.rOpt.cdxml_context.ref();
         if (context.enabled) {
            RenderCdxmlContext::PropertyData& data = context.property_data.at(mol_idx);
            float letter_width = context.propertyFontSize / 1.5f;
            int longest_line = _getLongestLineXml(data.propertyName);
            
            key_widths[mol_idx] = longest_line * letter_width / MoleculeCdxmlSaver::BOND_LENGTH;

            longest_line += _getLongestLineXml(data.propertyValue);
            float prop_width = longest_line * letter_width / MoleculeCdxmlSaver::BOND_LENGTH;
            prop_widths[mol_idx] = prop_width;
            
            width = __max(width, prop_width);
         }
      }

      column_widths[column] = __max(width, column_widths[column]);
   }

   float x_margins_base = 1.1f, y_margins_base = 1.1f;
   float x_grid_base = 1.5f;

   Array<float> column_offset;
   column_offset.resize(params.cnvOpt.gridColumnNumber);
   column_offset[0] = params.cnvOpt.marginX / 10.0f + x_margins_base;
   for (int i = 1; i < params.cnvOpt.gridColumnNumber; i++)
      column_offset[i] = column_offset[i - 1] + column_widths[i - 1] + x_grid_base;

   float page_y_offset_base = params.cnvOpt.marginY / 10.0f + y_margins_base;
   float row_y_offset = page_y_offset_base;
   int last_row = 0;
   float max_y = 0;

   float title_y = 0;

   // Get each structure bounds 
   int row_moved = 0;
   for (int mol_idx = 0; mol_idx < mols.size(); ++mol_idx)
   {
      Pos &p = positions[mol_idx];

      int column = mol_idx % params.cnvOpt.gridColumnNumber;
      int row = mol_idx / params.cnvOpt.gridColumnNumber;

      p.page_offset.x = column_offset[column];
      p.page_offset.y = row_y_offset;

      p.size.diff(p.str_max, p.str_min);
      p.all_size = p.size;
      
      if (mol_idx < params.titles.size())
      {
         const Array<char> &title = params.titles[mol_idx];
         if (title.size() > 0)
         {
            int lines = title.count('\n') + 1;
            float letter_height = params.rOpt.titleFontFactor / MoleculeCdxmlSaver::BOND_LENGTH;
            //float title_height = lines * saver.textLineHeight();
            //p.all_size.y += title_height + saver.textLineHeight(); // Add blank line
            float title_height = lines * letter_height;
            title_heights[mol_idx] = title_height;
            p.all_size.y += title_height + letter_height; // Add blank line
         }
      }
      if (params.rOpt.cdxml_context.get() != NULL) {
         RenderCdxmlContext& context = params.rOpt.cdxml_context.ref();
         if (context.enabled) {
            RenderCdxmlContext::PropertyData& data = context.property_data.at(mol_idx);
            int lines = data.propertyName.count('\n') + 1;

            float letter_height = params.rOpt.titleFontFactor / MoleculeCdxmlSaver::BOND_LENGTH;
            float prop_height = lines * letter_height;
            p.all_size.y += prop_height + letter_height; // Add blank line
         }
      }

      // Check that the structure is fully on a single page
      int pbegin = (int)(p.page_offset.y / saver.pageHeight());
      int pend = (int)((p.page_offset.y + p.all_size.y) / saver.pageHeight());
      // Additional check that we didn't moved this row before
      if (pbegin != pend && row_moved != row)
      {
         // Update starting row_y_offset for the whole row and start this row again
         row_y_offset = (pbegin + 1) * saver.pageHeight() + page_y_offset_base;
         mol_idx = row * params.cnvOpt.gridColumnNumber - 1;
         row_moved = row;
         continue;
      }

      p.offset.x = p.page_offset.x - p.str_min.x + (column_widths[column] - p.size.x) / 2;
      p.offset.y = -p.page_offset.y - p.str_max.y;

      p.title_offset_y = -p.page_offset.y - p.size.y - 1.0f;

      max_y = __max(max_y, p.page_offset.y + p.all_size.y);

      int next_row = (mol_idx + 1) / params.cnvOpt.gridColumnNumber;
      if (last_row != next_row)
      {
         row_y_offset = max_y + 1.0f;
         last_row = next_row;
      }
   }

   if (params.cnvOpt.comment.size() > 0)
   {
      int lines = params.cnvOpt.comment.count('\n') + 1;
      float comment_height = lines * 0.3f;
      max_y += 0.3f;
      title_y = max_y;
      max_y += comment_height;
   }

   MoleculeCdxmlSaver::Bounds b;
   b.min.set(0, 0);

   float w = column_offset[params.cnvOpt.gridColumnNumber - 1] + column_widths[params.cnvOpt.gridColumnNumber - 1];
   w += x_margins_base + params.cnvOpt.marginX / 10.0f;

   b.max.set(w, max_y + y_margins_base);
   saver.beginDocument(&b);
   
   Array<char> font_attr;
   ArrayOutput font_out(font_attr);
   
   font_out.printf("<s size=\"%f\"", params.rOpt.titleFontFactor);

   if (params.rOpt.cdxml_context.get() != NULL) {
      RenderCdxmlContext& context = params.rOpt.cdxml_context.ref();
      if (context.fonttable.size() > 0) {
         saver.addFontTable(context.fonttable.ptr());
      }
      if (context.colortable.size() > 0) {
         saver.addColorTable(context.colortable.ptr());
      }
      if (context.titleFont.size() > 0) {
         font_out.printf(" font=\"%s\"", context.titleFont.ptr());
      }
      if (context.titleFace.size() > 0) {
         font_out.printf(" face=\"%s\"", context.titleFace.ptr());
      }
   }
   font_out.printf(">");
   font_attr.push(0);

   //if (params.rOtitleFont.size() > 0) {
   //   font_out.printf("id=\"5\" charset=\"iso-8859-1\" name=\"%s\"", params.cnvOpt.titleFont.ptr());
   //   font_attr.push(0);
   //   saver.addFontTable(font_attr.ptr());
   //   /*
   //   * Set font as id 5 always
   //   */

   //   font_attr.clear();
   //   if (params.rOpt.titleFontFactor > 1)
   //      font_out.printf(" font=\"5\" size=\"%.0f\"", params.rOpt.titleFontFactor);
   //   else
   //      font_out.printf(" font=\"5\"");
   //} else {
   //   if (params.rOpt.titleFontFactor > 1)
   //      font_out.printf(" size=\"%.0f\"", params.rOpt.titleFontFactor);
   //}
   //font_attr.push(0);
   saver.beginPage(&b);
   Array<char> title_font;

   for (int mol_idx = 0; mol_idx < mols.size(); ++mol_idx)
   {
      int column = mol_idx % params.cnvOpt.gridColumnNumber;

      Pos &p = positions[mol_idx];
      Vec2f offset = p.offset;
      offset.scale(1 / p.scale);
      saver.saveMoleculeFragment(mols[mol_idx]->asMolecule(), offset, p.scale, -1, ids);
      
      if (mol_idx < params.titles.size())
      {
         const Array<char> &title = params.titles[mol_idx];
         
         if (title.size() > 0)
         {
            title_font.clear();
            title_font.readString(font_attr.ptr(), false);
            // Get title bounding box
            float x = params.cnvOpt.titleAlign.getAnchorPoint(p.page_offset.x, column_widths[column], title_widths[mol_idx]);

            const char *alignment_str = "";
            MultilineTextLayout alignment = params.cnvOpt.titleAlign;
            if (alignment.inbox_alignment == MultilineTextLayout::Center)
               alignment_str = "Center";
            if (alignment.inbox_alignment == MultilineTextLayout::Left)
               alignment_str = "Left";
            if (alignment.inbox_alignment == MultilineTextLayout::Right)
               alignment_str = "Right";

            Vec2f title_offset(x, p.title_offset_y);
            title_font.appendString(title.ptr(), true);
            title_font.appendString("</s>", true);

            saver.addCustomText(title_offset, alignment_str, params.rOpt.titleFontFactor, title_font.ptr());
         }
      }
      if (params.rOpt.cdxml_context.get() != NULL) {
         RenderCdxmlContext& context = params.rOpt.cdxml_context.ref();
         if (context.enabled) {
            RenderCdxmlContext::PropertyData& data = context.property_data.at(mol_idx);
            float prop_width = prop_widths[mol_idx];
            float key_width = key_widths[mol_idx];
            float prop_offset_y = p.title_offset_y - title_heights[mol_idx];
            float x = params.cnvOpt.titleAlign.getAnchorPoint(p.page_offset.x, column_widths[column], prop_width);

            float prop_offset_key = prop_width * 0.5f;
            float prop_offset_val = prop_offset_key - (prop_width - key_width);
            if (context.keyAlignment == RenderCdxmlContext::ALIGNMENT_LEFT) {
               Vec2f title_offset_key(x - prop_offset_key, prop_offset_y);
               Vec2f title_offset_val(x + prop_offset_val, prop_offset_y);
               saver.addCustomText(title_offset_key, "Left", context.propertyFontSize, data.propertyName.ptr());
               saver.addCustomText(title_offset_val, "Left", context.propertyFontSize, data.propertyValue.ptr());
            }
            else {
               Vec2f title_offset_key(x + prop_offset_val, prop_offset_y);
               Vec2f title_offset_val(x + prop_offset_val, prop_offset_y);
               saver.addCustomText(title_offset_key, "Right", context.propertyFontSize, data.propertyName.ptr());
               saver.addCustomText(title_offset_val, "Left", context.propertyFontSize, data.propertyValue.ptr());
            }
         }

      }
      
     
   }

   if (params.cnvOpt.comment.size() > 0)
   {
      Vec2f pos(b.max.x / 2, -title_y);
      saver.addText(pos, params.cnvOpt.comment.ptr());
   }

   saver.endPage();
   saver.endDocument();
}