/*

    Bist: a chemical drawing tool
    Copyright (C) 2008 Valerio Benfante

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#include <global.hpp>

#include <cstdio>



#include <cairo/cairo.h>
#include <pango/pangocairo.h>
#include <cairo_t_singleton.hpp>
#include <glib.h>


#include <FL/fl_draw.H>
#include <FL/Fl.H>
#include <FL/Fl_Double_Window.H>
#include <FL/Fl_Scroll.H>
#include <FL/Fl_Image.H>
#include <FL/Fl_Pixmap.H>

#include <interfacce.hpp>
#include <legame.hpp>
#include <etichetta.hpp>
#include <atomo.hpp>
#include <procedura.hpp>
#include <multiline_label.hpp>
#include <multifont_label.hpp>
#include <paragraph_text.hpp>
#include <gruppo.hpp>
#include <immagine.hpp>
#include <bist_plugin.hpp>
#include <mol_canvas.hpp>
#include <finestra_pr.hpp>

#include <util.hpp>

#include <prefs.hpp>


#include <substructure_search.hpp>

extern finestra_pr* MainWindow;

extern Preferences  __pref;



bool ordina_gruppo_id(gruppo uno, gruppo  altro){
  //  cout << "SORT GRUPPI!!!!!!!!!!!!!" << uno.id() << " " << altro.id() <<  endl;
  return uno.id() < altro.id();
}

int dummy_pf(atomo* da , atomo* fino, void* data, void* data2 ,void* data3){
  vector<bool>* visti=static_cast< vector<bool>* >(data);
  int* i=static_cast<int*>(data2);
  cout << "comp::" << *i << endl;
  (*visti)[*i]=true;
  return 0;
}

/*********************gruppo*********************/


gruppo::gruppo(const gruppo& altro)
    :_id_gruppo(altro._id_gruppo),
     _tipo_gruppo(altro._tipo_gruppo),
     _angolorot(altro._angolorot),
     _xpivot(altro._xpivot),
     _ypivot(altro._ypivot)

  {

    _atomi.erase(_atomi.begin(),_atomi.end());
    _procedure.erase(_procedure.begin(),_procedure.end());

    for(unsigned int i=0;i<(altro._procedure).size();i++){

      switch(((altro._procedure)[i])->tipo()){
      case PROC_ARC:
	{
	  proc_arc* arc=dynamic_cast<proc_arc*>((altro._procedure)[i]);
	  proc_arc* arcnw=new proc_arc(arc);
	  arcnw->aggiungi_genitore(this);
	  _procedure.push_back(arcnw);
	  break;
	}
      case PROC_ARROW:
	{

	  proc_arrow* arr=dynamic_cast<proc_arrow*>((altro._procedure)[i]);
	  proc_arrow* arrnw=new proc_arrow(arr);
	  arrnw->aggiungi_genitore(this);
	  _procedure.push_back(arrnw);
	  break;
	}


      case PROC_BEZIER:
	{

	  proc_bezier* bez=dynamic_cast<proc_bezier*>((altro._procedure)[i]);
	  proc_bezier* beznw= new proc_bezier(bez);
	  beznw->aggiungi_genitore(this);
	  _procedure.push_back(beznw);
	  break;
	}

      case PROC_BOX:
	{

	  BoxProc* box=dynamic_cast<BoxProc*>((altro._procedure)[i]);
	  BoxProc* boxnw=new BoxProc(box);
	  boxnw->aggiungi_genitore(this);
	  _procedure.push_back(boxnw);
	  break;
	}

      }
    }


    for(unsigned int cta=0;cta<(altro._atomi).size();cta++){

      _atomi.push_back(altro._atomi[cta]);
      _atomi.back().aggiungi_genitore(this);
    }

  }


gruppo& gruppo::operator=(const gruppo& altro){
#ifdef DEBUG
  cout << "OPERATORE GRUPPO =" << endl;
#endif

  _id_gruppo=altro._id_gruppo;
  _tipo_gruppo=altro._tipo_gruppo;
  _angolorot=altro._angolorot;
  _xpivot=altro._xpivot;
  _ypivot=altro._ypivot;

  _atomi.erase(_atomi.begin(),_atomi.end());
  _procedure.erase(_procedure.begin(),_procedure.end());

  for(unsigned int i=0;i<(altro._procedure).size();i++){

    switch(((altro._procedure)[i])->tipo()){
    case PROC_ARC:
      {
	proc_arc* arc=dynamic_cast<proc_arc*>((altro._procedure)[i]);
	proc_arc* arcnw=new proc_arc(arc);
	arcnw->aggiungi_genitore(this);
	_procedure.push_back(arcnw);
	break;
      }
    case PROC_ARROW:
      {
	proc_arrow* arr=dynamic_cast<proc_arrow*>((altro._procedure)[i]);
	proc_arrow* arrnw=new proc_arrow(arr);
	arrnw->aggiungi_genitore(this);
	_procedure.push_back(arrnw);
	
	break;
      }


    case PROC_BEZIER:
      {

	proc_bezier* bez=dynamic_cast<proc_bezier*>((altro._procedure)[i]);
	proc_bezier* beznw= new proc_bezier(bez);
	beznw->aggiungi_genitore(this);
	_procedure.push_back(beznw);
	break;
      }

      case PROC_BOX:
	{

	  BoxProc* box=dynamic_cast<BoxProc*>((altro._procedure)[i]);
	  BoxProc* boxnw=new BoxProc(box);
	  boxnw->aggiungi_genitore(this);
	  _procedure.push_back(boxnw);
	  break;
	}


    }
  }


  for(unsigned int cta=0;cta<(altro._atomi).size();cta++){
    _atomi.push_back(altro._atomi[cta]);
    _atomi.back().aggiungi_genitore(this);
  }

  return *this;

}


gruppo::gruppo()
  :_id_gruppo(0),
   _tipo_gruppo(DEFAULT_TYPE_GROUP),
   _angolorot(0),
   _xpivot(0),
   _ypivot(0)


{

}

gruppo::~gruppo(){
  for(unsigned int i=0;i<_procedure.size();i++){
#ifdef DEBUG
    cout << "Eliminata procedura..." ;
#endif
    delete _procedure[i];
  }
}


bool gruppo::operator==(gruppo altro){
  if(id_gruppo()==altro.id_gruppo()){
    return true;
  }else{
    return false;
  }
}


float gruppo::w(){

  std::pair<float,float> ld;
  std::pair<float,float> ru;

  get_bounding_box(ld,ru);

  return ru.first-ld.first;

}

float gruppo::phys_w(){
  std::pair<float,float> ld;
  std::pair<float,float> ru;

  get_phys_bounding_box(ld,ru);
  return ru.first-ld.first;
}


float gruppo::visual_w(){

  std::pair<float,float> ld;
  std::pair<float,float> ru;

  get_visual_bounding_box(ld,ru);
  return ru.first-ld.first;

}


float gruppo::h(){
  
  
  std::pair<float,float> ld;
  std::pair<float,float> ru;

  get_bounding_box(ld,ru);

  return ru.second-ld.second;

}

float gruppo::phys_h(){

  std::pair<float,float> ld;
  std::pair<float,float> ru;

  get_phys_bounding_box(ld,ru);
  return ru.second-ld.second;


}

float gruppo::visual_h(){
  std::pair<float,float> ld;
  std::pair<float,float> ru;

  get_visual_bounding_box(ld,ru);
  return ru.second-ld.second;
}




float gruppo::posx(){
  std::pair<float,float> ld;
  std::pair<float,float> ru;

  get_bounding_box(ld,ru);
  return ld.first;

}

float gruppo::phys_posx(){
  std::pair<float,float> ld;
  std::pair<float,float> ru;

  get_phys_bounding_box(ld,ru);
  

  return ld.first;
}

float gruppo::visual_posx(){

  std::pair<float,float> ld;
  std::pair<float,float> ru;

  get_visual_bounding_box(ld,ru);
  return ld.first;
}



float gruppo::posy(){
  std::pair<float,float> ld;
  std::pair<float,float> ru;

  get_bounding_box(ld,ru);
  return ld.second;
}

float gruppo::phys_posy(){

  std::pair<float,float> ld;
  std::pair<float,float> ru;

  get_phys_bounding_box(ld,ru);
  return ld.second;

}

float gruppo::visual_posy(){
  std::pair<float,float> ld;
  std::pair<float,float> ru;

  get_visual_bounding_box(ld,ru);
  return ld.second;

}


void gruppo::xpivot(float nw){
  _xpivot=nw;
}

void gruppo::ypivot(float nw){
  _ypivot=nw;
}

void gruppo::angolorot(float nw){
  _angolorot=nw;
}



float gruppo::xpivot(){
  return _xpivot;
}

float gruppo::ypivot(){
  return _ypivot;
}

float gruppo::angolorot(){
  return _angolorot;
}



/**
 *Setta il valore dell 'id del gruppo
 * \param nx nuovo id
 */

void gruppo::id_gruppo(int nw){

  _id_gruppo=nw;

}




/**
 *Ritorna l'id del gruppo
 */

int gruppo::id_gruppo(){
  return _id_gruppo;
}

int gruppo::id(){
  return id_gruppo();
}

void gruppo::id(int nw){
  id_gruppo(nw);
}



void gruppo::tipo_gruppo(int nw){
  _tipo_gruppo=nw;
}

int gruppo::tipo_gruppo(){
  return _tipo_gruppo;
}


bool gruppo::purge_atom(int id){

  vector<atomo>::iterator inatom=iniz_atom();
  vector<atomo>::iterator finatom=fin_atom();
  while(inatom!=finatom){
    (*inatom).elimina_legame(id);
    inatom++;
  }

  elimina_atomo(id);

  inatom=iniz_atom();
  finatom=fin_atom();
  sort(_atomi.begin(), _atomi.end(), ordina_atomo_id);
  return true;
}

vector<atomo>::iterator gruppo::elimina_atomo(int id){

  vector<atomo>::iterator inatom=iniz_atom();
  vector<atomo>::iterator finatom=fin_atom();
  vector<atomo>::iterator resul=fin_atom();
  while(inatom!=finatom){
    if((*inatom).id()==id){
      //cout << "id da eliminare " << id ;
      resul=_atomi.erase(inatom);
      break;
    }else{
      inatom++;
    }
  }
  //cout << "...eliminato" << endl;
  return resul;
}


void gruppo::add_atomo(atomo nw, bool sorted){
  _atomi.push_back(nw);
  if(sorted){
    sort(_atomi.begin(), _atomi.end(), ordina_atomo_id);
  }
}

void gruppo::ordina(){
  sort(_atomi.begin(), _atomi.end(), ordina_atomo_id);
}


/**
 *Aggiunge un atomo al gruppo setta un id unico e ordina secondo l'operatore "minore di"
 *gli atomi.
 *
 *\param nw nuovo atomo
 */

int gruppo::add_atomo_id(atomo nw){

  int id_atm=0;

  if(_atomi.size()>0){
    id_atm=_atomi.back().id()+1;
  }

  nw.id(id_atm);
  _atomi.push_back(nw);
  sort(_atomi.begin(), _atomi.end(), ordina_atomo_id);
  return id_atm;
}

bool gruppo::has_atoms(){
  return (iniz_atom() != fin_atom());
}

void gruppo::depth_search(atomo& start){
  if(!start.visitato()){
    start.visitato(true);
    vector<legame>::iterator primo=start.primo_leg();
    vector<legame>::iterator ultimo=start.ultimo_leg();

    while(primo!=ultimo){

      int legato=(*primo).id_atomo();

      for(unsigned int i=0;i<_atomi.size();i++){

	if((_atomi[i]).id()==legato){

	  if(!_atomi[i].visitato()){

	    render(start,_atomi[i],(*primo));
	  }else if ( !_atomi[i].e_arrivato( start.id()  )){

	    render(start,_atomi[i],(*primo));
	  }else{

	    if((start.ultimo_leg()-start.primo_leg())<=1){

	      etichetta sy=start.etich();

	      allinea_etichetta(sy,start);

	      if((sy.vec_str())[0].first!=string(NO_ETIC)){
		if((sy.vec_str())[0].first!=string(ETIC_IDR_UP)){
		  sy.disegna();
		}else{
                  if(cairo_t_singleton::can_export()){
                    cairo_t* cn=cairo_t_singleton::get_context();
                    cairo_save(cn);
                    
                    cairo_set_source_rgb(cn,
                                         remap_color_1(sy.cr()),
                                         remap_color_1(sy.cg()),
                                         remap_color_1(sy.cb()));
                    cairo_move_to(cn,start.pos_x(),start.pos_y());          
                    cairo_arc(cn,start.pos_x(),start.pos_y(),RAGGIO_EL,0,2*M_PI);
                    cairo_fill(cn);
                    cairo_restore(cn);
                    
                    
                  }else{
		    fl_color(sy.cr(),sy.cg(),sy.cb());
		    int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
		    int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();
		    		    
		    float raggio_hidr_zoomed= RAGGIO_IDR_UP *__pref.getZoom();
		    int   approx_r_hidr_zoomed=static_cast<int>(rintf(raggio_hidr_zoomed));
		                        
                    fl_pie(static_cast<int>(rintf(start.pos_x()-raggio_hidr_zoomed/2
                                                  +dx_scroll)),
                           static_cast<int>(rintf(start.pos_y()-raggio_hidr_zoomed/2
                                                  +dy_scroll)),
                            approx_r_hidr_zoomed,approx_r_hidr_zoomed,0,360);
                  }
		}
	      }

	      if(start.cariche()){
                int free_side=render_carica(start,sy.x(), sy.y(), sy.w(), sy.font(),sy.dim());
		(start.ritorna_lati_liberi())[free_side]=false;
	      }



              render_el_spaiati(start,sy.x(), sy.y(), sy.w(),sy.h());
              render_el_spaiati(start,sy.x(), sy.y(), sy.w(),sy.h(),
				  true);

	      start.libera_tutti();
	    }
	    

	  }
	  start.setta_arrivati(_atomi[i].id());
	  depth_search(_atomi[i]);
	}
      }
      primo++;
    }

  }else{

  }
}




void gruppo::visual_allinea_etichetta(etichetta& sy,atomo& start){

  float st_xpos=0;
  float st_ypos=0;
  get_visual_bb_etic(sy, st_xpos, st_ypos);

  sy.trasla(static_cast<int>(rintf(st_xpos+start.visual_pos_x())),
	    static_cast<int>(rintf(st_ypos+start.visual_pos_y())) );
}




void gruppo::allinea_etichetta(etichetta& sy,atomo& start){

  float st_xpos=0;
  float st_ypos=0;

  get_bb_etic(sy, st_xpos, st_ypos);
  
  sy.phys_translate(st_xpos+start.phys_pos_x(),
                    st_ypos+start.phys_pos_y());
}


etichetta scaled_charge_etichetta(atomo& atm,std::string& numc, float& scaled_dim,
				  float f_size){
  int car=atm.cariche();
  etichetta et_charge;
  float sc_apic=SCALE_APICI;

  if(car){
    ostringstream ostr;
    switch(car){
    case 1:
      numc = PLUS;
      break;
    case -1:
      numc = MINUS;
      break;
    default:
      ostr << car;
      string to_reverse=ostr.str();
      if(car<0){
	numc=to_reverse.substr(1) + string("-");
      }else{
	numc=to_reverse + string("+");
      }
    }


    //calculate position of charge

    if(numc==MINUS){
      sc_apic*=SCALE_SUP_MINUS;
    }


  float sc_apic=SCALE_APICI;
  if(numc==MINUS){
    sc_apic*=SCALE_SUP_MINUS;
  }


  etichetta tmp_etich=atm.etich();
  et_charge.aggiungi(numc,ET_STR);
  et_charge.font(atm.etich().font());
  et_charge.dim(f_size/sc_apic);
  scaled_dim=f_size/sc_apic;
  }
  return et_charge;
}


