Computational routine
eng

##
canimxy3d

### File content

    /**
       \file canimxy3d.c
       \author Benoit Bayol
       \version 1.0
       \date September 2006 - January 2007
       \brief CANIMXY3D is a scope in 3D which draw its input as a XY scope, there is animation.
       \see CANIMXY3D.sci in macros/scicos_blocks/Sinks/
    */

    #include "scoMemoryScope.h"
    #include "scoWindowScope.h"
    #include "scoMisc.h"
    #include "scoGetProperty.h"
    #include "scoSetProperty.h"
    #include "scicos_block4.h"

    /** \fn canimxy3d_draw(scicos_block * block, ScopeMemory ** pScopeMemory, int firstdraw)
        \brief Function to draw or redraw the window
    */
    void canimxy3d_draw(scicos_block * block, ScopeMemory ** pScopeMemory, int firstdraw)
    {
      int i; //As usual
      int * ipar; //Integer Parameters
      int color_number; //Flag on Color
      int * color;
      int * line_size;
      int nbr_curves;
      int animed;
      int win; //Windows ID : To give a name to the window
      int buffer_size; //Buffer Size
      int win_pos[2]; //Position of the Window
      int win_dim[2]; //Dimension of the Window
      int nipar;
      double * rpar; //Reals parameters
      double xmin, xmax, ymin, ymax, zmin, zmax,alpha,theta; //Ymin and Ymax are vectors here
      scoGraphicalObject Pinceau; //Pointer to each polyline of each axes
      scoGraphicalObject Gomme; //Pointer to each polyline of each axes
      scoGraphicalObject Trait; //Pointer to each trache of each axes
      int number_of_subwin;
      int number_of_curves_by_subwin;
      int dimension = 3;
      int gomme_color;
      int size=0;

      ipar = GetIparPtrs(block);
      nipar = GetNipar(block);
      rpar = GetRparPtrs(block);
      win = ipar[0];
      color_number = ipar[1];
      buffer_size = ipar[2];
      color = (int*)scicos_malloc(color_number*sizeof(int));
      line_size = (int*)scicos_malloc(color_number*sizeof(int));
      for(i = 0 ; i < color_number ; i++)
        {
          color[i] = ipar[i+3];
          line_size[i] = ipar[i+3+color_number];
        }
      size = 2*color_number;
      animed = ipar[size+3];
      win_pos[0] = ipar[size+4];
      win_pos[1] = ipar[size+5];
      win_dim[0] = ipar[size+6];
      win_dim[1] = ipar[size+7];
      xmin = rpar[0];
      xmax = rpar[1];
      ymin = rpar[2];
      ymax = rpar[3];
      zmin = rpar[4];
      zmax = rpar[5];
      alpha = rpar[6];
      theta = rpar[7];
      number_of_subwin = 1;
      nbr_curves = ipar[size+8];

      /* If only one element to draw*/
      if (buffer_size == 1)
        {
          number_of_curves_by_subwin = nbr_curves;
          if(firstdraw == 1)
    	{
    	  scoInitScopeMemory(block->work,pScopeMemory, number_of_subwin, &number_of_curves_by_subwin);
    	  scoSetShortDrawSize(*pScopeMemory,0,1);
    	  scoSetLongDrawSize(*pScopeMemory,0,0);
    	}

          scoInitOfWindow(*pScopeMemory, dimension, win, win_pos, win_dim, &xmin, &xmax, &ymin, &ymax, &zmin, &zmax);
          if(scoGetScopeActivation(*pScopeMemory) == 1)
    	{
    	  pFIGURE_FEATURE(scoGetPointerScopeWindow(*pScopeMemory))->pixmap = 1;
    	  pFIGURE_FEATURE(scoGetPointerScopeWindow(*pScopeMemory))->wshow = 1;

    	  for(i = 0 ; i < scoGetNumberOfCurvesBySubwin(*pScopeMemory, 0) ; i++)
    	    {
    	      scoAddPolylineForShortDraw(*pScopeMemory,0,i,color[i]);
    	      Pinceau = scoGetPointerShortDraw(*pScopeMemory,0,i);

    	      sciSetMarkSize(Pinceau, line_size[i]);

    	      pPOLYLINE_FEATURE(Pinceau)->n1 = 1;
    	    }
    	}
        }
      /*else if 2 or more elements*/
      else
        {
          number_of_curves_by_subwin = 2*nbr_curves; //it is a trick to recognize the type of scope, not sure it is a good way because normally a curve is the combination of a short and a longdraw
          if(firstdraw == 1)
    	{
    	  scoInitScopeMemory(block->work,pScopeMemory, number_of_subwin, &number_of_curves_by_subwin);
    	}
          scoInitOfWindow(*pScopeMemory, dimension, win, win_pos, win_dim, &xmin, &xmax, &ymin, &ymax, &zmin, &zmax);
          if(scoGetScopeActivation(*pScopeMemory) == 1)
    	{
    	  gomme_color = sciGetBackground(scoGetPointerAxes(*pScopeMemory,0));

              if(firstdraw == 1) {
                scoSetShortDrawSize(*pScopeMemory,0,2);
                scoSetLongDrawSize(*pScopeMemory,0,buffer_size);
              }

              for(i = 0 ; i < nbr_curves ; i++) {
                /*if mark style*/
                if (color[i]<=0) {
                  //because of color[0] is negative it will add a black mark with style number color[0]
                  scoAddPolylineForShortDraw(*pScopeMemory,0,i,color[i]);
                  scoAddPolylineForShortDraw(*pScopeMemory,0,i+nbr_curves,color[i]); //same type of mark and black for the rubber
                  scoAddPolylineForLongDraw(*pScopeMemory,0,i,color[i]);

                  Pinceau = scoGetPointerShortDraw(*pScopeMemory,0,i);
                  Gomme = scoGetPointerShortDraw(*pScopeMemory,0,i+nbr_curves);
                  Trait = scoGetPointerLongDraw(*pScopeMemory,0,i);

                  sciSetMarkSize(Pinceau, line_size[i]);
                  sciSetMarkSize(Gomme, line_size[i]);
                  sciSetMarkSize(Trait, line_size[i]);

                  pPOLYLINE_FEATURE(Pinceau)->n1 = 1;
                  pPOLYLINE_FEATURE(Gomme)->n1 = 1;
                  sciSetMarkForeground(Gomme, gomme_color); //here the rubber becomes colored like the background of the axes
                  pPOLYLINE_FEATURE(Trait)->n1 = buffer_size-1;
                }
                /*if line style*/
                else {
                  scoAddPolylineForShortDraw(*pScopeMemory,0,i,color[i]);
                  scoAddPolylineForShortDraw(*pScopeMemory,0,i+nbr_curves,gomme_color);
                  scoAddPolylineForLongDraw(*pScopeMemory,0,i,color[i]);

                  Pinceau = scoGetPointerShortDraw(*pScopeMemory,0,i);
                  Gomme = scoGetPointerShortDraw(*pScopeMemory,0,i+nbr_curves);
                  Trait = scoGetPointerLongDraw(*pScopeMemory,0,i);

                  sciSetLineWidth(Pinceau, line_size[i]);
                  sciSetLineWidth(Gomme, line_size[i]);
                  sciSetLineWidth(Trait, line_size[i]);

                  pPOLYLINE_FEATURE(Pinceau)->n1 = 2;
                  pPOLYLINE_FEATURE(Gomme)->n1 = 2;
                  pPOLYLINE_FEATURE(Trait)->n1 = buffer_size;
                }
              }

    	}
        }
      if(scoGetScopeActivation(*pScopeMemory) == 1)
        {
          pSUBWIN_FEATURE(scoGetPointerAxes(*pScopeMemory,0))->alpha = alpha;
          pSUBWIN_FEATURE(scoGetPointerAxes(*pScopeMemory,0))->theta = theta;

          scoAddTitlesScope(*pScopeMemory,"x","y","z");
        }
      scicos_free(color);
      scicos_free(line_size);
    }
    /** \fn void canimxy3d(scicos_block * block, int flag)
        \brief the computational function
        \param block A pointer to a scicos_block
        \param flag An integer which indicates the state of the block (init, update, ending)
    */
    void canimxy3d(scicos_block * block, int flag)
    {
      /* Declarations*/
      double *u1,*u2,*u3;
      ScopeMemory * pScopeMemory;
      scoGraphicalObject pShortDraw;
      /* State Machine Control */
      switch(flag)
        {
        case Initialization:
          {

    	canimxy3d_draw(block,&pScopeMemory,1);
    	break; //Break of the switch condition don t forget it
          } //End of Initialization

        case StateUpdate:
          {
    	scoRetrieveScopeMemory(block->work,&pScopeMemory);
    	if(scoGetScopeActivation(pScopeMemory) == 1)
    	  {
    	    /* Charging Elements */
    	if (scoGetPointerScopeWindow(pScopeMemory) == NULL) // If the window has been destroyed we recreate it
    	  {
    	    canimxy3d_draw(block,&pScopeMemory,0);
    	  }

    	/*Retrieve Elements*/
    	u1 = GetRealInPortPtrs(block,1);
    	u2 = GetRealInPortPtrs(block,2);
    	u3 = GetRealInPortPtrs(block,3);

    	scoDrawScopeAnimXYStyle(pScopeMemory,u1,u2,u3);
    	  }
    	break; //Break of the switch don t forget it !
          }//End of stateupdate

          //This case is activated when the simulation is done or when we close scicos
        case Ending:
          {
    	scoRetrieveScopeMemory(block->work, &pScopeMemory);
    	if(scoGetScopeActivation(pScopeMemory) == 1)
    	  {
    	    sciSetUsedWindow(scoGetWindowID(pScopeMemory));
    	    pShortDraw = sciGetCurrentFigure();
    	    pFIGURE_FEATURE(pShortDraw)->user_data = NULL;
    	    pFIGURE_FEATURE(pShortDraw)->size_of_user_data = 0;
    	  }
    	scoFreeScopeMemory(block->work, &pScopeMemory);
    	break; //Break of the switch
          }
          //free the memory which is allocated at each turn by some variables

        }
    }