Пример #1
0
  bool OBDepict::AddAtomLabels(AtomLabelType type)
  {
    d->painter->SetPenColor(OBColor("red"));
    d->painter->SetFillColor(OBColor("red"));
    d->painter->SetFontSize((int)(GetFontSize() * 0.8));// smaller text
    OBAtomIterator i;
    for (OBAtom *atom = d->mol->BeginAtom(i); atom; atom = d->mol->NextAtom(i)) {
      vector3 pos(atom->GetVector());
      std::stringstream ss;
      switch (type) {
        case AtomId:
          ss << atom->GetId();
          d->painter->DrawText(pos.x(), pos.y(), ss.str());
          break;
        case AtomSymmetryClass:
          ss << GetAtomSymClass(atom);
          d->painter->DrawText(pos.x(), pos.y(), ss.str());
          break;
        case AtomIndex:
          ss << atom->GetIdx();
          d->painter->DrawText(pos.x(), pos.y(), ss.str());
          break;

        default:
          break;
      }
    }

    return true;    
  }
Пример #2
0
  void CairoPainter::NewCanvas(double width, double height)
  {
    double titleheight = m_title.empty() ? 0.0 : 16.0;
    if (m_index == 1) {
      // create new surface to paint on
      if(m_cropping) {
        double ratio = width / height;
        if(ratio > 1.0)
          m_height = m_height / ratio;
        else
          m_width = m_width * ratio;
      }
      m_surface = cairo_image_surface_create(CAIRO_FORMAT_ARGB32, static_cast<int> (m_width), static_cast<int> (m_height));
      m_cairo = cairo_create(m_surface);
      if(m_transparent)
        cairo_set_source_rgba (m_cairo, 0.0, 0.0, 0.0, 0.0);
      else {
        OBColor bg = OBColor(m_fillcolor);
        cairo_set_source_rgb (m_cairo, bg.red, bg.green, bg.blue);
      }
      
      cairo_paint (m_cairo);
      cairo_set_line_width(m_cairo, m_pen_width);
    }
    else {
      // reset transformation matrix
      cairo_identity_matrix(m_cairo);
    }

    // Work out some things!
    double cellwidth = m_width/m_ncols;
    double cellheight = m_height/m_nrows;
    int row = (m_index - 1)/m_ncols + 1;
    int col = m_index - ((row-1)*m_ncols);

    // Work out the scaling factor
    double scale_x = cellwidth / (double) width;
    double scale_y = (cellheight-titleheight) / (double) height; // Leave some extra space for the title if present
    double scale = std::min(scale_x, scale_y);

    // Add the title
    if (!m_title.empty()) {
      this->SetPenColor(OBColor(m_bondcolor));
      this->SetFontSize(static_cast<int>(16.0));
      OBFontMetrics fm = this->GetFontMetrics(m_title);
      this->DrawText(cellwidth/2.0 - fm.width/2.0 + cellwidth*(col-1),
                     cellheight - fm.height * 0.25 + cellheight*(row-1), m_title);
    }

    // Translate the over-scaled dimension into the centre
    if (scale < scale_y)
      cairo_translate(m_cairo, 0 + cellwidth*(col-1), cellheight/2.0 - scale*height/2.0 + cellheight*(row-1));
    else
      cairo_translate(m_cairo, cellwidth/2.0 - scale*width/2.0 + cellwidth*(col-1), 0 + cellheight*(row-1));
    cairo_scale(m_cairo, scale, scale); // Set a scaling transformation
  }