int gruppo::render_carica(atomo& atm,float x, float y, float w, int fon, int dim){
  int res_free_side=0;
  int dx_scroll=0;
  int dy_scroll=0;
  if(!cairo_t_singleton::can_export()){
    dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
    dy_scroll=(MainWindow->ritorna_mol_canvas())->y();
  }

  int car=atm.cariche();
  if(car){
    std::string numc;
    float scaled_dim=0;
    etichetta et_charge=scaled_charge_etichetta(atm,numc,scaled_dim,dim);

    float x_charge=x+w;
    float y_charge=y;
    
    switch(atm.position_charge()){
    case L_BOTTOM:
       {
	 float w_charge=0;

         etichetta tmp_etich=atm.etich();
         w_charge=et_charge.phys_w();
	 x_charge=x-w_charge;
         
         if(cairo_t_singleton::can_export()){
	   if(numc==MINUS || numc==PLUS){
	     y_charge+=tmp_etich.phys_h() - et_charge.phys_h();
	   }else{
	     y_charge+=tmp_etich.phys_h() - et_charge.phys_h()/2;
	   }
         }else{
           y_charge+=tmp_etich.h();
         }
	 res_free_side=2;
       }
       break;
    case R_BOTTOM:
      {
        etichetta tmp_etich=atm.etich();
        if(cairo_t_singleton::can_export()){
	  if(numc==MINUS || numc==PLUS){
	    y_charge+=tmp_etich.phys_h() - et_charge.phys_h();
	  }else{
	    y_charge+=tmp_etich.phys_h() - et_charge.phys_h()/2;
	  }
        }else{
          y_charge+=tmp_etich.h();
        }
	
	res_free_side=0;
      }
      break;
    case L_TOP:
      {
	 float w_charge=0;
         w_charge=et_charge.phys_w();
	 
	 x_charge=x-w_charge;
	 res_free_side=2;
      }
      
    case R_TOP:
    default:
      {
	if(cairo_t_singleton::can_export()){
	  y_charge-=et_charge.phys_h()/2;           
	}else{
	  y_charge+=et_charge.phys_h()/2;
	}
	res_free_side=0;
      }
    }

    if(cairo_t_singleton::can_export()){

      draw_pango_string(numc,x_charge,y_charge,
                        remap_ps_font(fon),scaled_dim,
                        atm.cr(),
                        atm.cg(),
                        atm.cb());
    }else{
      fl_font(fon,scaled_dim);
      fl_color(atm.cr(),atm.cg(),atm.cb());
      fl_draw(numc.c_str(),static_cast<int>(rintf(x_charge+dx_scroll)),
	      static_cast<int>(rintf(y_charge+dy_scroll)));
    }
  }

  switch(atm.position_charge()){
  case L_BOTTOM:
    res_free_side=2;
    break;
  case R_BOTTOM:
    res_free_side=0;
    break;
  case L_TOP:
    res_free_side=2;
    break;
  case R_TOP:
  default:
    res_free_side=0;
    break;
    
  }


  return res_free_side;

}

void gruppo::render_el_spaiati(atomo& atm,float x, float y, float w, float h,
                               bool dopp){

  int w_f_atm;
 

  int dx_scroll=0;
  int dy_scroll=0;

  if(! cairo_t_singleton::can_export()){
    dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
    dy_scroll=(MainWindow->ritorna_mol_canvas())->y();
  }



  etichetta sy=atm.etich();
  //cout << "iio allineo da el_spaiati" << endl;
  allinea_etichetta(sy,atm);
  //cout << "YHHHHHHH" << endl;


  w_f_atm=sy.w();
 

  float xr;
  float yr;
  /*
    int gruppo::clip_leg(float xrect, float yrect, float w, float h,
    atomo& da , atomo& fino, float& xrisul, float& yrisul){
  */
  vector<legame>:: iterator legin=atm.iniz_leg();
  vector<legame>:: iterator legfin=atm.fin_leg();


  while(legin!=legfin){
    for(unsigned int i=0;i<_atomi.size();i++){ //cerchiamo gli atomi
      if(_atomi[i].id()==(*legin).id_atomo()){

	  clip_leg(sy.x(), sy.y(), sy.w(), sy.h(),
		   atm , _atomi[i], xr, yr);
	  
	  if(static_cast<int>(rintf(sy.x()+sy.w()))==static_cast<int>(rintf(xr))){
	    (atm.ritorna_lati_liberi())[0]=false;
	  }else

	  if(static_cast<int>(rintf(sy.y()+sy.h()))==static_cast<int>(rintf(yr))){
	    (atm.ritorna_lati_liberi())[1]=false;
	  }else

	  if(static_cast<int>(rintf(sy.x()))==static_cast<int>(rintf(xr))){
	    (atm.ritorna_lati_liberi())[2]=false;
	  }else

	  if(static_cast<int>(rintf(sy.y()))==static_cast<int>(rintf(yr))){
	    (atm.ritorna_lati_liberi())[3]=false;
	  }

	  //}else{
	  /*
	  fl_color(0,0,255);
	  fl_rectf(sy.visual_x()+dx_scroll,sy.visual_y()+dy_scroll,3,3);
	  fl_color(255,0,255);
	  fl_rectf(sy.visual_x()+sy.visual_w()/2+dx_scroll,
		   sy.visual_y()+sy.visual_h()/2+dy_scroll,3,3);
	  fl_color(0,255,0);
	  fl_rectf(sy.x()+dx_scroll,sy.y()+dy_scroll,3,3);
	  fl_color(255,0,0);
	  fl_rectf(atm.visual_pos_x()+dx_scroll,atm.visual_pos_y()+dy_scroll,3,3);
	  */
	  //return;
	  

	  //cout << "entro clip" << endl;
	  //clip_leg(sy.x(), sy.y(), sy.w(), sy.h(),
	  //	   atm , _atomi[i], xr, yr);
	  /*
	  if(__pref.getZoom()>1)
	    cout << "RRRRRRRRRRRRRRRRR"<< endl;
	  else
	    cout << "rrrrrrrrrrrrrrrrrrrrr"<< endl;
	  */
	  // if(static_cast<int>(rintf(sy.visual_x()+sy.visual_w()))==static_cast<int>(rintf(xr))){
// 	    (atm.ritorna_lati_liberi())[0]=false;
// 	  }else

// 	  if(static_cast<int>(rintf(sy.visual_y()+sy.visual_h()))==static_cast<int>(rintf(yr))){
// 	    (atm.ritorna_lati_liberi())[1]=false;
// 	  }else

// 	  if(static_cast<int>(rintf(sy.visual_x()))==static_cast<int>(rintf(xr))){
// 	    (atm.ritorna_lati_liberi())[2]=false;
// 	  }else

// 	  if(static_cast<int>(rintf(sy.visual_y()))==static_cast<int>(rintf(yr))){
// 	    (atm.ritorna_lati_liberi())[3]=false;
// 	  }

      

      }
    }
    legin++;
  }



  /*
  cout << "Lati liberi" << endl;
  cout << "id: " << atm.id() << endl;
  for(int i=0;i<4;i++){
    cout << (atm.ritorna_lati_liberi())[i] << ",";
  }
  cout << endl;
  */
  /////////////////////////////////continuare

  if(! cairo_t_singleton::can_export()){
    fl_color(atm.cr(),atm.cg(),atm.cb());
  }

  int limite=0;
  if(dopp){
    limite=atm.doppietti();
  }else{
    limite=atm.el_spaiati();
  }
  int xr2=0;
  int yr2=0;

  int lati_ancora_liberi=(atm.ritorna_lati_liberi())[0]
    +(atm.ritorna_lati_liberi())[1]
    +(atm.ritorna_lati_liberi())[2]
    +(atm.ritorna_lati_liberi())[3];

  //cout << "------------------------------------------------" << endl;
  while(limite>0 && lati_ancora_liberi>0){
     lati_ancora_liberi=(atm.ritorna_lati_liberi())[0]
    +(atm.ritorna_lati_liberi())[1]
    +(atm.ritorna_lati_liberi())[2]
    +(atm.ritorna_lati_liberi())[3];


     //cout << "Lati liberi" << endl;
     //cout << "id: " << atm.id() << endl;
     // for(int i=0;i<4;i++){
//        cout << (atm.ritorna_lati_liberi())[i] << ",";
//      }
//      cout << endl;
//      cout << "LIMITE : " << limite << endl;

    int libero_e=6;
    for(int i=0;i<4;i++){
      if((atm.ritorna_lati_liberi())[i]==true){
	(atm.ritorna_lati_liberi())[i]=false;
	limite--;
	libero_e=i;
	//cout << "esce" << " ed i=" << i <<  endl;

	break;
      }
    }

    int radius_scaled=RAGGIO_EL;

    if(!cairo_t_singleton::can_export()){
      radius_scaled= static_cast<int>(rintf(radius_scaled * __pref.getZoom()));
    }

    bool electron_limit_excedeed=false;

    //trovato lato libero disegnamo
    switch(libero_e){
    case 0:
      xr2=static_cast<int>(rintf(x+w+radius_scaled/2));
      yr2=static_cast<int>(rintf(y+h/2-radius_scaled/2));
      break;
    case 1:
      xr2=static_cast<int>(rintf(x+w_f_atm/2-radius_scaled/2));
      yr2=static_cast<int>(rintf(y+h + radius_scaled/2 ));
      break;
    case 2:
      xr2=static_cast<int>(rintf(x-radius_scaled/2));
      yr2=static_cast<int>(rintf(y+h/2-radius_scaled/2));
      break;
    case 3:
      xr2=static_cast<int>(rintf(x+w_f_atm/2-radius_scaled/2));
      yr2=static_cast<int>(rintf(y));
      break;
    default:
      electron_limit_excedeed=true;
      break;
    }

    if(!electron_limit_excedeed){
      if(!dopp){
        if(cairo_t_singleton::can_export()){
          
          /****testing cairo*********/
          cairo_t* cn=cairo_t_singleton::get_context();
          cairo_save(cn);
          
          cairo_set_source_rgb(cn,
                               remap_color_1(atm.cr()),
                               remap_color_1(atm.cg()),
                               remap_color_1(atm.cb()));
          cairo_move_to(cn,xr2,yr2);          
          cairo_arc(cn,xr2,yr2,radius_scaled/2,0,2*M_PI);
          cairo_fill(cn);
          cairo_restore(cn);
          
          /*****************/
        
        }else{
	  fl_pie(xr2+dx_scroll,yr2+dy_scroll,radius_scaled, radius_scaled, 0, 360);
	}
      }else{
	int xdp;
	int ydp;
	switch(libero_e){
	case 0:
	case 2:
	  //yr2-=RAGGIO_EL;
	  ydp=yr2+radius_scaled;
	  xdp=xr2;
	  break;
	case 1:
	case 3:
	  xr-=radius_scaled;
	  ydp=yr2;
	  xdp=xr2+radius_scaled;
	  break;
	default:
	  xdp=0;
	  ydp=0;
	  break;
	}


        if(cairo_t_singleton::can_export()){
          
          /****testing cairo*********/
          cairo_t* cn=cairo_t_singleton::get_context();
          cairo_save(cn);
          
          cairo_set_source_rgb(cn,
                               remap_color_1(atm.cr()),
                               remap_color_1(atm.cg()),
                               remap_color_1(atm.cb()));
          cairo_move_to(cn,xr2,yr2);
          cairo_arc(cn,xr2,yr2,radius_scaled/2,0,2*M_PI);
          cairo_move_to(cn,xdp,ydp);
          cairo_arc(cn,xdp,ydp,radius_scaled/2,0,2*M_PI);
          cairo_fill(cn);
          cairo_restore(cn);
          
          /*****************/
        
        }else{
	  
	  fl_pie(xr2+dx_scroll,yr2+dy_scroll,radius_scaled,radius_scaled, 0, 360);
	  fl_pie(xdp+dx_scroll,ydp+dy_scroll,radius_scaled, radius_scaled, 0, 360);
	}
      }
    }
  }
  //cout << "ıııııııııııııııııııııııııııııııııııııııııııııııııııııııııı" << endl;

  if(! cairo_t_singleton::can_export()){
    fl_color(atm.cr(),atm.cg(),atm.cb());
  }
  
}


std::vector<int> gruppo::calculate_electron_pos_relative(atomo& atm){
  if(atm.cariche()>0){
    switch(atm.position_charge()){
    case L_BOTTOM:
      (atm.ritorna_lati_liberi())[2]=false;
      break;
    case R_BOTTOM:
      (atm.ritorna_lati_liberi())[0]=false;
      break;
    case L_TOP:
      (atm.ritorna_lati_liberi())[2]=false;
      break;
    case R_TOP:
    default:
      (atm.ritorna_lati_liberi())[0]=false;
      break;
    }
  }


  etichetta sy=atm.etich();
  allinea_etichetta(sy,atm);
  //int w_f_atm=sy.w();
  //int htmp=sy.h();
  float xr;
  float yr;
  /*
    int gruppo::clip_leg(float xrect, float yrect, float w, float h,
    atomo& da , atomo& fino, float& xrisul, float& yrisul){
  */
  vector<legame>:: iterator legin=atm.iniz_leg();
  vector<legame>:: iterator legfin=atm.fin_leg();


  while(legin!=legfin){
      atomo* bond=find_atomo_id((*legin).id_atomo());
      clip_leg(sy.x(), sy.y(), sy.w(), sy.h(),
               atm , *bond, xr, yr);
      if(static_cast<int>(rintf(sy.x()+sy.w()))==static_cast<int>(rintf(xr))){
        (atm.ritorna_lati_liberi())[0]=false;
      }else if(static_cast<int>(rintf(sy.y()+sy.h()))==static_cast<int>(rintf(yr))){
        (atm.ritorna_lati_liberi())[1]=false;
      }else if(static_cast<int>(rintf(sy.x()))==static_cast<int>(rintf(xr))){
        (atm.ritorna_lati_liberi())[2]=false;
      }else if(static_cast<int>(rintf(sy.y()))==static_cast<int>(rintf(yr))){
        (atm.ritorna_lati_liberi())[3]=false;
      }
      legin++;
  }



  // for(int i=0;i<4;i++){
  //   cout << (atm.ritorna_lati_liberi())[i] << ",";
  // }
  // cout << endl;
  
  /////////////////////////////////continuare
  int limite=atm.doppietti() + atm.el_spaiati();

  int lati_ancora_liberi=(atm.ritorna_lati_liberi())[0]
    +(atm.ritorna_lati_liberi())[1]
    +(atm.ritorna_lati_liberi())[2]
    +(atm.ritorna_lati_liberi())[3];


  std::vector<int> res;

  //cout << "------------------------------------------------" << endl;
  while(limite>0 && lati_ancora_liberi>0){
     lati_ancora_liberi=(atm.ritorna_lati_liberi())[0]
    +(atm.ritorna_lati_liberi())[1]
    +(atm.ritorna_lati_liberi())[2]
    +(atm.ritorna_lati_liberi())[3];

    for(int i=0;i<4;i++){
      if((atm.ritorna_lati_liberi())[i]==true){
	(atm.ritorna_lati_liberi())[i]=false;
        res.push_back(i);
	limite--;
        break;
      }
    }

  }

  return res;
}




void gruppo::render(atomo& da, atomo& fino, legame& il_legame){

  int dx_scroll=0;
  int dy_scroll=0;
  if(!cairo_t_singleton::can_export()){
    dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
    dy_scroll=(MainWindow->ritorna_mol_canvas())->y();
  }


  etichetta sy=da.etich();

  //float st_xpos=sy.x()+da.pos_x();
  //float st_ypos=sy.y()+da.pos_y();

  /*
  sy.trasla(static_cast<int>(rintf(sy.x()+da.pos_x()))-sy.w()/2,
	    static_cast<int>(rintf(sy.y()+da.pos_y()))-sy.h()/2 );
  */

  //cout << "iioallineo da render inizio" << endl;
  allinea_etichetta(sy,da);

  //  fl_color(sy.cr(),sy.cg(),sy.cb());
  /*
  fl_rect(static_cast<int>(rintf(sy.x())), static_cast<int>(rintf(sy.y())),
	  static_cast<int>(rintf(sy.w())), static_cast<int>(rintf(sy.h())));
  */


  if((sy.vec_str())[0].first!=string(NO_ETIC)){

    if((sy.vec_str())[0].first!=string(ETIC_IDR_UP)){
      sy.disegna();
    }else{
      if(cairo_t_singleton::can_export()){
        cairo_t* cn=cairo_t_singleton::get_context();
        cairo_save(cn);
        cairo_move_to(cn,da.pos_x(),da.pos_y());
        cairo_set_source_rgb(cn,
                             remap_color_1(sy.cr()),
                             remap_color_1(sy.cg()),
                             remap_color_1(sy.cb()));
        cairo_arc(cn,
                  da.pos_x(),
                  da.pos_y(),
                  RAGGIO_EL,
                  0,
                  2*M_PI);
        cairo_fill(cn);
        cairo_restore(cn);

      }else{
	fl_color(sy.cr(),sy.cg(),sy.cb());


	float raggio_hidr_zoomed= RAGGIO_IDR_UP *__pref.getZoom();
	int   approx_r_hidr_zoomed=static_cast<int>(rintf(raggio_hidr_zoomed));
	
	fl_pie(static_cast<int>(rintf(da.pos_x()-raggio_hidr_zoomed/2
				      +dx_scroll)),
	       static_cast<int>(rintf(da.pos_y()-raggio_hidr_zoomed/2
				      +dy_scroll)),
	       approx_r_hidr_zoomed,approx_r_hidr_zoomed,0,360);
	/*
	fl_pie(static_cast<int>(rintf(da.pos_x()-RAGGIO_IDR_UP/2+dx_scroll)),
	     static_cast<int>(rintf(da.pos_y()-RAGGIO_IDR_UP/2+dy_scroll)),
	     RAGGIO_IDR_UP,RAGGIO_IDR_UP,0,360);
	*/
      }
    }
  }



  if(da.cariche()){
    render_carica(da,sy.x(), sy.y(), sy.w(), sy.font(),sy.dim());
    
    (da.ritorna_lati_liberi())[0]=false;
    
  }


  render_el_spaiati(da,sy.x(), sy.y(), sy.w(),sy.h());
  render_el_spaiati(da,sy.x(), sy.y(), sy.w(),sy.h(),true);
  da.libera_tutti();


  etichetta finsy=fino.etich();
  allinea_etichetta(finsy,fino);



  /*
  if(plotter || cairo_t_singleton::can_export()){
    
  }else{
    fl_color(finsy.cr(),finsy.cg(),finsy.cb());
  }
  */
  float xr , yr;

  if((sy.vec_str())[0].first!=string(NO_ETIC) && 
     (sy.vec_str())[0].first!=string(ETIC_IDR_UP)){
      clip_leg(sy.x(), sy.y(), sy.w(), sy.h(),
	       da , fino, xr, yr);
  }else{
      xr=da.pos_x();
      yr=da.pos_y();
  }

  float xr2, yr2;
  if((finsy.vec_str())[0].first!=string(NO_ETIC) &&
     (finsy.vec_str())[0].first!=string(ETIC_IDR_UP)){
    clip_leg(finsy.x(), finsy.y(), finsy.w(), finsy.h(),
             fino , da, xr2, yr2);
  }else{
    xr2=fino.pos_x();
    yr2=fino.pos_y();
  }

  switch(il_legame.tipo_legame()){

  case LEGAME_TRIPLO: 
    if(cairo_t_singleton::can_export()){
      
      draw_parallel(xr,yr,xr2,yr2,
                        il_legame.cr(),il_legame.cg(),il_legame.cb());
      
      draw_parallel(xr,yr,xr2,yr2,
                        il_legame.cr(),il_legame.cg(),il_legame.cb(),true);
    }else{
      draw_parallel(xr+dx_scroll, yr+dy_scroll,
			xr2+dx_scroll, yr2+dy_scroll,
                        il_legame.cr(),il_legame.cg(),il_legame.cb());
      draw_parallel(xr+dx_scroll, yr+dy_scroll,
			xr2+dx_scroll, yr2+dy_scroll,
                        il_legame.cr(),il_legame.cg(),il_legame.cb(),true);
    }
  case LEGAME_SINGOLO:
    {
      if(cairo_t_singleton::can_export()){

        /****testing cairo*********/
        cairo_t* cn=cairo_t_singleton::get_context();
        cairo_save(cn);

        cairo_set_source_rgb(cn,
                             remap_color_1(il_legame.cr()),
                             remap_color_1(il_legame.cg()),
                             remap_color_1(il_legame.cb()));
        
        cairo_move_to(cn,xr,yr);
        cairo_line_to(cn,xr2,yr2);
        cairo_stroke(cn);
        cairo_restore(cn);
        
        /*****************/

      }else{
        fl_color(il_legame.cr(),il_legame.cg(),il_legame.cb());
        fl_line_style(FL_SOLID,static_cast<int>(rintf(__pref.getZoom())),0);
        fl_begin_line();
        fl_vertex(xr+dx_scroll, yr+dy_scroll);
        fl_vertex(xr2+dx_scroll, yr2+dy_scroll);
        fl_end_line();
        fl_line_style(0);
      }
      break;
    }
  case LEGAME_DOPPIO: 
    render_doppio(da, fino,xr,yr,
                  xr2,yr2,
                  il_legame.cr(),il_legame.cg(),il_legame.cb(),
                  false);
    break;

  case LEGAME_DOPPIO_1: 

    render_double_forced(da, fino,xr,yr,
                         xr2,yr2,
                         il_legame.cr(),il_legame.cg(),il_legame.cb(),
                         false,true);

    break;



  case LEGAME_DOPPIO_2: 
    render_double_forced(da, fino,xr,yr,
                         xr2,yr2,
                         il_legame.cr(),il_legame.cg(),il_legame.cb(),
                         false,false);
    break;



  case LEGAME_INTERNO: 
    if(cairo_t_singleton::can_export()){
      render_stereo_down(xr, yr, xr2, yr2,
                         il_legame.cr(),il_legame.cg(),il_legame.cb());
    }else{
      render_stereo_down(xr+dx_scroll, yr+dy_scroll,
			 xr2+dx_scroll, yr2+dy_scroll,
                         il_legame.cr(),il_legame.cg(),il_legame.cb());
    }
    break;
  case LEGAME_INTERNO_OPP: 
     if(cairo_t_singleton::can_export()){
       render_stereo_down(xr2, yr2, xr, yr,
                          il_legame.cr(),il_legame.cg(),il_legame.cb());
     }else{
       render_stereo_down(xr2+dx_scroll, yr2+dy_scroll,
			  xr+dx_scroll, yr+dy_scroll,
                          il_legame.cr(),il_legame.cg(),il_legame.cb());
     }
    break;
  case LEGAME_ESTERNO:
    renderizza_stereo_up(da,fino,xr, yr,
			 xr2, yr2,
                         il_legame.cr(),il_legame.cg(),il_legame.cb());
    break;
  case LEGAME_ESTERNO_OPP:
    renderizza_stereo_up(fino,da,xr2, yr2,
    			 xr, yr,
                         il_legame.cr(),il_legame.cg(),il_legame.cb());
    break;
  case LEGAME_ISPESSITO: 
    if(cairo_t_singleton::can_export()){
      renderizza_ispessito(xr,yr,xr2,yr2,
                           il_legame.cr(),il_legame.cg(),il_legame.cb());
    }else{
      renderizza_ispessito(xr+dx_scroll,yr+dy_scroll,
			   xr2+dx_scroll,yr2+dy_scroll,
                           il_legame.cr(),il_legame.cg(),il_legame.cb());
    }
    break;
  case LEGAME_TRATTEGGIATO: 
    {

      
      if(cairo_t_singleton::can_export()){
        cairo_t* cn=cairo_t_singleton::get_context();
        cairo_save(cn);
        const double dash_gap[1]={__pref.get_tratteggio_legame()};
        cairo_set_dash(cn,dash_gap,1,0);
        cairo_set_source_rgb(cn,
                             remap_color_1(il_legame.cr()),
                             remap_color_1(il_legame.cg()),
                             remap_color_1(il_legame.cb()));
        cairo_move_to(cn,xr,yr);
        cairo_line_to(cn,xr2,yr2);
        cairo_stroke(cn);
        cairo_restore(cn);
      }else{
	char dash[2]={__pref.get_tratteggio_legame(),0}; //preferenze
        fl_color(il_legame.cr(),il_legame.cg(),il_legame.cb());
	fl_line_style(FL_SOLID,static_cast<int>(rintf(__pref.getZoom())),dash);
	fl_begin_line();
	fl_vertex(xr+dx_scroll, yr+dy_scroll);
	fl_vertex(xr2+dx_scroll, yr2+dy_scroll);
	fl_end_line();
	fl_line_style(0);
      }
      break;
    }
  case LEGAME_DOPPIO_TRATTEGGIATO: 
    render_doppio(da,fino,xr,yr,xr2,yr2,
                  il_legame.cr(),il_legame.cg(),il_legame.cb(),
                  true);
    break;

  case LEGAME_DOPPIO_TRATTEGGIATO_1: 

    render_double_forced(da, fino,xr,yr,
                         xr2,yr2,
                         il_legame.cr(),il_legame.cg(),il_legame.cb(),
                         true,true);

    break;



  case LEGAME_DOPPIO_TRATTEGGIATO_2: 
    render_double_forced(da, fino,xr,yr,
                         xr2,yr2,
                         il_legame.cr(),il_legame.cg(),il_legame.cb(),
                         true,false);
    break;



  case LEGAME_STEREO_SCON: 
    if(cairo_t_singleton::can_export()){
      renderizza_stereo_scon(xr,yr,xr2,yr2,
                             il_legame.cr(),il_legame.cg(),il_legame.cb());
    }else{
      renderizza_stereo_scon(xr+dx_scroll,yr+dy_scroll,
			     xr2+dx_scroll,yr2+dy_scroll,
                             il_legame.cr(),il_legame.cg(),il_legame.cb());
    }
    break;
  default:
    break;
  }
}


/*
#define LEGAME_SINGOLO                0
#define LEGAME_DOPPIO                 1
#define LEGAME_TRIPLO                 2
#define LEGAME_INTERNO                3
#define LEGAME_INTERNO_OPP            -3
#define LEGAME_ESTERNO                4
#define LEGAME_ESTERNO_OPP            -4
#define LEGAME_ISPESSITO              5
#define LEGAME_TRATTEGGIATO           6
#define LEGAME_DOPPIO_TRATTEGGIATO    7
#define LEGAME_STEREO_SCON            8
*/


int gruppo::clip_leg(float xrect, float yrect, float w, float h,
		      atomo& da , atomo& fino, float& xrisul, float& yrisul){
  float x1,y1,x2,y2,y4;
  x1=xrect;
  y1=yrect;
  x2=xrect+w;
  y2=yrect;
  y4=yrect+h;


  /*
        x1,y1       x2,y2
  	.............
	.	    .
	.............
	x4,y4       x3,y3

  */

  unsigned char outcode=0x00 ;
  float a1_x=da.pos_x();
  float a1_y=da.pos_y();
  float a2_x=fino.pos_x();
  float a2_y=fino.pos_y();


  if(a2_x<xrect){
    outcode|=0x01;
  }else if(a2_x>xrect+w){
    outcode|=0x02;
  }


  if(a2_y<yrect){
    outcode|=0x08;
  }else  if(a2_y>yrect+h){
    outcode|=0x04;
  }
      
  //cout << "--------------" << endl;

  //cout << hex << "0X" << (unsigned int)outcode << endl;
  



  switch(outcode){
  case 0x01:
    yrisul=b_clip_v(a1_x, a1_y,
		    a2_x, a2_y, x1);

    xrisul=x1;

    break;



  case 0x02:
    yrisul=b_clip_v(a1_x,a1_y,
		    a2_x,a2_y, x2);

    xrisul=x2;


    break;

  case 0x08:
    
    xrisul=b_clip_h(a1_x,a1_y,
		    a2_x,a2_y, y1);

    yrisul=y1;

    break;

 case 0x09:
   
   xrisul=b_clip_h(a1_x,a1_y,
		   a2_x,a2_y, y1);
   
   yrisul=b_clip_v(a1_x,a1_y,
		   a2_x,a2_y, x1);
   



   if(xrisul<x1){
     xrisul=x1;
   }else{
     yrisul=y1;
   }


   break;



case 0x05:

  xrisul=b_clip_h(a1_x,a1_y,
		  a2_x,a2_y, y4);

  yrisul=b_clip_v(a1_x,a1_y,
		  a2_x,a2_y, x1);


    if(xrisul<x1){
      xrisul=x1;
    }else{
      yrisul=y4;
    }


    break;

case 0x06:

    xrisul=b_clip_h(a1_x,a1_y,
		    a2_x,a2_y, y4);

    yrisul=b_clip_v(a1_x,a1_y,
		    a2_x,a2_y, x2);

    if(xrisul>x2){
      xrisul=x2;
    }else{
      yrisul=y4;
    }

    break;


case 0x0a:
    xrisul=b_clip_h(a2_x,a2_y,
		    a1_x,a1_y, y2);

    yrisul=b_clip_v(a1_x,a1_y,
		    a2_x,a2_y, x2);




    if(xrisul>x2){
      xrisul=x2;
    }else{
      yrisul=y2;
    }


    break;


  case 0x04:

    xrisul=b_clip_h(a1_x,a1_y,
		  a2_x,a2_y, y4);

    yrisul=y4;

    break;


  }

  return 0;
}