Пример #3
0
bool SVGFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
{
  OBMol* pmol = dynamic_cast<OBMol*>(pOb);
  if(!pmol)
    return false;
  ostream &ofs = *pConv->GetOutStream();

  //Check for option for single mol in fixed size image
  const char* fixedpx = pConv->IsOption("P");
  if(!fixedpx)
    fixedpx= pConv->IsOption("px", OBConversion::GENOPTIONS);
  //If WriteMolecule called directly, e.g. from OBConversion::Write()
  //the default mode is a fixed image size of 200px square
  if(!fixedpx && !pConv->IsOption("svgwritechemobject"))
    fixedpx = "200";
  if(fixedpx)
  {
    _nmax = _nrows = _ncols = 1;
    pConv->AddOption("j");
    pConv->SetLast(true);
    pConv->SetOutputIndex(1);
  }

  //*** Coordinate generation ***
  //Generate coordinates only if no existing 2D coordinates
  if( (pConv->IsOption("y") || !pmol->Has2D(true)) && !pConv->IsOption("n") )
  {
    OBOp* pOp = OBOp::FindType("gen2D");
    if(!pOp)
    {
      obErrorLog.ThrowError("SVGFormat", "gen2D not found", obError, onceOnly);
      return false;
    }
    if(!pOp->Do(pmol))
    {
      obErrorLog.ThrowError("SVGFormat", string(pmol->GetTitle()) + "- Coordinate generation unsuccessful", obError);
      return false;
    }
  }
  if(!pmol->Has2D() && pmol->NumAtoms()>1)//allows 3D coordinates (if passed by -xn above)
  {
    string mes("Molecule ");
    mes += pmol->GetTitle();
    mes += " needs 2D coordinates to display in SVGformat";
    obErrorLog.ThrowError("SVGFormat", mes, obError);
    return false;
  }
  
  bool hasTable = (_nrows || _ncols);

  bool transparent=false;
  string background, bondcolor;
  const char* bg = pConv->IsOption("b");
  background = bg ? "black" : "white";
  bondcolor  = bg ? "white" : "black";
  if(bg && (!strcmp(bg, "none") || bg[0]=='0'))
  {
    transparent = true;
    bondcolor = "gray";
  }
  const char* bcol = pConv->IsOption("B");
  if(bcol && *bcol)
    bondcolor = bcol;
  if(bg && *bg)
    background = bg;
  
  if(pConv->GetOutputIndex()==1 || fixedpx)
  {
    //For the first molecule...
    if(hasTable)
    {
      //multiple molecules - use a table
      //Outer svg has viewbox for 0 0 100 100 or adjusted for table shape,
      //and no width or height - it uses the whole of its containing element.
      //Inner svg with width, height, x, y of table cell,
      //and viewbox to match molecule min and max x and y
      if(!pConv->IsOption("x"))
        ofs << "<?xml version=\"1.0\"?>\n";

      ofs << "<svg version=\"1.1\" id=\"topsvg\"\n"
             "xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
             "xmlns:cml=\"http://www.xml-cml.org/schema\" ";

      //*** Outer viewbox ***
      double vbwidth=100, vbheight=100;
      if (_nrows>_ncols)
        vbwidth = (100*_ncols)/_nrows;
      else if(_ncols>_nrows)
        vbheight = (100*_nrows)/_ncols;

      if(fixedpx)//fixed size image
        ofs << "x=\"0\" y=\"0\" width=\"" << fixedpx << "px\" height=\"" << fixedpx <<"px\" ";
      else
        ofs << "x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" ";
      
      ofs << "viewBox=\"0 0 " << vbwidth << ' ' << vbheight << "\">\n";

      ofs << "<title>OBDepict</title>\n";
      // Draw the background unless transparent
      if(!transparent)
        ofs << "<rect x=\"0\" y=\"0\" width=\"" << vbwidth << "\" height=\"" << vbheight
            << "\" fill=\"" << background << "\"/>\n";
    }
  }

  //All mols
  double cellsize;
  if(hasTable)
  {
    //*** Parameter for inner svg ***
    int nc = _ncols ? _ncols : 1;
    int nr = (_nrows ? _nrows : 1);
    cellsize = 100. / std::max(nc, nr);
    int indx = pConv->GetOutputIndex() - 1;
    double innerX  = (indx % nc) * cellsize;
    double innerY  = (indx / nc) * cellsize;

    // Change the background in this cell if the condition in the first
    // parameter of  the -xh option is met. Use a default color if
    // the highlight color is not specified in the second parameter.
    const char* htxt = pConv->IsOption("h");
    if(htxt)
    {
      vector<string> vec;
      tokenize(vec, htxt);
      string highlight(vec.size()>1 ? vec[1] : "#f4f0ff");
      std::istringstream conditionText(vec[0]);
      if(OBDescriptor::FilterCompare(pOb, conditionText, false))
        //Still in outer <svg>, unfortunately
        ofs << "<rect x=\"" << innerX << "\" y=\"" << innerY
            << "\" width=\"" << cellsize << "\" height=\"" << cellsize
            << "\" fill=\"" << highlight << "\"/>\n";
    }

    //*** Write molecule name ***
    if(!pConv->IsOption("d"))
      ofs << "<text text-anchor=\"middle\" font-size=\"" << 0.06*cellsize << "\""
      << " fill =\"" << bondcolor << "\" font-family=\"sans-serif\"\n"
      << "x=\"" << innerX + cellsize * 0.5 << "\" y=\"" << innerY + cellsize - 2.0/nr << "\" >"
      << pmol->GetTitle() << "</text>\n";

    SVGPainter painter(*pConv->GetOutStream(), true, cellsize,cellsize,innerX,innerY);
    OBDepict depictor(&painter);

    if(!pConv->IsOption("C"))
      depictor.SetOption(OBDepict::drawTermC);// on by default
    if(pConv->IsOption("a"))
      depictor.SetOption(OBDepict::drawAllC);

    if(pConv->IsOption("A"))
    {
      AliasData::RevertToAliasForm(*pmol);
      depictor.SetAliasMode();
    }
    painter.SetFontFamily("sans-serif");
    painter.SetPenColor(OBColor(bondcolor));
    depictor.SetBondColor(bondcolor);
    if(pConv->IsOption("t"))
      painter.SetPenWidth(4);
    else
      painter.SetPenWidth(2);

    //No element-specific atom coloring if requested
    if(pConv->IsOption("u"))
      depictor.SetOption(OBDepict::bwAtoms);
    if(!pConv->IsOption("U"))
      depictor.SetOption(OBDepict::internalColor);
    if(pConv->IsOption("s"))
      depictor.SetOption(OBDepict::asymmetricDoubleBond);

    depictor.DrawMolecule(pmol);

    //Draw atom indices if requested
    if(pConv->IsOption("i"))
      depictor.AddAtomLabels(OBDepict::AtomIndex);

    //Embed CML of molecule if requested
    if(pConv->IsOption("e"))
      EmbedCML(pmol,pConv);
  }
  else //single molecule
  {
    //Nothing written until DrawMolecule call
    //Final </svg> written at the end of this block (painter destructor)
    //This leads to some code duplication.
    double factor = 1.0;
    SVGPainter painter(*pConv->GetOutStream(), false);
    OBDepict depictor(&painter);

    //Scale image by specifying the average bond length in pixels.
    const char* ppx = pConv->IsOption("p");
    if(!ppx)
      ppx= pConv->IsOption("px", OBConversion::GENOPTIONS);
    if(ppx)
    {
      double oldblen = depictor.GetBondLength();
      double newblen = atof(ppx);
      depictor.SetBondLength(newblen);
      factor = newblen / oldblen;
      //Scale bondspacing and font size by same factor
      depictor.SetBondSpacing(depictor.GetBondSpacing() * factor);
      depictor.SetFontSize((int)(depictor.GetFontSize() * factor));
    }

    if(pConv->IsOption("W"))
      depictor.SetOption(OBDepict::noWedgeHashGen);
    if(!pConv->IsOption("C"))
      depictor.SetOption(OBDepict::drawTermC);// on by default
    if(pConv->IsOption("a"))
      depictor.SetOption(OBDepict::drawAllC);

    if(pConv->IsOption("A"))
    {
      AliasData::RevertToAliasForm(*pmol);
      depictor.SetAliasMode();
    }

    painter.SetFontFamily("sans-serif");
    painter.SetPenColor(OBColor(bondcolor));
    depictor.SetBondColor(bondcolor);
    painter.SetFillColor(OBColor(background));
    if(pConv->IsOption("t"))
      painter.SetPenWidth(4);
    else
      painter.SetPenWidth(1);

    //No element-specific atom coloring if requested
    if(pConv->IsOption("u"))
      depictor.SetOption(OBDepict::bwAtoms);
    if(!pConv->IsOption("U"))
      depictor.SetOption(OBDepict::internalColor);
    if(pConv->IsOption("s"))
      depictor.SetOption(OBDepict::asymmetricDoubleBond);

    depictor.DrawMolecule(pmol);

    //Draw atom indices if requested
    if(pConv->IsOption("i"))
      depictor.AddAtomLabels(OBDepict::AtomIndex);


    //*** Write molecule name ***
    if(!pConv->IsOption("d"))
      ofs << "<text font-size=\"" << 18 * factor  << "\""
      << " fill =\"" << bondcolor << "\" font-family=\"sans-serif\"\n"
      << "x=\"" << 10 * factor << "\" y=\"" << 20 * factor << "\" >"
      << pmol->GetTitle() << "</text>\n";

    //*** Write page title name ***
    ofs << "<title>" << pmol->GetTitle() << " - OBDepict</title>\n";

    //Embed CML of molecule if requested
    if(pConv->IsOption("e"))
      EmbedCML(pmol,pConv);
  }

  if(hasTable && pConv->IsLast())
  {
    //Draw grid lines
    if(_nrows && _ncols && pConv->IsOption("l"))
    {
      for(int i=1; i<_nrows; ++i)
        ofs << " <line  stroke=\"gray\" stroke-width=\"0.1\" x1=\"0\" x2=\"100\""
            << " y1=\""  << i*cellsize << "\" y2=\""  << i*cellsize << "\"/>\n";
      for(int i=1; i<_ncols; ++i)
        ofs << " <line  stroke=\"gray\" stroke-width=\"0.1\" y1=\"0\" y2=\"100\""
            << " x1=\""  << i*cellsize << "\" x2=\""  << i*cellsize << "\"/>\n";
    }

    //Insert javascript for zooming and panning
    if(!pConv->IsOption("j"))
      EmbedScript(ofs);

    ofs << "</svg>\n" << endl;//Outer svg
  }
  return !fixedpx; // return false with fixed size image because only 1 mol
}
Пример #4
0
  bool OBDepict::DrawMolecule(OBMol *mol)
  {
    if (!d->painter)
      return false;

    d->mol = mol;

    double width=0.0, height=0.0;

    OBAtom *atom;
    OBBondIterator j;
    OBAtomIterator i;

    if(mol->NumAtoms()>0) {
      // scale bond lengths
      double bondLengthSum = 0.0;
      for (OBBond *bond = mol->BeginBond(j); bond; bond = mol->NextBond(j))
        bondLengthSum += bond->GetLength();
      const double averageBondLength = bondLengthSum / mol->NumBonds();
      const double f = mol->NumBonds() ? d->bondLength / averageBondLength : 1.0;
      for (atom = mol->BeginAtom(i); atom; atom = mol->NextAtom(i))
        atom->SetVector(atom->GetX() * f, atom->GetY() * f, 0.0);

      // find min/max values
      double min_x, max_x;
      double min_y, max_y;
      atom = mol->BeginAtom(i);
      min_x = max_x = atom->GetX();
      min_y = max_y = atom->GetY();
      for (atom = mol->NextAtom(i); atom; atom = mol->NextAtom(i)) {
        min_x = std::min(min_x, atom->GetX());
        max_x = std::max(max_x, atom->GetX());
        min_y = std::min(min_y, atom->GetY());
        max_y = std::max(max_y, atom->GetY());
      }

      const double margin = 40.0;
      // translate all atoms so the bottom-left atom is at margin,margin
      for (atom = mol->BeginAtom(i); atom; atom = mol->NextAtom(i))
        atom->SetVector(atom->GetX() - min_x + margin, atom->GetY() - min_y + margin, 0.0);

      width  = max_x - min_x + 2*margin;
      height = max_y - min_y + 2*margin;
      
      //d->painter->SetPenWidth(d->penWidth);
      //d->painter->SetPenColor(d->pen));
      //d->painter->SetFillColor(OBColor("black"));
    }

    d->painter->NewCanvas(width, height);
    
    // draw bonds
    if(d->options & genWedgeHash)
      d->SetWedgeAndHash(mol);
    for (OBBond *bond = mol->BeginBond(j); bond; bond = mol->NextBond(j)) {
      OBAtom *begin = bond->GetBeginAtom();
      OBAtom *end = bond->GetEndAtom();

      if((d->options & internalColor) && bond->HasData("color"))
        d->painter->SetPenColor(OBColor(bond->GetData("color")->GetValue()));
      else
        d->painter->SetPenColor(d->bondColor);

      if (bond->IsWedge()) {
        d->DrawWedge(begin, end);
      } else if (bond->IsHash()) {
        d->DrawHash(begin, end);
      } else if (!bond->IsInRing()) {
        d->DrawSimpleBond(begin, end, bond->GetBO());
      }
    }
    
    // draw ring bonds
    std::vector<OBRing*> rings(mol->GetSSSR());
    OBBitVec drawnBonds;
    for (std::vector<OBRing*>::iterator k = rings.begin(); k != rings.end(); ++k) {
      OBRing *ring = *k;
      std::vector<int> indexes = ring->_path;
      vector3 center(VZero);
      for (std::vector<int>::iterator l = indexes.begin(); l != indexes.end(); ++l) {
        center += mol->GetAtom(*l)->GetVector();        
      }
      center /= indexes.size();

      for (unsigned int l = 0; l < indexes.size(); ++l) {
        OBAtom *begin = mol->GetAtom(indexes[l]);
        OBAtom *end;
        if (l+1 < indexes.size())
          end = mol->GetAtom(indexes[l+1]);
        else
          end = mol->GetAtom(indexes[0]);

        OBBond *ringBond = mol->GetBond(begin, end);
        if (drawnBonds.BitIsSet(ringBond->GetId()))
          continue;

        if((d->options & internalColor) && ringBond->HasData("color"))
          d->painter->SetPenColor(OBColor(ringBond->GetData("color")->GetValue()));
        else
          d->painter->SetPenColor(d->bondColor);

        d->DrawRingBond(begin, end, center, ringBond->GetBO());
        drawnBonds.SetBitOn(ringBond->GetId());
      }

    }

    // draw atom labels
    for (atom = mol->BeginAtom(i); atom; atom = mol->NextAtom(i)) {
      double x = atom->GetX();
      double y = atom->GetY();

      int alignment = GetLabelAlignment(atom);
      bool rightAligned = false;
      switch (alignment) {
        case TopRight:
        case CenterRight:
        case BottomRight:
          rightAligned = true;
        default:
          break;
      }

      if((d->options & internalColor) && atom->HasData("color"))
        d->painter->SetPenColor(OBColor(atom->GetData("color")->GetValue()));
      else if(d->options & bwAtoms)
        d->painter->SetPenColor(d->bondColor);
      else
        d->painter->SetPenColor(OBColor(etab.GetRGB(atom->GetAtomicNum())));

      //charge and radical
      int charge = atom->GetFormalCharge();
      int spin = atom->GetSpinMultiplicity();
      if(charge || spin) {
        OBFontMetrics metrics = d->painter->GetFontMetrics("N");
        double yoffset = d->HasLabel(atom) ? 0.4 * metrics.height : 0.0;
        switch (GetLabelAlignment(atom)) {
          case TopCenter:
          case TopRight:
          case TopLeft:
          case CenterLeft:
          case CenterRight:
            yoffset = - 1.2 * metrics.height;
        }
        stringstream ss;
        if(charge) {
          if(abs(charge)!=1)
            ss << abs(charge);
          ss << (charge>0 ? "+" : "-") ;
        }
        if(spin) {
          ss << (spin==2 ? "." : "..");
          yoffset += 0.5 * metrics.height;
        }
        if(spin || charge<0)
          d->painter->SetFontSize(2 * metrics.fontSize);
        d->painter->DrawText(x-0.4*metrics.width, y-yoffset, ss.str());
        d->painter->SetFontSize(metrics.fontSize);//restore
      }
 
      if (atom->IsCarbon()) { 
        if(!(d->options & drawAllC))
        {
          if (atom->GetValence() > 1)
            continue;
          if ((atom->GetValence() == 1) && !(d->options & drawTermC))//!d->drawTerminalC)
            continue;
        }
      }

      stringstream ss;
      AliasData* ad = NULL;
      if(d->aliasMode && atom->HasData(AliasDataType))
        ad = static_cast<AliasData*>(atom->GetData(AliasDataType));
      
      //For unexpanded aliases use appropriate form of alias instead of element symbol, Hs, etc
      if(ad && !ad->IsExpanded())
      {
        ss <<ad->GetAlias(rightAligned);
        OBColor aliasColor = !ad->GetColor().empty() ? ad->GetColor() : d->bondColor; 
          d->painter->SetPenColor(aliasColor);
      }
      else {
        const char* atomSymbol;
        if(atom->IsHydrogen() && atom->GetIsotope()>1)
          atomSymbol = atom->GetIsotope()==2 ? "D" : "T";
        else
          atomSymbol = etab.GetSymbol(atom->GetAtomicNum());

        unsigned int hCount = atom->ImplicitHydrogenCount();
        // rightAligned:  
        //   false  CH3
        //   true   H3C
        if (hCount && rightAligned)
          ss << "H";
        if ((hCount > 1) && rightAligned)
          ss << hCount;
        ss << atomSymbol;
        if (hCount && !rightAligned)
          ss << "H";
        if ((hCount > 1) && !rightAligned)
          ss << hCount;
      }
      d->DrawAtomLabel(ss.str(), alignment, vector3(x, y, 0.0));
    }

    return true;
  }