void gruppo::render_stereo_down(float x1, float y1,
				float x2, float y2,
                                int cr, int cg, int cb){


  float m;
  float q;

  bool ris=rett_eqn(x1, y1,
		    x2, y2,
		    m, q);
  //float lung=sqrt( pow(x2-x1,2) + pow(y2-y1,2) );
  float larg_cuneo=__pref.get_larg_max_cuneo(); //preferenze
  int numcunei=__pref.get_num_barrette_stereo_down(); //preferenze
  float decr=larg_cuneo/numcunei;

  float dx=(x2-x1)/numcunei;
  float dy=(y2-y1)/numcunei;



  float xef;
  float yef;

  
  float leff=0;
  if(cairo_t_singleton::can_export()){
    leff=larg_cuneo;
  }else{
    leff=larg_cuneo*__pref.getZoom();
    decr*=__pref.getZoom();
  }
  if(ris){
    xef=x1+dx;
    yef=m*xef+q;
  }else{
    xef=x1;
    yef=y1+dy;
  }

  while(numcunei>0){

	float vert2x;
	float vert2y;
	float vert3x;
	float vert3y;

	is_perpendicular(x1, y1,
			     x2, y2,
			     true,leff,
			     vert2x, vert2y);

	is_perpendicular(x1, y1,
			     x2, y2,
			     false,leff,
			     vert3x, vert3y);


        if(cairo_t_singleton::can_export()){
          
          /****testing cairo*********/
          cairo_t* cn=cairo_t_singleton::get_context();
          cairo_save(cn);
          
          cairo_set_source_rgb(cn,
                               remap_color_1(cr),
                               remap_color_1(cg),
                               remap_color_1(cb));
          
          cairo_move_to(cn, xef+vert2x, yef+vert2y);
          cairo_line_to(cn,xef+vert3x,yef+vert3y);
          cairo_stroke(cn);
          cairo_restore(cn);
          
          /*****************/
      
        }else{
          fl_color(cr,cg,cb);
	  fl_line_style(FL_SOLID,static_cast<int>(rintf(__pref.getZoom())),0);
	  fl_begin_line();
	  fl_vertex(xef+vert2x, yef+vert2y);
	  fl_vertex(xef+vert3x, yef+vert3y);
	  fl_end_line();
	  fl_line_style(0);
	}
	if(ris){
	  xef+=dx;
	  yef=m*xef+q;
	}else{
	  yef+=dy;

	}

	leff-=decr;
	numcunei--;

      }



}


//////////


void gruppo::render_double_forced(atomo& da, atomo& fino,
                                  float x1, float y1,
                                  float x2, float y2, 
                                  int  cr, int cg, int cb,
                                  bool tratt,bool side){

  int dx_scroll=0;
  int dy_scroll=0;
  if(! cairo_t_singleton::can_export()){
    dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
    dy_scroll=(MainWindow->ritorna_mol_canvas())->y();
    fl_color(cr,cg,cb);
  }


  
  if(cairo_t_singleton::can_export()){
    
    
    cairo_t* cn=cairo_t_singleton::get_context();
    cairo_save(cn);
    
    cairo_set_source_rgb(cn,
                         remap_color_1(cr),
                         remap_color_1(cg),
                         remap_color_1(cb));

    cairo_move_to(cn,x1,y1);
    cairo_line_to(cn,x2,y2);
    cairo_stroke(cn);
    cairo_restore(cn);
      
    draw_parallel(x1, y1,x2, y2,
                      cr,cg,cb,
                      side,
                      __pref.get_multiple_bond_gap(),tratt);
    
      
  }else{
    fl_line_style(FL_SOLID,static_cast<int>(rintf(__pref.getZoom())),0);
    fl_begin_line();
    fl_vertex(x1+dx_scroll, y1+dy_scroll);
    fl_vertex(x2+dx_scroll, y2+dy_scroll);
    fl_end_line();
    fl_line_style(0);

    draw_parallel(x1+dx_scroll, y1+dy_scroll,
                      x2+dx_scroll, y2+dy_scroll,
                      cr,cg,cb,
                      side,
                      __pref.get_multiple_bond_gap(),tratt);


  }


  
}


////////////


void gruppo::render_doppio(atomo& da, atomo& fino,
			   float x1, float y1,
			   float x2, float y2, 
                           int  cr, int cg, int cb,
                           bool tratt){

  int dx_scroll=0;
  int dy_scroll=0;
  if(! cairo_t_singleton::can_export()){
    dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
    dy_scroll=(MainWindow->ritorna_mol_canvas())->y();
    fl_color(cr,cg,cb);
  }

  

  /*
  cout << "iio render doppio " <<da.id() << " "
       << fino.id() << endl;
  */
  if(fino.ultimo_leg()-fino.primo_leg()==1 ||
     da.ultimo_leg()-da.primo_leg()==1){


    //   cout << "iio" <<fino.id() << " "<< x1 << " " << x2 <<" " << y1 << " " << y2 <<endl;

    float dx;
    float dy;
    is_perpendicular(x1,y1, 
			 x2,y2, 
			 true,__pref.getDoubleBondOffset()/2,
			 dx, dy);




      float xp=x1+dx;
      float xp2=x2+dx;
      float yp=y1+dy;
      float yp2=y2+dy;
      
    //    cout << "@#@# EUGUALEEEEEE" << endl;


      if(cairo_t_singleton::can_export()){
        
        /****testing cairo*********/
        cairo_t* cn=cairo_t_singleton::get_context();
        cairo_save(cn);

        cairo_set_source_rgb(cn,
                             remap_color_1(cr),
                             remap_color_1(cg),
                             remap_color_1(cb));
        
        cairo_move_to(cn,xp,yp);
        cairo_line_to(cn,xp2,yp2);
        cairo_stroke(cn);
        cairo_restore(cn);
        
        /*****************/
        if(return_half_plane(xp, yp, 
                                 x1, y1,
                                 x2, y2 )){
          draw_parallel(xp, yp,
                            xp2, yp2,
                            cr,cg,cb,
                            false,
                            __pref.get_multiple_bond_gap(),tratt,true);
        }else{
          draw_parallel(xp, yp,
                            xp2, yp2,
                            cr,cg,cb,
                            true,
                            __pref.get_multiple_bond_gap(),tratt,true);
        }

      }else{
        fl_line_style(FL_SOLID,static_cast<int>(rintf(__pref.getZoom())),0);
        fl_begin_line();
        fl_vertex(xp+dx_scroll, yp+dy_scroll);
        fl_vertex(xp2+dx_scroll, yp2+dy_scroll);
        fl_end_line();
        fl_line_style(0);
        if(return_half_plane(xp, yp, 
                                 x1, y1,
                                 x2, y2 )){
          //cout << "iiotrue" << endl;
          draw_parallel(xp+dx_scroll, yp+dy_scroll,
                            xp2+dx_scroll, yp2+dy_scroll,
                            cr,cg,cb,
                            false,
                            __pref.get_multiple_bond_gap(),tratt,true); //preferenze
        }else{
          //cout << "iiofalse" << endl;
          draw_parallel(xp+dx_scroll, yp+dy_scroll,
                            xp2+dx_scroll, yp2+dy_scroll,
                            cr,cg,cb,
                            true,
                            __pref.get_multiple_bond_gap(),tratt,true); //preferenze
        }
























      }
  }else{


    if(cairo_t_singleton::can_export()){
      
      /****testing cairo*********/
      cairo_t* cn=cairo_t_singleton::get_context();
      cairo_save(cn);
      
      cairo_set_source_rgb(cn,
                           remap_color_1(cr),
                           remap_color_1(cg),
                           remap_color_1(cb));

      cairo_move_to(cn,x1,y1);
      cairo_line_to(cn,x2,y2);
      cairo_stroke(cn);
      cairo_restore(cn);
      
      /*****************/
      
    }else{
      fl_line_style(FL_SOLID,static_cast<int>(rintf(__pref.getZoom())),0);
      fl_begin_line();
      fl_vertex(x1+dx_scroll, y1+dy_scroll);
      fl_vertex(x2+dx_scroll, y2+dy_scroll);
      fl_end_line();
      fl_line_style(0);
    }

    vector<atomo> estremi;
    estremi.push_back(da);
    estremi.push_back(fino);
    vector<atomo>::iterator estr_iniz=estremi.begin();
    


    /*
      cout << "ESTREMI!!" << estremi.size()<<  endl;


      while(estr_iniz!=estr_fin){
      cout <<    (*estr_iniz).pos_x()  << "\t" <<  (*estr_iniz).pos_y() << endl;
      estr_iniz++;
      }

    */

    vector< vector<atomo> > legati;

    /*
      bool ritorna_semipiano_app(float x, float y,
      float xrt, float yrt,
      float xrt2, float yrt2 )
    */

    /*ordine: da_sopra, da_sotto, fino_sopra , fino_sotto*/

    for(int i=0; i<2;i++){
      //estr_iniz=estremi.begin();
      vector<legame>::iterator leginiz=(*estr_iniz).primo_leg();
      vector<legame>::iterator legfin=(*estr_iniz).ultimo_leg();
      vector<atomo> sopra;
      vector<atomo> sotto;

      while(leginiz!=legfin){


	for(unsigned int cta=0;cta<_atomi.size();cta++){
	  if(_atomi[cta].id()==(*leginiz).id_atomo() &&
	     _atomi[cta].id()!=estremi[0].id()       &&
	     _atomi[cta].id()!=estremi[1].id()
	     ){

	    /*
	      cout << "calcolo:\n"
	      <<  _atomi[cta].pos_x() << "\t" << _atomi[cta].pos_y() << endl
	      << (*estr_iniz).pos_x()  << "\t" <<  (*estr_iniz).pos_y() << endl
	      << (*(estr_iniz+1)).pos_x() <<"\t" <<  (*(estr_iniz+1)).pos_y() << endl;
	    */
	    /*
	      cout << "trovato:\n"
	      << _atomi[cta].id()
	      << "(" <<_atomi[cta].pos_x() << "," << _atomi[cta].pos_y() << ")"
	      << "da\n"
	      << (*estr_iniz).id()
	      << "(" <<(*estr_iniz).pos_x() << "," << (*estr_iniz).pos_y() << ")"
	      <<endl;
	    */

	    bool lato;

	    if(i==0){
	      lato=return_half_plane(_atomi[cta].pos_x(), _atomi[cta].pos_y(),
					 (*estr_iniz).pos_x(), (*estr_iniz).pos_y(),
					 (*(estr_iniz+1)).pos_x(), (*(estr_iniz+1)).pos_y() );

	    }else{

	      lato=return_half_plane(_atomi[cta].pos_x(), _atomi[cta].pos_y(),
					 (*(estr_iniz-1)).pos_x(), (*(estr_iniz-1)).pos_y(),
					 (*estr_iniz).pos_x(), (*estr_iniz).pos_y() );

	    }



	    if(lato){
	      sopra.push_back(_atomi[cta]);
	    }else{
	      sotto.push_back(_atomi[cta]);
	    }

	  }

	}


	leginiz++;
      }

      legati.push_back(sopra);
      legati.push_back(sotto);

      estr_iniz++;
    }



    //Abbiamo nel  vettore legati gli atomi  che sono legati  a quelli che
    //devono  formare   il  legame  doppio   secondo  l'ordine:  da_sopra,
    //da_sotto, fino_sopra , fino_sotto. Adesso dobbiamo controllare se vi
    //sono cicli.
    /*
      cout << da.id() << " " << fino.id() << endl;
      cout << "-------------------------------------" << endl;
      for(int p=0;p<legati.size();p++){
      cout << legati[p].size() << endl;
      }
      cout << "-------------------------------------" << endl;
    */


    //   for(int i=0;i<2;i++){ //da sopra, da_sotto

    //     for(int legct=0;legct<legati[i].size();legct++){ //scandiamo tutti i legami di partenza
    //       for(int finct=0;finct<legati[i+2].size();finct++){ //controlliamo i cicli
    // 	/*
    // 	cout << "controllo "
    // 	       << (legati[i])[legct].id()
    // 	       << " "
    // 	       << (legati[i+2])[finct].id() << endl;
    // 	*/
    // 	if(trova_ciclo((legati[i])[legct],(legati[i+2])[finct])){
    // 	  /*
    // 	  cout << "trovato ciclo "
    // 	       << (legati[i])[legct].id()
    // 	       << " "
    // 	       << (legati[i+2])[finct].id() << endl;
    // 	  */

    // 	  bool semipiano=ritorna_semipiano_app((legati[i])[legct].pos_x(),
    // 					       (legati[i])[legct].pos_y(),
    // 					       da.pos_x(), da.pos_y(),
    // 					       fino.pos_x(), fino.pos_y() );
    // 	  //	  cout << semipiano << endl;
    // 	  //cout << "ciclo" << endl;
    // 	  disegna_parallela(x1+dx_scroll, y1+dy_scroll,
    // 			    x2+dx_scroll, y2+dy_scroll,semipiano,
    // 			    __pref.get_multiple_bond_gap(),tratt);

    // 	  return;
    // 	}

    //       }
    //     }
    //   }




    atomo* ult;



    if(trova_ciclo(da,fino,&ult)){
      /*
	cout << "trovato ciclo "
	<< (legati[i])[legct].id()
	<< " "
	<< (legati[i+2])[finct].id() << endl;
      */

      bool semipiano=return_half_plane(ult->pos_x(),
					   ult->pos_y(),
					   da.pos_x(), da.pos_y(),
					   fino.pos_x(), fino.pos_y() );

      //	  cout << semipiano << endl;
      //cout << "ciclo" << endl;

      if(cairo_t_singleton::can_export()){
	draw_parallel(x1, y1,x2, y2,
                          cr,cg,cb,
                          semipiano,
			  __pref.get_multiple_bond_gap(),tratt); //preferenze

      }else{
	draw_parallel(x1+dx_scroll, y1+dy_scroll,
			  x2+dx_scroll, y2+dy_scroll,
                          cr,cg,cb,
                          semipiano,
			  __pref.get_multiple_bond_gap(),tratt); //preferenze
      }



    }else{



      //se siamo arrivati qui non c'e' alcun ciclo


      /*ordine: da_sopra, da_sotto, fino_sopra , fino_sotto*/


      if(legati[0].size()+legati[2].size()>legati[1].size()+legati[3].size()){


	if(cairo_t_singleton::can_export()){
	  draw_parallel(x1, y1,x2, y2,
                            cr,cg,cb,
                            true,
			    __pref.get_multiple_bond_gap(),tratt); //preferenze
	  
	}else{
	  draw_parallel(x1+dx_scroll, y1+dy_scroll,
			    x2+dx_scroll, y2+dy_scroll,
                            cr,cg,cb,
                            true,
			    __pref.get_multiple_bond_gap(),tratt); //preferenze
	}

	/*
          disegna_parallela(x1+dx_scroll, y1+dy_scroll,
          x2+dx_scroll, y2+dy_scroll,true,
          __pref.get_multiple_bond_gap(),tratt); //preferenze
	*/
      }else{
	if(cairo_t_singleton::can_export()){
	  draw_parallel(x1, y1,x2, y2,
                            cr,cg,cb,
                            false,
			    __pref.get_multiple_bond_gap(),tratt); //preferenze
	  
	}else{
	  draw_parallel(x1+dx_scroll, y1+dy_scroll,
			    x2+dx_scroll, y2+dy_scroll,
                            cr,cg,cb,
                            false,
			    __pref.get_multiple_bond_gap(),tratt); //preferenze
	}
	/*
          disegna_parallela(x1+dx_scroll, y1+dy_scroll,
          x2+dx_scroll, y2+dy_scroll,false,
          __pref.get_multiple_bond_gap(),tratt); //preferenze
	*/
      }


      /*
	disegna_parallela(x1+dx_scroll, y1+dy_scroll,
	x2+dx_scroll, y2+dy_scroll,true,
	__pref.get_multiple_bond_gap(),tratt);
      */
    }

  }
}



bool gruppo::trova_ciclo(atomo& da , atomo& fino, atomo ** ultimo){


  //cout << da.id() << " " << fino.id() << endl;

//   stack<atomo*> pila;
//   vector<int> visti;
//   vector<int> da_visti;



//   int visitato=da.ultimo_leg()-da.primo_leg();
//   bool grigio=true;

//   pila.push(&da);

//   while(pila.size()>0){
//     //cout << "size " << pila.size() << endl;
//     atomo* cima=pila.top();
//     pila.pop();
//     //cout << "estratto " << cima->id()<<endl;

//     if(cima->id()==da.id()){
//       visitato--;
//     }

//     if(visitato<=0){
//       return false;
//     }

//     bool e_visto=false;

//     /*
//     cout << "vvvvvvvvvvvvvvvvvvv"<< endl;
//     for(int i=0;i<visti.size();i++){
//       cout << visti[i] << endl;
//     }
//     cout << "vvvvvvvvvvvvvvvvvvv"<< endl;
//     */

//     for(int i=0;i<visti.size();i++){
//       if(visti[i]==cima->id()){
// 	e_visto=true;
// 	break;
//       }
//     }


//     //cout << cima->id() << " " << e_visto << endl;
//     vector<legame>::iterator primo=cima->primo_leg();
//     vector<legame>::iterator ultimo=cima->ultimo_leg();
//     atomo* da_visit;
//       while(primo!=ultimo){
//     	for(int i=0;i<_atomi.size();i++){
// 	  if(_atomi[i].id()==(*primo).id_atomo()){
// 	    da_visit=&_atomi[i];
// 	  }
// 	}
// 	primo++;
//       }

//     if(!e_visto){
//       pila.push(da_visit);
//     }else{
//       if(da_visit->id()==da.id()){
// 	visitato--;
//       }
//     }



//     visti.push_back(cima->id());

//   }

//   //cout << "VV" << visitato << endl;
//   if(visitato<0){
//     return true;
//   }else{
//     return false;
//   }

//   return false;

  vector<int> visti(_atomi.size(),0);
  vector<int> grigi(_atomi.size(),0);
  vector<int> genit(_atomi.size(),0);
  bool risult=false;
  bool primo_e_adiacente=false;
  // cout << "\nrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrrr" <<endl;

//   cout << "cerco ciclo " << da.id() << " " << fino.id() << endl;
//   cout << "atomi: " << endl;

//   for (unsigned int i=0;i<_atomi.size();i++){
//     cout << _atomi[i].id() << ",";
//   }
  //cout <<endl;
  depth_first_ciclo(&da , &da, &fino, grigi, visti, genit, risult,ultimo,primo_e_adiacente);

  return risult;

}


void gruppo::depth_first_ciclo(atomo* st , atomo* da,
			       atomo* fino, vector<int>& grigi,
			       vector<int>& visitati,
			       vector <int>& genitore,
			       bool& risult, atomo** ultimo,bool& primo_e_adiacente){


  if(visitati[get_position_inarr(fino->id())]==1){
    //cout << "qwerty: fino is black"  << std::endl;
    risult=false;
    return;
  }


  //cout << "RIsult " << risult << endl;
  if(risult){
    return;
  }

  //  cout << "parto da: " << st->id() << endl;;

  grigi[get_position_inarr(st->id())]=1;





  vector<legame>::iterator inleg=st->iniz_leg();
  vector<legame>::iterator finleg=st->fin_leg();

  while(inleg!=finleg){

    if(risult){
      return;
    }

    atomo* nuovost=0;

    if(st->id()==da->id() && !primo_e_adiacente){
      primo_e_adiacente=true;
      nuovost=fino;
    }else{
      for(unsigned int atct=0;atct<_atomi.size();atct++){
	if(_atomi[atct].id()==(*inleg).id_atomo()){//trovato nuovo atomo
	  if(_atomi[atct].id()!=fino->id() || primo_e_adiacente){
	    nuovost=&_atomi[atct];
	    break;
	  }
	}
      }
    }


    //cout << "trovato atomo "<< nuovost->id();
    int colgr=grigi[get_position_inarr(nuovost->id())];

    int colbl=visitati[get_position_inarr(nuovost->id())];
    if(colgr==0 && colbl==0){ //bianco mai visitato
      //cout << " mai visitato ";
      genitore[get_position_inarr(st->id())]=nuovost->id();


      /*
      cout << "impostato genitore["
	   << get_position_inarr(st->id())
	   << "]=" << nuovost->id() << " di " << st->id() <<  endl;
     
	cout << "\ngenitori : ";
	for(unsigned int i=0;i<genitore.size();i++){
	  cout << genitore[i] << ",";
	}
	cout << endl;
      */



	depth_first_ciclo(nuovost , da, fino, grigi, visitati, genitore, risult,
			  ultimo,primo_e_adiacente);
    }else{
      if(colgr==1 && colbl==0){
	//cout  << " grigio "  ;
	if(genitore[get_position_inarr(nuovost->id())]!=st->id()){
	  //cout << "ciclo" << endl;
	  //cout << "figlio di (" <<  get_position_inarr(nuovost->id())
	  //    << "): " << genitore[get_position_inarr(nuovost->id())] << " " << st->id() << endl;
	  //for(unsigned int i=0;i<genitore.size();i++){
	  //  cout << genitore[i] << ",";
	  //}
	  //cout << endl;

	  if(nuovost->id()==da->id()){
	    (*ultimo)=st;
	    //cout << "ultimo del ciclo " << (*ultimo)->id() << endl;
	    risult=true;
	    return;
	  }else{
	    //cout << "ma e' un altro ciclo quindi continuo l'esplorazione" << endl;
	  }
	}
	//cout << "figlio di (" <<  get_position_inarr(nuovost->id())
	//     << "): " << genitore[get_position_inarr(nuovost->id())] << " " << st->id() << endl;
	//cout << "genitori : ";
	//for(unsigned int i=0;i<genitore.size();i++){
	// cout << genitore[i] << ",";
	//}
	//cout << endl;
      }
    }

    inleg++;
    }
  visitati[get_position_inarr(st->id())]=1;

}


atomo* gruppo::find_atomo_id(int id){
  atomo* risul=0;
  for(unsigned int i=0;i<_atomi.size();i++){
    if(_atomi[i].id()==id){
      risul=&_atomi[i];
    }
  }
  return risul;
}


procedura* gruppo::find_proc_id(int id){
  procedura* risul=0;
  for(unsigned int i=0;i<_procedure.size();i++){
    if(_procedure[i]->id()==id){
      risul=_procedure[i];
    }
  }
  return risul;
}

int gruppo::get_position_inarr(int id){

  for(unsigned int i=0;i<_atomi.size();i++){
    if(_atomi[i].id()==id){
      return i;
    }
  }
  cout << "ma qui!!!!" << endl;
  return -1;
}

void gruppo::generic_depth_search(atomo* da, void* data, void* data2 ,void* data3,
				  int (*pf)(atomo* da , atomo* fino,
					    void* data, void* data2, void* data3) ){
  //cout << da.id() << " " << fino.id() << endl;

  int (*applica)(atomo* da , atomo* fino,
		 void* data, void* data2, void* data3)=pf;

  stack<atomo*> pila;
  vector<int> visti;

  pila.push(da);

  while(pila.size()>0){
    //cout << "size " << pila.size() << endl;
    atomo* cima=pila.top();
    pila.pop();
    //cout << "estratto " << cima->id()<<endl;

    bool e_visto=false;


    /*
    cout << "trasl------------------"<< endl;
    for(unsigned int i=0;i<visti.size();i++){
      cout << "trasl " <<  visti[i] << endl;
    }
    cout << "trasl ==============="<< endl;
    */


    for(unsigned int i=0;i<visti.size();i++){
      if(visti[i]==cima->id()){
	e_visto=true;
	break;
      }
    }

    //cout << "trasl cima " << cima->id() << " " << e_visto<< endl;

    //cout << "gruppo: " <<  id() << endl;
    if(!e_visto){

      vector<legame>::iterator primo=cima->primo_leg();
      vector<legame>::iterator ultimo=cima->ultimo_leg();
      //cout << ultimo -primo << " "<< endl;
      while(primo!=ultimo){
	//cout << cima->id() << " " << (*primo).id_atomo() << endl;
	for(unsigned int i=0;i<_atomi.size();i++){
	  if(_atomi[i].id()==(*primo).id_atomo()){
	    applica(cima,&_atomi[i],data,data2,data3);
	    pila.push(&_atomi[i]);
	  }
	}

	primo++;
      }
      //cout << "--------------" << endl;
    }

    visti.push_back(cima->id());

  }

}





void gruppo::generic_depth_search(atomo* da, void* data, void* data2 ,void* data3,void* data4,
				  int (*map_atom)(atomo* da , atomo* fino,
                                                  void* data, void* data2, void* data3),
                                  bool(*ignore)(atomo* atm, void* data4)
                                  )
{
  //cout << da.id() << " " << fino.id() << endl;

  int (*applica)(atomo* da , atomo* fino,
		 void* data, void* data2, void* data3)=map_atom;

  stack<atomo*> pila;
  vector<int> visti;

  pila.push(da);

  while(pila.size()>0){
    //cout << "size " << pila.size() << endl;
    atomo* cima=pila.top();
    pila.pop();
    //cout << "estratto " << cima->id()<<endl;

    bool e_visto=false;


    /*
    cout << "trasl------------------"<< endl;
    for(unsigned int i=0;i<visti.size();i++){
      cout << "trasl " <<  visti[i] << endl;
    }
    cout << "trasl ==============="<< endl;
    */


    for(unsigned int i=0;i<visti.size();i++){
      if(visti[i]==cima->id()){
	e_visto=true;
	break;
      }
    }

    //cout << "trasl cima " << cima->id() << " " << e_visto<< endl;

    //cout << "gruppo: " <<  id() << endl;
    if(!e_visto &&
       !ignore(cima,data4)
       ){

      vector<legame>::iterator primo=cima->primo_leg();
      vector<legame>::iterator ultimo=cima->ultimo_leg();
      //cout << ultimo -primo << " "<< endl;
      while(primo!=ultimo){
	//cout << cima->id() << " " << (*primo).id_atomo() << endl;
	for(unsigned int i=0;i<_atomi.size();i++){
	  if(_atomi[i].id()==(*primo).id_atomo()){
	    applica(cima,&_atomi[i],data,data2,data3);
	    pila.push(&_atomi[i]);
	  }
	}

	primo++;
      }
      //cout << "--------------" << endl;
    }

    visti.push_back(cima->id());

  }

}



void gruppo::generic_depth_search_appl_popped(atomo* da, void* data, void* data2 ,
                                              void* data3, void* data4,
					      int (*pf)(atomo* da ,void* data, 
							void* data2, void* data3) ,
                                              bool(*ignore)(atomo* atm, void* data4)){

  int (*applica)(atomo* da,
		 void* data, void* data2, void* data3)=pf;
  stack<atomo*> pila;
  vector<int> visti;
  pila.push(da);

  while(pila.size()>0){
    atomo* cima=pila.top();
    pila.pop();
    bool e_visto=false;

    for(unsigned int i=0;i<visti.size();i++){
      if(visti[i]==cima->id()){
	e_visto=true;
	break;
      }
    }

    //cout << "trasl cima " << cima->id() << " " << e_visto<< endl;

    //cout << "gruppo: " <<  id() << endl;
    if(!e_visto &&
       !ignore(cima,data4)){
      applica(cima,data,data2,data3);
      vector<legame>::iterator primo=cima->primo_leg();
      vector<legame>::iterator ultimo=cima->ultimo_leg();
      while(primo!=ultimo){
	for(unsigned int i=0;i<_atomi.size();i++){
	  if(_atomi[i].id()==(*primo).id_atomo()){
	    pila.push(&_atomi[i]);
	  }
	}

	primo++;
      }
    }
    visti.push_back(cima->id());
  }
}



void gruppo::generic_depth_search_appl_popped(atomo* da, void* data, void* data2 ,void* data3,
					      int (*pf)(atomo* da ,void* data, 
							void* data2, void* data3) ){

  int (*applica)(atomo* da,
		 void* data, void* data2, void* data3)=pf;
  stack<atomo*> pila;
  vector<int> visti;
  pila.push(da);

  while(pila.size()>0){
    atomo* cima=pila.top();
    pila.pop();
    bool e_visto=false;

    for(unsigned int i=0;i<visti.size();i++){
      if(visti[i]==cima->id()){
	e_visto=true;
	break;
      }
    }

    //cout << "trasl cima " << cima->id() << " " << e_visto<< endl;

    //cout << "gruppo: " <<  id() << endl;
    if(!e_visto){
      applica(cima,data,data2,data3);
      vector<legame>::iterator primo=cima->primo_leg();
      vector<legame>::iterator ultimo=cima->ultimo_leg();
      while(primo!=ultimo){
	for(unsigned int i=0;i<_atomi.size();i++){
	  if(_atomi[i].id()==(*primo).id_atomo()){
	    pila.push(&_atomi[i]);
	  }
	}

	primo++;
      }
    }
    visti.push_back(cima->id());
  }
}


void gruppo::no_componenti_connesse(int& no){
  no=0;
  vector<int> visti;

  for(unsigned int ctgr=0;ctgr<_atomi.size();ctgr++){
    bool trov=false;

    for(unsigned int trvct=0;trvct<visti.size();trvct++){
      if(visti[trvct]==_atomi[ctgr].id()){
	trov=true;
	break;
      }
    }

    if(!trov){
      no++;
      atomo* da=&_atomi[ctgr];
      stack<atomo*> pila;
    
      pila.push(da);
    
      while(pila.size()>0){
	//cout << "size " << pila.size() << endl;
	atomo* cima=pila.top();
	pila.pop();
	//cout << "estratto " << cima->id()<<endl;
      
	bool e_visto=false;


	/*
	  cout << "------------------"<< endl;
	  for(int i=0;i<visti.size();i++){
	  cout << visti[i] << endl;
	  }
	  cout << "==============="<< endl;
	*/


	for(unsigned int i=0;i<visti.size();i++){
	  if(visti[i]==cima->id()){
	    e_visto=true;
	    break;
	  }
	}
      
	//    cout << cima->id() << " " << e_visto<< endl;
      
	//cout << "gruppo: " <<  id() << endl;
	if(!e_visto){
	
	  vector<legame>::iterator primo=cima->primo_leg();
	  vector<legame>::iterator ultimo=cima->ultimo_leg();
	  //cout << ultimo -primo << " "<< endl;
	  while(primo!=ultimo){
	    //cout << cima->id() << " " << (*primo).id_atomo() << endl;
	    for(unsigned int i=0;i<_atomi.size();i++){
	      if(_atomi[i].id()==(*primo).id_atomo()){
		pila.push(&_atomi[i]);
	      }
	    }
	  
	    primo++;
	  }
	  //cout << "--------------" << endl;
	}
      
	visti.push_back(cima->id());

      }
    }

    
  }

}