Пример #5
0
bool SVGFormat::WriteSVG(OBConversion* pConv, vector<OBBase*>& molecules)
{

  bool ret=true;

  //Check for option for single mol in fixed size image
  const char* fixedpx = pConv->IsOption("P");
  if(!fixedpx)
    fixedpx= pConv->IsOption("px", OBConversion::GENOPTIONS);
  //If WriteMolecule called directly, e.g. from OBConversion::Write()
  //the default mode is a fixed image size of 200px square
  if(!fixedpx && molecules.size()==1)
    fixedpx = "200";
  if(fixedpx)
  {
    _nmax = _nrows = _ncols = 1;
    pConv->AddOption("j");
  }

  ostream &ofs = *pConv->GetOutStream();

  bool hasTable = (_nrows>1) || (_ncols>1);

  bool transparent=false;
  string background, bondcolor;
  const char* bg = pConv->IsOption("b");
  background = bg ? "black" : "white";
  bondcolor  = bg ? "white" : "black";
  if(bg && (!strcmp(bg, "none") || bg[0]=='0'))
  {
    transparent = true;
    bondcolor = "gray";
  }
  const char* bcol = pConv->IsOption("B");
  if(bcol && *bcol)
    bondcolor = bcol;
  if(bg && *bg)
    background = bg;

  if(!pConv->IsOption("x"))
  ofs << "<?xml version=\"1.0\"?>\n";

  ofs << "<svg version=\"1.1\" id=\"topsvg\"\n"
         "xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
         "xmlns:cml=\"http://www.xml-cml.org/schema\" ";
  double vbwidth=100, vbheight=100;
  if (_nrows>_ncols)
    vbwidth = (100*_ncols)/_nrows;
  else if(_ncols>_nrows)
    vbheight = (100*_nrows)/_ncols;

  if(fixedpx)//fixed size image
    ofs << "x=\"0\" y=\"0\" width=\"" << fixedpx << "px\" height=\"" << fixedpx <<"px\" ";
  else
    ofs << "x=\"0\" y=\"0\" width=\"100%\" height=\"100%\" ";

  ofs << "viewBox=\"0 0 " << vbwidth << ' ' << vbheight << "\">\n";

  if (hasTable)
    ofs << "<title>Multiple Molecules - Open Babel Depiction</title>\n";
  else if(molecules.size() == 1)
    ofs << "<title>" << molecules[0]->GetTitle() << " - Open Babel Depiction</title>\n";

  // Draw the background unless transparent
  if(!transparent)
    ofs << "<rect x=\"0\" y=\"0\" width=\"" << vbwidth << "\" height=\"" << vbheight
        << "\" fill=\"" << background << "\"/>\n";

  unsigned opts = 0;
  if(pConv->IsOption("u"))
    opts |= OBDepict::bwAtoms;
  if(!pConv->IsOption("U"))
   opts |= OBDepict::internalColor;
  if(!pConv->IsOption("C"))
    opts |= OBDepict::drawTermC;// on by default
  if(pConv->IsOption("a"))
    opts |= OBDepict::drawAllC;
  if(pConv->IsOption("W"))
    opts |= OBDepict::noWedgeHashGen;
  if(pConv->IsOption("s"))
   opts |= OBDepict::asymmetricDoubleBond;
  if(pConv->IsOption("X"))
    opts |= OBDepict::allExplicit;

  bool balldepict = false;
  if(pConv->IsOption("S"))
    balldepict = true;

  double factor = 1.0;
  int nc = _ncols ? _ncols : 1;
  int nr = (_nrows ? _nrows : 1);
  double cellsize = 100. / std::max(nc, nr);

  stringstream molfs;
  std::set<ColorGradient> gradients;

  OBOp* pOp = OBOp::FindType("gen2D");
  if(!pOp)
  {
    obErrorLog.ThrowError("SVGFormat", "gen2D not found", obError, onceOnly);
    return false;
  }

  vector<OBBase*>::iterator iter;
  int indx = 0;
  for(iter=_objects.begin(); ret && iter!=_objects.end(); ++iter,++indx)
  {
    OBMol* pmol = dynamic_cast<OBMol*>(*iter);

    if (!pmol)
      continue;
    //*** Coordinate generation ***
    //Generate coordinates only if no existing 2D coordinates
    if( (pConv->IsOption("y") || !pmol->Has2D(true)) && !pConv->IsOption("n") )
    {
      if(!pOp->Do(pmol))
      {
        obErrorLog.ThrowError("SVGFormat", string(pmol->GetTitle()) + "- Coordinate generation unsuccessful", obError);
        return false;
      }
    }
    if(!pmol->Has2D() && pmol->NumAtoms()>1)//allows 3D coordinates (if passed by -xn above)
    {
      string mes("Molecule ");
      mes += pmol->GetTitle();
      mes += " needs 2D coordinates to display in SVGformat";
      obErrorLog.ThrowError("SVGFormat", mes, obError);
      return false;
    }
    double innerX = 0.0;
    double innerY = 0.0;
    if(hasTable)
    {
      //*** Parameter for inner svg ***
      innerX  = (indx % nc) * cellsize;
      innerY  = (indx / nc) * cellsize;

      // Change the background in this cell if the condition in the first
      // parameter of  the -xh option is met. Use a default color if
      // the highlight color is not specified in the second parameter.
      const char* htxt = pConv->IsOption("h");
      if(htxt)
      {
        vector<string> vec;
        tokenize(vec, htxt);
        string highlight(vec.size()>1 ? vec[1] : "#f4f0ff");
        std::istringstream conditionText(vec[0]);
        if(OBDescriptor::FilterCompare(*iter, conditionText, false))
          //Still in outer <svg>, unfortunately
          molfs << "<rect x=\"" << innerX << "\" y=\"" << innerY
              << "\" width=\"" << cellsize << "\" height=\"" << cellsize
              << "\" fill=\"" << highlight << "\"/>\n";
      }
    }

    SVGPainter painter(molfs, &gradients, true, cellsize, cellsize);
    OBDepict depictor(&painter, balldepict);

    depictor.SetOption(opts);

    if(pConv->IsOption("A"))
    {
      AliasData::RevertToAliasForm(*pmol);
      depictor.SetAliasMode();
    }
    painter.SetFontFamily("sans-serif");
    painter.SetPenColor(OBColor(bondcolor));
    depictor.SetBondColor(bondcolor);
    if(pConv->IsOption("t"))
      painter.SetPenWidth(4);
    else
      painter.SetPenWidth(2);

    molfs << "<g transform=\"translate(" << innerX << "," << innerY << ")\">\n";

    ret = depictor.DrawMolecule(pmol);


    //Draw atom indices if requested
    if(pConv->IsOption("i"))
      depictor.AddAtomLabels(OBDepict::AtomIndex);

    painter.EndCanvas();


    //Embed CML of molecule if requested
    if(pConv->IsOption("e"))
      EmbedCML(pmol, pConv, &molfs);

    molfs <<"</g>\n";

    //*** Write molecule name ***
    if(!pConv->IsOption("d"))
      if(hasTable)
        molfs << "<text text-anchor=\"middle\" font-size=\"" << 0.06*cellsize << "\""
        << " fill =\"" << bondcolor << "\" font-family=\"sans-serif\"\n"
        << "x=\"" << innerX + cellsize * 0.5 << "\" y=\"" << innerY + cellsize - 2.0/nr << "\" >"
        << pmol->GetTitle() << "</text>\n";
      else
        molfs << "<text font-size=\"" << 18 * factor  << "\""
        << " fill =\"" << bondcolor << "\" font-family=\"sans-serif\"\n"
        << "x=\"" << 10 * factor << "\" y=\"" << 20 * factor << "\" >"
        << pmol->GetTitle() << "</text>\n";
  }

  // finally write svg defs
  SVGPainter painter(ofs, &gradients, true, cellsize,cellsize);
  painter.WriteDefs();

  // and stream back all molecule data
  ofs << molfs.str();

  //Draw grid lines
  if(hasTable && pConv->IsOption("l"))
  {
    for(int i=1; i<_nrows; ++i)
      ofs << " <line  stroke=\"gray\" stroke-width=\"0.1\" x1=\"0\" x2=\"100\""
          << " y1=\""  << i*cellsize << "\" y2=\""  << i*cellsize << "\"/>\n";
    for(int i=1; i<_ncols; ++i)
      ofs << " <line  stroke=\"gray\" stroke-width=\"0.1\" y1=\"0\" y2=\"100\""
          << " x1=\""  << i*cellsize << "\" x2=\""  << i*cellsize << "\"/>\n";
  }

  //Insert javascript for zooming and panning
  if(!pConv->IsOption("j"))
    EmbedScript(ofs);

  ofs << "</svg>\n";
return ret;
}
Пример #6
0
bool SVGFormat::WriteMolecule(OBBase* pOb, OBConversion* pConv)
{
    OBMol* pmol = dynamic_cast<OBMol*>(pOb);
    if(!pmol)
        return false;
    ostream &ofs = *pConv->GetOutStream();

    //*** Coordinate generation ***
    //Generate coordinates only if no existing 2D coordinates
    if( (pConv->IsOption("y") || !pmol->Has2D(true)) && !pConv->IsOption("n") )
    {
        OBOp* pOp = OBOp::FindType("gen2D");
        if(!pOp)
        {
            obErrorLog.ThrowError("SVGFormat", "gen2D not found", obError, onceOnly);
            return false;
        }
        if(!pOp->Do(pmol))
        {
            obErrorLog.ThrowError("SVGFormat", string(pmol->GetTitle()) + "- Coordinate generation unsuccessful", obError);
            return false;
        }
    }
    if(!pmol->Has2D() && pmol->NumAtoms()>1)//allows 3D coordinates (if passed by -xn above)
    {
        string mes("Molecule ");
        mes += pmol->GetTitle();
        mes += " needs 2D coordinates to display in SVGformat";
        obErrorLog.ThrowError("SVGFormat", mes, obError);
        return false;
    }

    bool hasTable = (_nrows || _ncols);

    string background = pConv->IsOption("b") ? "black" : "white";
    string bondcolor  = pConv->IsOption("b") ? "white" : "black";

    if(pConv->GetOutputIndex()==1)
    {
        //For the first molecule...
        if(hasTable)
        {
            //multiple molecules - use a table
            //Outer svg has viewbox for 0 0 100 100 or adjusted for table shape,
            //and no width or height - it uses the whole of its containing element.
            //Inner svg with width, height, x, y of table cell,
            //and viewbox to match molecule min and max x and y
            if(!pConv->IsOption("x"))
                ofs << "<?xml version=\"1.0\"?>\n";

            ofs << "<svg version=\"1.1\" id=\"topsvg\"\n"
                "xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\"\n"
                "xmlns:cml=\"http://www.xml-cml.org/schema\" ";

            //*** Outer viewbox ***
            double vbwidth=100, vbheight=100;
            if (_nrows>_ncols)
                vbwidth = (100*_ncols)/_nrows;
            else if(_ncols>_nrows)
                vbheight = (100*_nrows)/_ncols;
            ofs << "viewBox=\"0 0 " << vbwidth << ' ' << vbheight << "\">\n";

            ofs << "<title>OBDepict</title>\n";
            // Draw the background
            ofs << "<rect x=\"0\" y=\"0\" width=\"" << vbwidth << "\" height=\"" << vbheight
                << "\" fill=\"" << background << "\"/>\n";
        }
    }

    //All mols
    double cellsize;
    if(hasTable)
    {
        //*** Parameter for inner svg ***
        int nc = _ncols ? _ncols : 1;
        int nr = (_nrows ? _nrows : 1);
        cellsize = 100. / std::max(nc, nr);
        int indx = pConv->GetOutputIndex() - 1;
        double innerX  = (indx % nc) * cellsize;
        double innerY  = (indx / nc) * cellsize;

        //*** Write molecule name ***
        if(!pConv->IsOption("d"))
            ofs << "<text text-anchor=\"middle\" font-size=\"" << 0.06*cellsize << "\""
                << " fill =\"" << bondcolor << "\" font-family=\"sans-serif\"\n"
                << "x=\"" << innerX + cellsize * 0.5 << "\" y=\"" << innerY + cellsize - 2.0/nr << "\" >"
                << pmol->GetTitle() << "</text>\n";

        SVGPainter painter(*pConv->GetOutStream(), true, cellsize,cellsize,innerX,innerY);
        OBDepict depictor(&painter);

        if(pConv->IsOption("w"))
            depictor.SetOption(OBDepict::genWedgeHash);
        if(!pConv->IsOption("C"))
            depictor.SetOption(OBDepict::drawTermC);// on by default
        if(pConv->IsOption("a"))
            depictor.SetOption(OBDepict::drawAllC);

        if(pConv->IsOption("A"))
        {
            AliasData::RevertToAliasForm(*pmol);
            depictor.SetAliasMode();
        }
        painter.SetFontFamily("sans-serif");
        painter.SetPenColor(OBColor(bondcolor));
        depictor.SetBondColor(bondcolor);
        painter.SetPenWidth(2);

        //No element-specific atom coloring if requested
        if(pConv->IsOption("u"))
            depictor.SetOption(OBDepict::bwAtoms);
        if(!pConv->IsOption("U"))
            depictor.SetOption(OBDepict::internalColor);

        depictor.DrawMolecule(pmol);

        //Draw atom indices if requested
        if(pConv->IsOption("i"))
            depictor.AddAtomLabels(OBDepict::AtomIndex);

        //Embed CML of molecule if requested
        if(pConv->IsOption("e"))
            EmbedCML(pmol,pConv);
    }
    else //single molecule
    {
        //Nothing written until DrawMolecule call
        //Final </svg> written at the end of this block (painter destructor)
        //This leads to some code duplication.
        double factor = 1.0;
        SVGPainter painter(*pConv->GetOutStream());
        OBDepict depictor(&painter);

        //Scale image by specifying the average bond length in pixels.
        if(pConv->IsOption("p"))
        {
            double oldblen = depictor.GetBondLength();
            double newblen = atof(pConv->IsOption("p"));
            depictor.SetBondLength(newblen);
            factor = newblen / oldblen;
            //Scale bondspacing and font size by same factor
            depictor.SetBondSpacing(depictor.GetBondSpacing() * factor);
            depictor.SetFontSize((int)(depictor.GetFontSize() * factor));
        }

        if(!pConv->IsOption("w"))
            depictor.SetOption(OBDepict::genWedgeHash);
        if(!pConv->IsOption("C"))
            depictor.SetOption(OBDepict::drawTermC);// on by default
        if(pConv->IsOption("a"))
            depictor.SetOption(OBDepict::drawAllC);

        if(pConv->IsOption("A"))
        {
            AliasData::RevertToAliasForm(*pmol);
            depictor.SetAliasMode();
        }

        painter.SetFontFamily("sans-serif");
        painter.SetPenColor(OBColor(bondcolor));
        depictor.SetBondColor(bondcolor);
        painter.SetFillColor(OBColor(background));
        painter.SetPenWidth(1);

        //No element-specific atom coloring if requested
        if(pConv->IsOption("u"))
            depictor.SetOption(OBDepict::bwAtoms);
        if(!pConv->IsOption("U"))
            depictor.SetOption(OBDepict::internalColor);

        depictor.DrawMolecule(pmol);

        //Draw atom indices if requested
        if(pConv->IsOption("i"))
            depictor.AddAtomLabels(OBDepict::AtomIndex);


        //*** Write molecule name ***
        if(!pConv->IsOption("d"))
            ofs << "<text font-size=\"" << 18 * factor  << "\""
                << " fill =\"" << bondcolor << "\"\n"
                << "x=\"" << 140 * factor << "\" y=\"" << 20 * factor << "\" >"
                << pmol->GetTitle() << "</text>\n";

        //*** Write page title name ***
        ofs << "<title>" << pmol->GetTitle() << " - OBDepict</title>\n";

        //Embed CML of molecule if requested
        if(pConv->IsOption("e"))
            EmbedCML(pmol,pConv);
    }

    if(hasTable && pConv->IsLast())
    {
        //Draw grid lines
        if(_nrows && _ncols && pConv->IsOption("l"))
        {
            for(int i=1; i<_nrows; ++i)
                ofs << " <line  stroke=\"gray\" stroke-width=\"0.1\" x1=\"0\" x2=\"100\""
                    << " y1=\""  << i*cellsize << "\" y2=\""  << i*cellsize << "\"/>\n";
            for(int i=1; i<_ncols; ++i)
                ofs << " <line  stroke=\"gray\" stroke-width=\"0.1\" y1=\"0\" y2=\"100\""
                    << " x1=\""  << i*cellsize << "\" x2=\""  << i*cellsize << "\"/>\n";
        }

        //Insert javascript for zooming and panning
        if(!pConv->IsOption("j"))
            EmbedScript(ofs);

        ofs << "</svg>\n" << endl;//Outer svg
    }

    return true;
}
Пример #7
0
 SVGPainter::SVGPainter(ostream& ofs, std::set<ColorGradient>* gradients, bool withViewBox,
   double width, double height)
   :  m_ofs(ofs), m_withViewBox(withViewBox), m_width(width), m_height(height),
      m_Pencolor("black"), m_Fillcolor("white"), m_Gradientcolor(make_pair(OBColor("white"),OBColor("white"))), m_PenWidth(1),
      m_fontPointSize(16), m_isFillcolor(true), m_Gradients(gradients)  {}