void gruppo::renderizza_stereo_scon(float x1,float y1,
				    float x2,float y2,
                                    int cr, int cg, int cb){

  float compx=x2-x1;
  float compy=y2-y1;
  float alfa=atan2(compx,compy)-M_PI/2.0;
  float lung=sqrt( pow(compx,2) + pow(compy,2) );
  float laics=0;
  float laips=0;
  float ampiezza=__pref.get_ampiezza_stereo_scon(); //preferenze
  float frequenza=__pref.get_frequenza_stereo_scon();//preferenze

  if(!cairo_t_singleton::can_export()){
    ampiezza*=__pref.getZoom();
    frequenza/=__pref.getZoom();
  }


  while(laics<lung){
      laips=ampiezza * sin(frequenza * laics);

      float x=laics;
      float y=laips;

      float xp=x*cos(alfa)+y*sin(alfa);
      float yp=y*cos(alfa)-x*sin(alfa);

      if(cairo_t_singleton::can_export()){
      
        /****testing cairo*********/
        cairo_t* cn=cairo_t_singleton::get_context();
        cairo_save(cn);
        
        cairo_set_source_rgb(cn,
                             remap_color_1(cr),
                             remap_color_1(cg),
                             remap_color_1(cb));
        
        cairo_arc(cn,xp+x1,yp+y1,0.1,0,2*M_PI);
        cairo_fill(cn);
        cairo_restore(cn);
        
        /*****************/
        
      }else{
        if(__pref.getZoom()<=1){
          fl_color(cr,cg,cb);
          fl_point(static_cast<int>(rintf(xp+x1)),
                   static_cast<int>(rintf(yp+y1)));
        }else{
          fl_line_style(FL_SOLID,static_cast<int>(rintf(__pref.getZoom())),0);
          float radius=(__pref.getZoom()/2.0)+0.1;
          fl_color(cr,cg,cb);
          fl_begin_complex_polygon();
	  fl_circle(xp+x1,yp+y1,radius);
	  fl_end_complex_polygon();
	  fl_line_style(0);
	}
      }
      laics+=0.1;

  }

}

 void gruppo::renderizza_ispessito(float x1, float y1,
				   float x2, float y2,
                                   int cr, int cg, int cb){
   float vert2x;
   float vert2y;
   float vert3x;
   float vert3y;
   float larg_cuneo=__pref.get_larg_max_cuneo(); //preferenze

   if(!cairo_t_singleton::can_export()){
     larg_cuneo*=__pref.getZoom();
   }

   is_perpendicular(x1, y1,
			x2, y2,
			true,larg_cuneo,
			vert2x, vert2y);

   is_perpendicular(x1, y1,
			x2, y2,
			false,larg_cuneo,
			vert3x, vert3y);

   if(cairo_t_singleton::can_export()){
      
      /****testing cairo*********/
      cairo_t* cn=cairo_t_singleton::get_context();
      cairo_save(cn);
      
      cairo_set_source_rgb(cn,
                           remap_color_1(cr),
                           remap_color_1(cg),
                           remap_color_1(cb));

      cairo_move_to(cn,vert2x+x1, vert2y+y1);
      cairo_line_to(cn,vert2x+x1, vert2y+y1);
      cairo_line_to(cn,vert3x+x1, vert3y+y1);
      cairo_line_to(cn,vert3x+x2, vert3y+y2);
      cairo_line_to(cn,vert2x+x2, vert2y+y2);
      cairo_line_to(cn,vert2x+x1, vert2y+y1);
      cairo_fill(cn);
      cairo_restore(cn);
      
      /*****************/
      
    }else{
     fl_color(cr,cg,cb);
     fl_begin_polygon();
     fl_vertex(vert2x+x1,vert2y+y1);
     fl_vertex(vert3x+x1,vert3y+y1);
     fl_vertex(vert3x+x2,vert3y+y2);
     fl_vertex(vert2x+x2,vert2y+y2);
     fl_end_polygon();
   }
 }

void gruppo::renderizza_stereo_up(atomo &da, atomo& fino,
				  float strettox, float strettoy,
				  float largox, float largoy,
                                  int cr, int cg, int cb){

  //cout << "iii:fino.id() " << fino.id() << endl;
  

  int dx_scroll=0;
  int dy_scroll=0;
  if(!cairo_t_singleton::can_export()){
    dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
    dy_scroll=(MainWindow->ritorna_mol_canvas())->y();
  }

  float vert2x;
  float vert2y;
  float vert3x;
  float vert3y;
  float larg_cuneo=__pref.get_larg_max_cuneo(); //preferenze
  if(!cairo_t_singleton::can_export()){
    larg_cuneo*=__pref.getZoom();
  }
  

  is_perpendicular(strettox, strettoy,
		       largox, largoy,
		       true,larg_cuneo,
		       vert2x, vert2y);

  is_perpendicular(strettox, strettoy,
		       largox, largoy,
		       false,larg_cuneo,
		       vert3x, vert3y);

  vert2x+=largox;
  vert2y+=largoy;

  vert3x+=largox;
  vert3y+=largoy;

  etichetta sy=fino.etich();
  vector < pair<string,int> > stringhe=sy.vec_str();
  bool noetic=true;

  if(stringhe.size()>0){
    if(stringhe[0].first!=string(NO_ETIC)){
      noetic=false;
    }
  }

  if(fino.ultimo_leg()-fino.primo_leg()==1 || !noetic){

    if(cairo_t_singleton::can_export()){
      
      /****testing cairo*********/
      cairo_t* cn=cairo_t_singleton::get_context();
      cairo_save(cn);
      
      cairo_set_source_rgb(cn,
                           remap_color_1(cr),
                           remap_color_1(cg),
                           remap_color_1(cb));

      cairo_move_to(cn,strettox, strettoy);
      cairo_line_to(cn,strettox, strettoy);
      cairo_line_to(cn,vert2x, vert2y);
      cairo_line_to(cn,vert3x, vert3y);
      cairo_line_to(cn,strettox, strettoy);
      cairo_fill(cn);
      cairo_restore(cn);
      
      /*****************/
      
    }else{
     
      fl_color(cr,cg,cb);
      fl_begin_polygon();
      fl_vertex(strettox+dx_scroll,strettoy+dy_scroll);
      fl_vertex(vert2x+dx_scroll,vert2y+dy_scroll);
      fl_vertex(vert3x+dx_scroll,vert3y+dy_scroll);
      fl_end_polygon();
    }
  }else if(fino.ultimo_leg()-fino.primo_leg()==2){


    /*					     /-
                       mcun		  /--
	                      /----+    /-   mleg
	          /-----------     | /--
    	    ---\--        	   +-
	        -------\ 	   |
		       	-------\   |
				---+
		      mcun2

    */

    





    float xleg=-1;
    float yleg=-1;
    vector<legame>::iterator legatoin=fino.primo_leg();
    vector<legame>::iterator legatofin=fino.ultimo_leg();
    int id_leg=-1;
    int tipo_leg=-1;
    while(legatoin!=legatofin){
      if((*legatoin).id_atomo()!=da.id()){
	id_leg=(*legatoin).id_atomo();
	tipo_leg=(*legatoin).tipo_legame();
      }
      legatoin++;
    }
      for(unsigned int i=0;i<_atomi.size();i++){
	if(_atomi[i].id()==id_leg){
	  xleg=_atomi[i].pos_x();
	  yleg=_atomi[i].pos_y();
	}
      }


      if(tipo_leg==LEGAME_ISPESSITO){
	float x_clip_lato1;
	float y_clip_lato1;
	
	float x_clip_lato2;
	float y_clip_lato2;
	
	float xy_lato1_a[2];//intersezione primo lato cuneo primo lato rettangolo
	float xy_lato1_b[2];//intersezione primo lato cuneo secondo lato rettangolo
	/*
	float xy_lato2_a[2];//intersezione secondo lato cuneo primo lato rettangolo
	float xy_lato2_b[2];//intersezione secondo lato cuneo secondo lato rettangolo
	*/
	float vertax;
	float vertay;
	float vertbx;
	float vertby;
	float larg_cuneo=__pref.get_larg_max_cuneo(); //preferenze
	if(!cairo_t_singleton::can_export()){
	  larg_cuneo*=__pref.getZoom();
	}


	is_perpendicular(fino.pos_x(), fino.pos_y(),
			     xleg, yleg,
			     true,larg_cuneo,
			     vertax, vertay);
	
	is_perpendicular(fino.pos_x(), fino.pos_y(),
			     xleg, yleg,
			     false,larg_cuneo,
			     vertbx, vertby);
	
	
	clip_lato_cuneo(xy_lato1_a,vertax+fino.pos_x(),vertay+fino.pos_y(),
			xleg+vertax,yleg+vertay,strettox, strettoy,
			vert2x, vert2y);
	
	clip_lato_cuneo(xy_lato1_b,vertbx+fino.pos_x(),vertby+fino.pos_y(),
			xleg+vertbx,yleg+vertby,strettox, strettoy,
			vert2x, vert2y);


	float lung_lato1_a=sqrt(pow(static_cast<double>(xy_lato1_a[0]-strettox),2.0)+
				pow(static_cast<double>(xy_lato1_a[1]-strettoy),2.0));

	float lung_lato1_b=sqrt(pow(static_cast<double>(xy_lato1_b[0]-strettox),2.0)+
				pow(static_cast<double>(xy_lato1_b[1]-strettoy),2.0));


	if(lung_lato1_a<=lung_lato1_b){
	  x_clip_lato1=xy_lato1_b[0];
	  y_clip_lato1=xy_lato1_b[1];
	}else{
	  x_clip_lato1=xy_lato1_a[0];
	  y_clip_lato1=xy_lato1_a[1];
	}


	//otro 

	clip_lato_cuneo(xy_lato1_a,vertax+fino.pos_x(),vertay+fino.pos_y(),
			xleg+vertax,yleg+vertay,strettox, strettoy,
			vert3x, vert3y);
	
	clip_lato_cuneo(xy_lato1_b,vertbx+fino.pos_x(),vertby+fino.pos_y(),
			xleg+vertbx,yleg+vertby,strettox, strettoy,
			vert3x, vert3y);


	lung_lato1_a=sqrt(pow(xy_lato1_a[0]-strettox,2)+pow(xy_lato1_a[1]-strettoy,2));
	lung_lato1_b=sqrt(pow(xy_lato1_b[0]-strettox,2)+pow(xy_lato1_b[1]-strettoy,2));

	if(lung_lato1_a<=lung_lato1_b){
	  x_clip_lato2=xy_lato1_b[0];
	  y_clip_lato2=xy_lato1_b[1];
	}else{
	  x_clip_lato2=xy_lato1_a[0];
	  y_clip_lato2=xy_lato1_a[1];
	}

        if(cairo_t_singleton::can_export()){
          
          /****testing cairo*********/
          cairo_t* cn=cairo_t_singleton::get_context();
          cairo_save(cn);
          
          cairo_set_source_rgb(cn,
                               remap_color_1(cr),
                               remap_color_1(cg),
                               remap_color_1(cb));
          
          cairo_move_to(cn,strettox, strettoy);
          cairo_line_to(cn,strettox, strettoy);
          cairo_line_to(cn,x_clip_lato1, y_clip_lato1);
          cairo_line_to(cn,x_clip_lato2, y_clip_lato2);
          cairo_line_to(cn,strettox, strettoy);
          cairo_fill(cn);
          cairo_restore(cn);
          
          /*****************/
      
        }else{
          fl_color(cr,cg,cb);
	  fl_begin_polygon();
	  fl_vertex(strettox+dx_scroll,strettoy+dy_scroll);
	  fl_vertex(x_clip_lato1+dx_scroll,y_clip_lato1+dy_scroll);
	  fl_vertex(x_clip_lato2+dx_scroll,y_clip_lato2+dy_scroll);
	  fl_end_polygon();
	}


      }else{
	float xy_lato1[2];
	float xy_lato2[2];
	
	clip_lato_cuneo(xy_lato1,fino.pos_x(),fino.pos_y(),
			xleg,yleg,strettox, strettoy,
			vert2x, vert2y);
	

	
	clip_lato_cuneo(xy_lato2,fino.pos_x(),fino.pos_y(),
			xleg,yleg,strettox, strettoy,
			vert3x, vert3y);


        if(cairo_t_singleton::can_export()){
          
          /****testing cairo*********/
          cairo_t* cn=cairo_t_singleton::get_context();
          cairo_save(cn);
          
          cairo_set_source_rgb(cn,
                               remap_color_1(cr),
                               remap_color_1(cg),
                               remap_color_1(cb));
          
          cairo_move_to(cn,strettox, strettoy);
          cairo_line_to(cn,strettox, strettoy);
          cairo_line_to(cn,xy_lato1[0], xy_lato1[1]);
          cairo_line_to(cn,xy_lato2[0], xy_lato2[1]);
          cairo_line_to(cn,strettox, strettoy);
          cairo_fill(cn);
          cairo_restore(cn);
          
          /*****************/
      
        }else{

	  //cout << "YYYYYYYYYYYYYYYYYYYYYY" << endl;
	  //float z=__pref.getZoom();
          fl_color(cr,cg,cb);
	  fl_begin_polygon();
	  fl_vertex(strettox+dx_scroll,strettoy+dy_scroll);
	  fl_vertex(xy_lato1[0]+dx_scroll,xy_lato1[1]+dy_scroll);
	  fl_vertex(xy_lato2[0]+dx_scroll,xy_lato2[1]+dy_scroll);
	  fl_end_polygon();
	}
      }

  }else{//clip attorno ai legami piu' prossimi
    vector<legame>::iterator legatoin=fino.primo_leg();
    vector<legame>::iterator legatofin=fino.ultimo_leg();
    bool has_bold=false;
    int id_leg=-1;

    while(legatoin!=legatofin){
      if((*legatoin).tipo_legame()==LEGAME_ISPESSITO){
	id_leg=(*legatoin).id_atomo();
	has_bold=true;
	break;
      }
      legatoin++;
    }


    if(has_bold){
      float xleg=-1;
      float yleg=-1;
      for(unsigned int i=0;i<_atomi.size();i++){
	if(_atomi[i].id()==id_leg){
	  xleg=_atomi[i].pos_x();
	  yleg=_atomi[i].pos_y();
	}
      }


      float x_clip_lato1;
      float y_clip_lato1;
      
      float x_clip_lato2;
      float y_clip_lato2;
      
      float xy_lato1_a[2];//intersezione primo lato cuneo primo lato rettangolo
      float xy_lato1_b[2];//intersezione primo lato cuneo secondo lato rettangolo
      /*
	float xy_lato2_a[2];//intersezione secondo lato cuneo primo lato rettangolo
	float xy_lato2_b[2];//intersezione secondo lato cuneo secondo lato rettangolo
      */
      float vertax;
      float vertay;
      float vertbx;
      float vertby;
      float larg_cuneo=__pref.get_larg_max_cuneo(); //preferenze
      is_perpendicular(fino.pos_x(), fino.pos_y(),
			   xleg, yleg,
			   true,larg_cuneo,
			   vertax, vertay);
      
      is_perpendicular(fino.pos_x(), fino.pos_y(),
			   xleg, yleg,
			   false,larg_cuneo,
			   vertbx, vertby);
      
      
      clip_lato_cuneo(xy_lato1_a,vertax+fino.pos_x(),vertay+fino.pos_y(),
		      xleg+vertax,yleg+vertay,strettox, strettoy,
		      vert2x, vert2y);
      
      clip_lato_cuneo(xy_lato1_b,vertbx+fino.pos_x(),vertby+fino.pos_y(),
		      xleg+vertbx,yleg+vertby,strettox, strettoy,
		      vert2x, vert2y);
      
      
      float lung_lato1_a=sqrt(pow(static_cast<double>(xy_lato1_a[0]-strettox),2.0)+
			      pow(static_cast<double>(xy_lato1_a[1]-strettoy),2.0));
      
      float lung_lato1_b=sqrt(pow(static_cast<double>(xy_lato1_b[0]-strettox),2.0)+
			      pow(static_cast<double>(xy_lato1_b[1]-strettoy),2.0));
      
      
      if(lung_lato1_a<=lung_lato1_b){
	x_clip_lato1=xy_lato1_b[0];
	y_clip_lato1=xy_lato1_b[1];
      }else{
	x_clip_lato1=xy_lato1_a[0];
	y_clip_lato1=xy_lato1_a[1];
      }
      
      
      //otro 
      
      clip_lato_cuneo(xy_lato1_a,vertax+fino.pos_x(),vertay+fino.pos_y(),
		      xleg+vertax,yleg+vertay,strettox, strettoy,
		      vert3x, vert3y);
      
      clip_lato_cuneo(xy_lato1_b,vertbx+fino.pos_x(),vertby+fino.pos_y(),
		      xleg+vertbx,yleg+vertby,strettox, strettoy,
		      vert3x, vert3y);
      

      lung_lato1_a=sqrt(pow(xy_lato1_a[0]-strettox,2)+pow(xy_lato1_a[1]-strettoy,2));
      lung_lato1_b=sqrt(pow(xy_lato1_b[0]-strettox,2)+pow(xy_lato1_b[1]-strettoy,2));
      
      if(lung_lato1_a<=lung_lato1_b){
	x_clip_lato2=xy_lato1_b[0];
	y_clip_lato2=xy_lato1_b[1];
      }else{
	x_clip_lato2=xy_lato1_a[0];
	y_clip_lato2=xy_lato1_a[1];
      }



      if(cairo_t_singleton::can_export()){
        
        /****testing cairo*********/
        cairo_t* cn=cairo_t_singleton::get_context();
        cairo_save(cn);
        
        cairo_set_source_rgb(cn,
                             remap_color_1(cr),
                             remap_color_1(cg),
                             remap_color_1(cb));
        
        cairo_move_to(cn,strettox, strettoy);
        cairo_line_to(cn,strettox, strettoy);
        cairo_line_to(cn,x_clip_lato1, y_clip_lato1);
	cairo_line_to(cn,x_clip_lato2, y_clip_lato2);
        cairo_line_to(cn,strettox, strettoy);
        cairo_fill(cn);
        cairo_restore(cn);
        
        /*****************/
        
      }else{
        fl_color(cr,cg,cb);
	fl_begin_polygon();
	fl_vertex(strettox+dx_scroll,strettoy+dy_scroll);
	fl_vertex(x_clip_lato1+dx_scroll,y_clip_lato1+dy_scroll);
	fl_vertex(x_clip_lato2+dx_scroll,y_clip_lato2+dy_scroll);
	fl_end_polygon();
      }
     
    }else{
      vector<float*> xy_clip_a;
      vector<float*> xy_clip_b;
      vector<float> xleg;
      vector<float> yleg;

      vector<legame>::iterator legatoin=fino.primo_leg();
      vector<legame>::iterator legatofin=fino.ultimo_leg();

      while(legatoin!=legatofin){
	if((*legatoin).id_atomo()!=da.id()){
	  atomo* found=find_atomo_id((*legatoin).id_atomo());
	  if(found != NULL){
	    if(fino.ultimo_leg()-fino.primo_leg()<=3){
	      xleg.push_back(found->pos_x());
	      yleg.push_back(found->pos_y());
	    }else{
	      float m1=1;
	      float q1=1;
	      rett_eqn(da.pos_x()  , da.pos_y(),
		       fino.pos_x(), fino.pos_y(),
		       m1, q1);
	      float m2=1;
	      float q2=1;
	      rett_eqn(fino.pos_x(), fino.pos_y(),
		       found->pos_x(), found->pos_y(),
		       m2, q2);
	      if(!similar_to(m1,m2,DEFAULT_SIMILAR_THRESHOLD)){

		xleg.push_back(found->pos_x());
		yleg.push_back(found->pos_y());
		
	      }
	    }
	  }
	}
	legatoin++;
      }      




      for(unsigned int i=0;i<xleg.size();i++){
	float* coordclip_a=new float[2];
	float* coordclip_b=new float[2];
	clip_lato_cuneo(coordclip_a,
			fino.pos_x(),fino.pos_y(),
			xleg[i],yleg[i],
			strettox, strettoy,
			vert2x, vert2y);
	float lung_seg_clip=sqrt(pow(coordclip_a[0]-xleg[i],2)+pow(coordclip_a[1]-yleg[i],2));
	float lung_seg=sqrt(pow(fino.pos_x()-xleg[i],2)+pow(fino.pos_y()-yleg[i],2));

	if(lung_seg_clip<lung_seg){
	  xy_clip_a.push_back(coordclip_a);
	}else if(static_cast<int>(coordclip_a[0])==static_cast<int>(vert2x) &&  
		 static_cast<int>(coordclip_a[1])==static_cast<int>(vert2y)){
	  coordclip_a[0]=vert2x;
	  coordclip_a[1]=vert2y;
	  xy_clip_a.push_back(coordclip_a);
	}

      

	clip_lato_cuneo(coordclip_b,
			fino.pos_x(),fino.pos_y(),
			xleg[i],yleg[i],
			strettox, strettoy,
			vert3x, vert3y);

	lung_seg_clip=sqrt(pow(coordclip_b[0]-xleg[i],2)+pow(coordclip_b[1]-yleg[i],2));
	
	
	if(lung_seg_clip<lung_seg){
	  xy_clip_b.push_back(coordclip_b);
	}else if(static_cast<int>(coordclip_b[0])==static_cast<int>(vert3x) &&  
		 static_cast<int>(coordclip_b[1])==static_cast<int>(vert3y)){
	  coordclip_b[0]=vert3x;
	  coordclip_b[1]=vert3y;
	  xy_clip_b.push_back(coordclip_b);
	}

      }

      unsigned int posclip_a=0;
      if(xy_clip_a.size()>0){
	//cout << "iiia" << xy_clip_a.size() << endl;
	float min_a=10000000;

	for(unsigned int c1=0;c1<xy_clip_a.size();c1++){
	  float lung=sqrt(pow(xy_clip_a[c1][0]-strettox,2)+pow(xy_clip_a[c1][1]-strettoy,2));
	  if(min_a>lung){
	    min_a=lung;
	    posclip_a=c1;
	  }
	}
	
      }else{
	float* coordclip=new float[2];
	coordclip[0]=vert2x;
	coordclip[1]=vert2y;
	xy_clip_a.push_back(coordclip);
	posclip_a=0;
      }
      unsigned int posclip_b=0;
      if(xy_clip_b.size()>0){
	//cout << "iiib" << xy_clip_b.size() << endl;
	float min_b=10000000;

	for(unsigned int c2=0;c2<xy_clip_b.size();c2++){
	  float lung=sqrt(pow(xy_clip_b[c2][0]-strettox,2)+pow(xy_clip_b[c2][1]-strettoy,2));
	  if(min_b>lung){
	    min_b=lung;
	    posclip_b=c2;
	  }
	}
      }else{
	float* coordclip=new float[2];
	coordclip[0]=vert3x;
	coordclip[1]=vert3y;
	xy_clip_b.push_back(coordclip);
	posclip_b=0;
      }

      /*
      cout <<"iix_m" <<  strettox << " " <<strettoy << endl;
      cout << "iiix_b " << vert3x
	   << " " << xy_clip_a[posclip_a][0]
	   << " " << xy_clip_a[posclip_a][1]<< endl;

      cout << "iiix_a " << vert2x
	    << " " << xy_clip_b[posclip_b][0]
	    << " " << xy_clip_b[posclip_b][1]<< endl;
      */


      if(cairo_t_singleton::can_export()){
        
        /****testing cairo*********/
        cairo_t* cn=cairo_t_singleton::get_context();
        cairo_save(cn);
        
        cairo_set_source_rgb(cn,
                             remap_color_1(cr),
                             remap_color_1(cg),
                             remap_color_1(cb));
        

        cairo_move_to(cn,strettox, strettoy);
	cairo_line_to(cn,strettox, strettoy);
	cairo_line_to(cn,xy_clip_a[posclip_a][0], xy_clip_a[posclip_a][1]);
	cairo_line_to(cn,fino.pos_x(), fino.pos_y());
	cairo_line_to(cn,xy_clip_b[posclip_b][0], xy_clip_b[posclip_b][1]);
	cairo_line_to(cn,strettox, strettoy);

        cairo_fill(cn);
        cairo_restore(cn);
        
        /*****************/
        
      }else{
        fl_color(cr,cg,cb);
	fl_begin_complex_polygon(); 
	fl_vertex(xy_clip_a[posclip_a][0]+dx_scroll,xy_clip_a[posclip_a][1]+dy_scroll);
	fl_vertex(fino.pos_x()+dx_scroll,fino.pos_y()+dy_scroll);
	fl_vertex(xy_clip_b[posclip_b][0]+dx_scroll,xy_clip_b[posclip_b][1]+dy_scroll);
	fl_vertex(strettox+dx_scroll,strettoy+dy_scroll);
	fl_end_complex_polygon();
      }

      for(unsigned int ctd=0;ctd<xy_clip_a.size();ctd++){
	delete [] xy_clip_a[ctd];
      }

      for(unsigned int ctd2=0;ctd2<xy_clip_b.size();ctd2++){
	delete [] xy_clip_b[ctd2];
      }
      

      /*
      fl_begin_polygon();
      fl_vertex(strettox+dx_scroll,strettoy+dy_scroll);
      fl_vertex(vert2x+dx_scroll,vert2y+dy_scroll);
      fl_vertex(vert3x+dx_scroll,vert3y+dy_scroll);
      fl_end_polygon();
      */

    }

  }

}


void gruppo::clip_lato_cuneo(float* risul, float xlegstart, float ylegstart,
			float xlegend,float ylegend, float xcunstart, float ycunstart,
			float xcunend, float ycunend){


  float mcun;
  float qcun;
  
  bool riscun=rett_eqn(xcunstart, ycunstart,
		       xcunend, ycunend,
		       mcun, qcun);

  float mleg;
  float qleg;
  
  bool risleg=rett_eqn(xlegstart, ylegstart,
		       xlegend, ylegend,
		       mleg, qleg);
  

  if(riscun){
    if(risleg){
      //cout << "iiiaaaaaaaa " <<  xcunstart << " " << ycunstart << endl; 
      risul[0]=(qcun-qleg)/(mleg-mcun);
      risul[1]=mcun*risul[0]+qcun;

      if(static_cast<int>(rintf(risul[0]))==static_cast<int>(rintf(xcunstart)) && 
	 static_cast<int>(risul[1])==static_cast<int>(ycunstart)){
	//cout << "iiibbbbb " <<  xcunstart << " " << ycunstart << endl; 
	 risul[0]=xcunend;
	 risul[1]=ycunend;
      }

    }else{
      risul[0]=xlegstart;
      risul[1]=mcun*risul[0]+qcun;
    }


    if(static_cast<int>(risul[0])==static_cast<int>(xcunstart) &&
       static_cast<int>(risul[1])==static_cast<int>(ycunstart)){
      risul[0]=xcunend;
      risul[1]=ycunend;
    }




  }else{
    if(risleg){
      risul[0]=xcunstart;
      risul[1]=mleg*risul[0]+qleg;
    }else{

      risul[0]=xcunend;
      risul[1]=ycunend;
    }
    
  }

  float lung_legame=sqrt(pow(xlegend-xlegstart,2)+pow(ylegend-ylegstart,2));
  float lung_clip=sqrt(pow(risul[0]-xlegstart,2)+pow(risul[1]-ylegstart,2));
  
  if(lung_legame<lung_clip){
    risul[0]=xlegend;
    risul[1]=ylegend;
  }

}


int gruppo::aggiungi_procedura(procedura* proc){
  int id_ult=-1;
  if(_procedure.size()>0){
    id_ult=_procedure.back()->id();
  }
  procedura* nuova=0;
  if(typeid(*proc)==typeid(proc_bezier)){
    nuova=new proc_bezier(dynamic_cast<proc_bezier*>(proc));
  }else if(typeid(*proc)==typeid(proc_arrow)){
    nuova=new proc_arrow(dynamic_cast<proc_arrow*>(proc));
  }else if(typeid(*proc)==typeid(proc_arc)){
    nuova=new proc_arc(dynamic_cast<proc_arc*>(proc));
  }else if(typeid(*proc)==typeid(BoxProc)){
    nuova=new BoxProc(dynamic_cast<BoxProc*>(proc));
  }

  nuova->id(id_ult+1);
  nuova->aggiungi_genitore(this);
  _procedure.push_back(nuova);

#ifdef DEBUG
  for(unsigned int i=0;i<_procedure.size();i++){
    std::cerr << "aggiunto_ size " << _procedure.size() 
	      <<  " id proc : " << _procedure[i]->id() 
	      << " id gruppo genitore " << _procedure[i]->id_gruppo() 
	      << " id gruppo (this) " << id()
	      << std::endl;
  }
#endif

  return nuova->id();
}



void gruppo::ruota(float angl,float x_pivot,float y_pivot){
  
 for(unsigned int i=0;i<_atomi.size();i++){
    (_atomi[i]).ruota(x_pivot,y_pivot,angl);

  }
  
 for(unsigned int i2=0;i2<_procedure.size();i2++){
    (_procedure[i2])->ruota(x_pivot,y_pivot,angl);

  }

 /*
  xpivot(x_pivot);
  ypivot(y_pivot);
  angolorot(angl);
 */

}

void gruppo::scale_from_origin(float sc){
 for(unsigned int i=0;i<_atomi.size();i++){
    _atomi[i].scale(sc);
  }

  vector<procedura*>::iterator proc_st=iniz_procedure();
  vector<procedura*>::iterator proc_fin=fin_procedure();
  while(proc_st!=proc_fin){
    (*proc_st)->scale(sc);
    proc_st++;
  }
}


void gruppo::scale(float sc){
  float dx_scale=posx()+w()/2.0;
  float dy_scale=posy()+h()/2.0;
  trasla(-dx_scale,-dy_scale);

 for(unsigned int i=0;i<_atomi.size();i++){
    _atomi[i].scale(sc);
 }

 vector<procedura*>::iterator proc_st=iniz_procedure();
 vector<procedura*>::iterator proc_fin=fin_procedure();
 while(proc_st!=proc_fin){
   (*proc_st)->scale(sc);
   proc_st++;
 }
 
 trasla(dx_scale,dy_scale);

}


void gruppo::trasla(float dx,float dy){
  //trasliamo gli atomi
  for(unsigned int i=0;i<_atomi.size();i++){
    _atomi[i].trasla(dx,dy);
  }


   //trasliamo le procedure
  vector<procedura*>::iterator proc_st=iniz_procedure();
  vector<procedura*>::iterator proc_fin=fin_procedure();
  while(proc_st!=proc_fin){
    (*proc_st)->trasla(dx,dy);
    proc_st++;
  }

}



void gruppo::phys_translate(float dx,float dy){
  //trasliamo gli atomi
  for(unsigned int i=0;i<_atomi.size();i++){
    _atomi[i].phys_translate(dx,dy);
  }


   //trasliamo le procedure
  vector<procedura*>::iterator proc_st=iniz_procedure();
  vector<procedura*>::iterator proc_fin=fin_procedure();
  while(proc_st!=proc_fin){
    (*proc_st)->phys_translate(dx,dy);
    proc_st++;
  }

}




void gruppo::cancel_visitato_all(){
  for(unsigned int i=0;i<_atomi.size();i++){
    _atomi[i].visitato(false);
  }
}

bool gruppo::is_shown() {
  if(cairo_t_singleton::can_export()){
    return true;
  }else{
    std::pair<float,float> ld;
    std::pair<float,float> ru;
    
    get_bounding_box(ld,ru);

    ld.first+=MainWindow->ritorna_mol_canvas()->x();
    ld.second+=MainWindow->ritorna_mol_canvas()->y();
    ru.first+=MainWindow->ritorna_mol_canvas()->x();
    ru.second+=MainWindow->ritorna_mol_canvas()->y();
    
    
    int main_w=MainWindow->ritorna_mol_canvas()->window()->w();
    int main_h=MainWindow->ritorna_mol_canvas()->window()->h()-ALT_BUTT_TOP-HEIGHT_INF_BAR;
    
    if(ld.first < main_w && ru.first > 0 &&
       ld.second < main_h && ru.second > 0){
      return true;
    }else{
      return false;
    }
  }
}

void gruppo::disegna(){

  if(is_shown()){
    //disegna la molecola
    if(_atomi.size()>0){
      depth_search((*iniz_atom()));
    }
    
    for(unsigned int act=0;act<_atomi.size();act++){
      _atomi[act].reset_arrivati();
    }
    
    //resetta i valori di visitato
    
    for(unsigned int i=0;i<_atomi.size();i++){
      _atomi[i].visitato(false);
    }
    
    
    //disegnamo le procedure
    vector<procedura*>::iterator proc_st=iniz_procedure();
    vector<procedura*>::iterator proc_fin=fin_procedure();
    
    while(proc_st!=proc_fin){
      (*proc_st)->disegna();
      proc_st++;
    }
  }
}

void gruppo::ruota(){

  /*
  for (int i=0;i<_atomi.size();i++){
    _atomi[i].ruota(angolorot(),xpivot(),ypivot());
  }
  */

  for(unsigned int i2=0;i2<_procedure.size();i2++){
    (_procedure[i2])->ruota(angolorot(),xpivot(),ypivot());

  }



}

void gruppo::genera_seme(float x1, float y1, float x2, float y2,int tipo) throw (range_error){

  if(_atomi.size()==0){
    
    int dx_scroll=(MainWindow->ritorna_mol_canvas())->x();
    int dy_scroll=(MainWindow->ritorna_mol_canvas())->y();
    
    atomo uno;
    atomo altro;

    uno.id(0);

    uno.pos_x(descale(x1-dx_scroll));
    uno.pos_y(descale(y1-dy_scroll));
    uno.etich_punt()->aggiungi(NO_ETIC, ET_STR);
    uno.aggiungi_genitore(this);
    altro.pos_x(descale(x2-dx_scroll));
    altro.pos_y(descale(y2-dy_scroll));
    altro.etich_punt()->aggiungi(NO_ETIC, ET_STR);
    altro.aggiungi_genitore(this);

    /*
      int	nw_leg_id_atomo,
      int nw_leg_tipo_legame,int nwcr,
      int nwcg , int nwcb)
    */

    add_atomo_id(uno);
    add_atomo_id(altro);
    _atomi[0].aggiungi_legame(_atomi.back().id(),tipo,0,0,0); //uno

    if(tipo==LEGAME_INTERNO || tipo== LEGAME_ESTERNO ||
       tipo==LEGAME_INTERNO_OPP || tipo==LEGAME_ESTERNO_OPP){
      tipo=-tipo;
    }

    _atomi.back().aggiungi_legame(_atomi[0].id(),tipo,0,0,0); //altro
    _atomi[0].costruisci_arrivati();
    _atomi[1].costruisci_arrivati();


  }else{
    throw range_error("genera_seme: il vettore degli atomi ha size()>0");
  }
}


void gruppo::rimappa_da(int nwid){
  for(unsigned int i=0;i<_atomi.size();i++){
    int vecchio_id=_atomi[i].id();
    _atomi[i].id(nwid);
    for(unsigned int rm=0;rm<_atomi.size();rm++){
      vector<legame>::iterator inleg=_atomi[rm].iniz_leg();
      vector<legame>::iterator finleg=_atomi[rm].fin_leg();

      while(inleg!=finleg){
	if((*inleg).id_atomo()==vecchio_id){
	  (*inleg).id_atomo(nwid);
	}
	inleg++;
      }
    }

    nwid++;
  }
}

int gruppo::rimappa_da(int nwid,int id_vec){
  //cout << "RIMAPPA" << endl;


  //cerchiamo il vecchio id e prediciamo in cosa si trasformera'

  int nuovo_id=-1;
  int id_vec_trans=nwid;

  for(unsigned int i=0;i<_atomi.size();i++){
    int vecchio_id=_atomi[i].id();
    if(vecchio_id==id_vec){
      nuovo_id=id_vec_trans;
      break;
    }
    id_vec_trans++;
  }

  //settiamo  tutti  gli  id  al  loro  opposto  per  evitare  conflitti
  //(ovviamente 0 rimane 0)


  for(unsigned int i=0;i<_atomi.size();i++){
    int vecchio_id=_atomi[i].id();
    int oppid=-vecchio_id;

    _atomi[i].id(oppid);

    for(unsigned int rm=0;rm<_atomi.size();rm++){
      vector<legame>::iterator inleg=_atomi[rm].iniz_leg();
      vector<legame>::iterator finleg=_atomi[rm].fin_leg();

      while(inleg!=finleg){
	if((*inleg).id_atomo()==vecchio_id){
	  (*inleg).id_atomo(oppid);
	}
	inleg++;
      }
    }
  }



  // a questo punto rimappiamo partendo da nwid

  for(unsigned int i=0;i<_atomi.size();i++){
    int vecchio_id=_atomi[i].id();

    _atomi[i].id(nwid);


    for(unsigned int rm=0;rm<_atomi.size();rm++){
      vector<legame>::iterator inleg=_atomi[rm].iniz_leg();
      vector<legame>::iterator finleg=_atomi[rm].fin_leg();

      while(inleg!=finleg){
	if((*inleg).id_atomo()==vecchio_id){
	  (*inleg).id_atomo(nwid);
	}
	inleg++;
      }
    }
    //cout << "rimappa " << nwid << endl;
    nwid++;
  }

  return nuovo_id;

}




bool gruppo::substructure_match(gruppo substructure){

  substructure_search::molecule_matching s(*this,substructure);
  bool res =s.match();
  DEBUG_TO_CERR(res);
  return res;

}






atomo* gruppo::check_atom_son_by_bond_type(atomo* parent, int bond_type){
  atomo* result=0;
  vector<legame>::iterator first=parent->primo_leg();
  vector<legame>::iterator last=parent->ultimo_leg();
  while(first!=last){
    atomo* child=find_atomo_id((*first).id_atomo());
    int type_bond_parent=(*first).tipo_legame();
    if(type_bond_parent==bond_type){
      result=child;
      break;
    }	
    first++;
  }
  return result;
}


atomo* gruppo::check_atom_son_by_bond_type(atomo* parent, int bond_type,
					   bool visited_value){
  atomo* result=0;
  vector<legame>::iterator first=parent->primo_leg();
  vector<legame>::iterator last=parent->ultimo_leg();
  while(first!=last){
    atomo* child=find_atomo_id((*first).id_atomo());
    int type_bond_parent=(*first).tipo_legame();
    if(type_bond_parent==bond_type && 
       child->visitato()==visited_value){
      result=child;
      break;
    }	
    first++;
  }
  return result;
}

atomo* gruppo::check_atom_son_by_bond_type(gruppo* group, atomo* parent, int bond_type,
					   bool visited_value){
  atomo* result=0;
  vector<legame>::iterator first=parent->primo_leg();
  vector<legame>::iterator last=parent->ultimo_leg();
  while(first!=last){
    atomo* child=group->find_atomo_id((*first).id_atomo());
    int type_bond_parent=(*first).tipo_legame();
    if(type_bond_parent==bond_type && 
       child->visitato()==visited_value){
      result=child;
      break;
    }	
    first++;
  }
  return result;
}



void gruppo::get_bounding_box(std::pair<float,float>& ld,
                              std::pair<float,float>& ru){

 vector <float> x;
 vector <float> y;
 for(unsigned int i=0;i<_procedure.size();i++){
   
   std::pair<float,float> ldp;
   std::pair<float,float> rup;
   
   _procedure[i]->get_bounding_box(ldp,rup);
   x.push_back(ldp.first);
   x.push_back(rup.first);
   y.push_back(ldp.second);
   y.push_back(rup.second);

 }



 for(unsigned int i=0;i<_atomi.size();i++){
   etichetta lb=_atomi[i].etich();
   if(false && lb.to_raw_string()!=std::string(NO_ETIC)){ //do take into account labels
     int w_lb=0;
     int h_lb=0;
     etichetta lb=_atomi[i].etich();
     allinea_etichetta(lb,_atomi[i]);
     w_lb=lb.w();
     h_lb=lb.h();

     x.push_back(lb.x());
     y.push_back(lb.y());


     x.push_back(lb.x()+w_lb);
     y.push_back(lb.y()+h_lb);

   }else{
     x.push_back(_atomi[i].pos_x());
     y.push_back(_atomi[i].pos_y());
   }

 }
  
 calc_bb_gen(x,y,ld,ru);


}

void gruppo::arrows_points(std::vector<float>& x,
                           std::vector<float>& y){
  
  for(unsigned int i=0;i<_procedure.size();i++){
    _procedure[i]->arrows_points(x,y);
  }

}


void gruppo::get_phys_bounding_box(std::pair<float,float>& ld,
                                   std::pair<float,float>& ru){


  vector <float> x;
  vector <float> y;
  for(unsigned int i=0;i<_procedure.size();i++){
    
    std::pair<float,float> ldp;
    std::pair<float,float> rup;
    
    _procedure[i]->get_phys_bounding_box(ldp,rup);



    x.push_back(ldp.first);
    x.push_back(rup.first);
    y.push_back(ldp.second);
    y.push_back(rup.second);
    
  }
  

  //std::cerr << "_atomi.size() " << _atomi.size() << std::endl; 
  for(unsigned int i=0;i<_atomi.size();i++){
    etichetta lb=_atomi[i].etich();
    if(lb.to_raw_string()!=std::string(NO_ETIC)){
      int w_lb=0;
      int h_lb=0;
      etichetta lb=_atomi[i].etich();
      allinea_etichetta(lb,_atomi[i]);
      w_lb=lb.phys_w();
      h_lb=lb.phys_h();
      
      x.push_back(lb.phys_x());
      y.push_back(lb.phys_y());
      
      
      x.push_back(lb.phys_x()+w_lb);
      y.push_back(lb.phys_y()+h_lb);
      
    }else{
      //std::cerr << "add " << _atomi[i].id() << " " <<_atomi[i].phys_pos_x() << " " << _atomi[i].phys_pos_y() << std::endl;
      x.push_back(_atomi[i].phys_pos_x());
      y.push_back(_atomi[i].phys_pos_y());
    }


    atomo cp=_atomi[i];
    etichetta lab=cp.etich();
    std::ostringstream car;

    if(cp.cariche()>0){
      car <<  cp.cariche() << "+";
    }else if(cp.cariche()<0){
      car <<  cp.cariche() << "-";
    }
    allinea_etichetta(lab,cp);
    std::vector<int> res=calculate_electron_pos_relative(cp);
    for(unsigned int i=0;i<res.size();i++){
      switch(res[i]){
      case 0:
        x.push_back(lab.phys_x() + lab.phys_w()/2 + RAGGIO_EL * 2);
        y.push_back(lab.phys_y());
        break;
      case 1:
        x.push_back(lab.phys_x());
        y.push_back(lab.phys_y() + lab.phys_h() +  RAGGIO_EL);
        break;
      case 2:
        x.push_back(lab.phys_x() - lab.phys_w()/2 - RAGGIO_EL * 2);
        y.push_back(lab.phys_y());

        break;
      case 3:
        x.push_back(lab.phys_x());
        y.push_back(lab.phys_y() - RAGGIO_EL *2);
        break;
      }
    }
    
    if(cp.cariche()!=0){
      float scale_font=SCALE_APICI;
      etichetta label_ch;
      float nwdim=lab.phys_dim()/scale_font;
      label_ch.aggiungi(car.str(), ET_STR);
      label_ch.font(cp.etich().font());
      label_ch.dim(nwdim);
      float h_ch=label_ch.phys_h();
      float w_ch=label_ch.phys_w();

      switch(cp.position_charge()){
      case L_BOTTOM:
        {
          x.push_back(lab.phys_x() - w_ch);
          y.push_back(lab.phys_y() - h_ch);
        }
        break;
      case R_BOTTOM:
        {
          x.push_back(lab.phys_x() + lab.phys_w() + w_ch);
          y.push_back(lab.phys_y() - h_ch);
          
        }
        break;
      case L_TOP:
        {
          x.push_back(lab.phys_x() - lab.phys_w() - w_ch);
          y.push_back(lab.phys_y());

        }
        break;
      case R_TOP:
      default:
        {
          x.push_back(lab.phys_x() + lab.phys_w() + w_ch);
          y.push_back(lab.phys_y());

        }
        
      }
      
    }
  
    
  }
  /*
  for(unsigned int i=0;i<x.size();i++){
    std::cerr << __FUNCTION__ << x[i] << " " << y[i] << std::endl;
  }
  */


  calc_bb_gen(x,y,ld,ru);


}

void gruppo::get_visual_bounding_box(std::pair<float,float>& ld,
                                     std::pair<float,float>& ru){
 vector <float> x;
 vector <float> y;
 for(unsigned int i=0;i<_procedure.size();i++){
   
   std::pair<float,float> ldp;
   std::pair<float,float> rup;
   
   _procedure[i]->get_visual_bounding_box(ldp,rup);
   x.push_back(ld.first);
   x.push_back(ru.first);
   y.push_back(ld.second);
   y.push_back(ru.second);

 }

 for(unsigned int i=0;i<_atomi.size();i++){
   x.push_back(_atomi[i].visual_pos_x());
   y.push_back(_atomi[i].visual_pos_y());
 }
  
 calc_bb_gen(x,y,ld,ru);

}

gruppo link_groups(gruppo* fst, gruppo* snd, std::vector<GruppoLink> links){
  gruppo linked=*fst;
  
  vector<atomo>::iterator beg=snd->iniz_atom();
  vector<atomo>::iterator end=snd->fin_atom();
 
  while(beg!=end){
    (*beg).aggiungi_genitore(&linked);
    (*beg).visitato(false);
    (*beg).costruisci_arrivati();
    (*beg).reset_arrivati();
    linked.add_atomo((*beg),false);
    beg++;
  }
  

  for(unsigned int i=0;i< links.size();i++){
    atomo* f=linked.find_atomo_id(links[i]._first);
    atomo* s=linked.find_atomo_id(links[i]._second);
    f->aggiungi_legame(s->id(),
     		       links[i]._bondtype,
     		       0,0,0);
    f->costruisci_arrivati();
    s->aggiungi_legame(f->id(),
     		       links[i]._bondtype,
     		       0,0,0);
    f->costruisci_arrivati();
  }
  

  return linked;
}
