<commit_before>/*********************************************************************************
* Copyright (c) 2013 David D. Marshall <ddmarsha@calpoly.edu>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*    David D. Marshall - initial code and implementation
********************************************************************************/

#ifndef eli_geom_intersect_minimum_distance_surface_hpp
#define eli_geom_intersect_minimum_distance_surface_hpp

#include <cmath>
#include <vector>
#include <list>

#ifdef Success  // X11 #define collides with Eigen
#undef Success
#endif

#include "Eigen/Eigen"

#include "eli/mutil/nls/newton_raphson_constrained_system_method.hpp"

#include "eli/geom/intersect/minimum_distance_curve.hpp"
#include "eli/geom/point/distance.hpp"

namespace eli
{
  namespace geom
  {
    namespace intersect
    {
      namespace internal
      {
        template <typename surface__>
        struct surface_g_functor
        {
          const surface__ *ps;
          typename surface__::point_type pt;
          typedef typename Eigen::Matrix<typename surface__::data_type, 2, 1> vec;

          vec operator()(const vec &u) const
          {
            typename surface__::data_type uu(u[0]), vv(u[1]);
            vec rtn;

            assert((uu>=0) && (uu<=1));
            assert((vv>=0) && (vv<=1));

            uu=std::min(std::max(uu, static_cast<typename surface__::data_type>(0)), static_cast<typename surface__::data_type>(1));
            vv=std::min(std::max(vv, static_cast<typename surface__::data_type>(0)), static_cast<typename surface__::data_type>(1));

            typename surface__::point_type tmp;

            tmp=ps->f(uu, vv)-pt;
            rtn(0)=tmp.dot(ps->f_u(uu, vv));
            rtn(1)=tmp.dot(ps->f_v(uu, vv));
            return rtn;
          }
        };

        template <typename surface__>
        struct surface_gp_functor
        {
          const surface__ *ps;
          typename surface__::point_type pt;
          typedef typename Eigen::Matrix<typename surface__::data_type, 2, 1> vec;
          typedef typename Eigen::Matrix<typename surface__::data_type, 2, 2> mat;

          mat operator()(const vec &u) const
          {
            typename surface__::data_type uu(u[0]), vv(u[1]);
            mat rtn;

            assert((uu>=0) && (uu<=1));
            assert((vv>=0) && (vv<=1));

            uu=std::min(std::max(uu, static_cast<typename surface__::data_type>(0)), static_cast<typename surface__::data_type>(1));
            vv=std::min(std::max(vv, static_cast<typename surface__::data_type>(0)), static_cast<typename surface__::data_type>(1));

            typename surface__::point_type tmp, Su, Sv, Suu, Suv, Svv;

            tmp=ps->f(uu, vv)-pt;
            Su=ps->f_u(uu, vv);
            Sv=ps->f_v(uu, vv);
            Suu=ps->f_uu(uu, vv);
            Suv=ps->f_uv(uu, vv);
            Svv=ps->f_vv(uu, vv);

            rtn(0,0)=Su.dot(Su)+tmp.dot(Suu);
            rtn(0,1)=Su.dot(Sv)+tmp.dot(Suv);
            rtn(1,0)=rtn(0,1);
            rtn(1,1)=Sv.dot(Sv)+tmp.dot(Svv);

            // TODO: What to do if matrix becomes singular?

            return rtn;
          }
        };
      }

      template<typename surface__>
      typename surface__::data_type minimum_distance(typename surface__::data_type &u, typename surface__::data_type &v, const surface__ &s, const typename surface__::point_type &pt,
                                                     const typename surface__::data_type &u0, const typename surface__::data_type &v0)
      {
        typedef eli::mutil::nls::newton_raphson_constrained_system_method<typename surface__::data_type, 2, 1> nonlinear_solver_type;
        nonlinear_solver_type nrm;
        int stat;
        internal::surface_g_functor<surface__> g;
        internal::surface_gp_functor<surface__> gp;
        typename surface__::data_type dist0, dist;
        typename surface__::tolerance_type tol;

        // setup the functors
        g.ps=&s;
        g.pt=pt;
        gp.ps=&s;
        gp.pt=pt;

        // setup the solver
        nrm.set_absolute_tolerance(tol.get_absolute_tolerance());
        nrm.set_max_iteration(20);
        nrm.set_norm_type(nonlinear_solver_type::max_norm);
        if (s.open_u())
        {
          nrm.set_lower_condition(0, 0, nonlinear_solver_type::NRC_EXCLUSIVE);
          nrm.set_upper_condition(0, 1, nonlinear_solver_type::NRC_EXCLUSIVE);
        }
        else
        {
          nrm.set_periodic_condition(0, 0, 1);
        }
        if (s.open_v())
        {
          nrm.set_lower_condition(1, 0, nonlinear_solver_type::NRC_EXCLUSIVE);
          nrm.set_upper_condition(1, 1, nonlinear_solver_type::NRC_EXCLUSIVE);
        }
        else
        {
          nrm.set_periodic_condition(1, 0, 1);
        }

        // set the initial guess
        typename nonlinear_solver_type::solution_matrix uinit, rhs, ans;

        uinit(0)=u0;
        uinit(1)=v0;
        nrm.set_initial_guess(uinit);
        rhs.setZero();
        dist0=eli::geom::point::distance(s.f(u0, v0), pt);

        // find the root
        stat = nrm.find_root(ans, g, gp, rhs);
        u=ans(0);
        v=ans(1);

        // if found root and it is within bounds and is closer than initial guess
        if (stat==nonlinear_solver_type::converged)
        {
          assert((u>=0) && (u<=1));
          assert((v>=0) && (v<=1));

          dist = eli::geom::point::distance(s.f(u, v), pt);
          if  (dist<=dist0)
          {
            return dist;
          }
        }
//         else
//         {
//             std::cout << "% not converged";
//             if (stat==nonlinear_solver_type::hit_constraint)
//               std::cout << " because hit constraint" << std::endl;
//             else if (stat==nonlinear_solver_type::max_iteration)
//               std::cout << " reached max iteration" << std::endl;
//             else
//               std::cout << " for out of range parameters (" << ans(0) << ", " << ans(1) << ")" << std::endl;
//         }

        // couldn't find better answer so return initial guess
        u=u0;
        v=v0;
        return dist0;
      }

      namespace internal
      {
        template<typename data__>
        struct surface_point_uv_pairs
        {
          data__ u, v, dist;
        };
      }

      template<typename surface__>
      typename surface__::data_type minimum_distance(typename surface__::data_type &u, typename surface__::data_type &v, const surface__ &s, const typename surface__::point_type &pt)
      {
        typename surface__::tolerance_type tol;
        std::list<internal::surface_point_uv_pairs<typename surface__::data_type>> uvinit;
        typename std::list<internal::surface_point_uv_pairs<typename surface__::data_type>>::iterator it;
        internal::surface_point_uv_pairs<typename surface__::data_type> cand_match;

        // possible that end points are closest, so start by checking them
        typename surface__::data_type dist, uu, vv, dd;

        // first check start and (if needed) end points of edges and middle of surface
        {
          bool openu=s.open_u(), openv=s.open_v();
          u=0;
          v=0;
          dist=eli::geom::point::distance(s.f(u, v), pt);
          uu=0.5;
          vv=0.5;
          dd=eli::geom::point::distance(s.f(uu, vv), pt);
          if (dd<dist)
          {
            u=uu;
            v=vv;
            dist=dd;
          }
          if (openu)
          {
            uu=1;
            vv=0;
            dd=eli::geom::point::distance(s.f(uu, vv), pt);
            if (dd<dist)
            {
              u=uu;
              v=vv;
              dist=dd;
            }
            if (openv)
            {
              uu=1;
              vv=1;
              dd=eli::geom::point::distance(s.f(uu, vv), pt);
              if (dd<dist)
              {
                u=uu;
                v=vv;
                dist=dd;
              }
            }
          }
          if (s.open_v())
          {
            uu=1;
            vv=0;
            dd=eli::geom::point::distance(s.f(uu, vv), pt);
            if (dd<dist)
            {
              u=uu;
              v=vv;
              dist=dd;
            }
          }

          // check center point
          uu=0.5;
          vv=0.5;
          dd=eli::geom::point::distance(s.f(uu, vv), pt);
          if (dd<dist)
          {
            u=uu;
            v=vv;
            dist=dd;
          }
        }

        // take best match so far and add it to cases
        cand_match.u=u;
        cand_match.v=v;
        cand_match.dist=dist;
        uvinit.push_back(cand_match);

        // next first check center and edges
        {
          typename surface__::boundary_curve_type bc;

          // check u-min edge
          u=0;
          s.get_uconst_curve(bc, u);
          dist=eli::geom::intersect::minimum_distance(v, bc, pt);

          // if open in u-direction check u-max edge
          if (s.open_u())
          {
            uu=1;
            s.get_uconst_curve(bc, uu);
            dd=eli::geom::intersect::minimum_distance(vv, bc, pt);
            if (dd<dist)
            {
              u=uu;
              v=vv;
              dist=dd;
            }

            // check v-min edge
            vv=0;
            s.get_vconst_curve(bc, vv);
            dd=eli::geom::intersect::minimum_distance(uu, bc, pt);
            if (dd<dist)
            {
              u=uu;
              v=vv;
              dist=dd;
            }

            // if open in v-direction check v-max edge
            if (s.open_v())
            {
              vv=1;
              s.get_vconst_curve(bc, vv);
              dd=eli::geom::intersect::minimum_distance(uu, bc, pt);
              if (dd<dist)
              {
                u=uu;
                v=vv;
                dist=dd;
              }
            }
          }
        }

        // take best match so far and add it to cases
        cand_match.u=u;
        cand_match.v=v;
        cand_match.dist=dist;
        uvinit.push_back(cand_match);

        // need to pick initial guesses
        typename surface__::index_type i, j, degu(s.degree_u()), degv(s.degree_v()), susize, svsize;
        std::vector<typename surface__::data_type> usample(1*degu+1), vsample(1*degv+1);
        typename surface__::point_type p0, p1;
        typename surface__::data_type temp;

        // determine the sample parameters from the control polygon points
// TODO: need to calculate distance between control points for better distribution of samples
#if 0
        ssize=tsample.size();
        i=0;
        p1=c.get_control_point(i);
        tsample[i]=0;
        for (++i; i<=degu; ++i)
        {
          p0=p1;
          p1=c.get_control_point(i);
          temp=eli::geom::point::distance(p0, p1)/2;
          tsample[2*i-1]=tsample[2*i-2]+temp;
          tsample[2*i]=tsample[2*i-1]+temp;
        }
        tlen=tsample[tsample.size()-1];
#else
          susize=usample.size();
          svsize=vsample.size();
          for (i=0; i<susize; ++i)
          {
            usample[i]=static_cast<typename surface__::data_type>(i)/(susize-1);
          }
          for (j=0; j<svsize; ++j)
          {
            vsample[j]=static_cast<typename surface__::data_type>(j)/(svsize-1);
          }
#endif

        // add points that are minimums
        {
          // find candidate starting locations using distance between sampled points on curve and point
          for (i=0; i<susize; ++i)
          {
            for (j=0; j<svsize; ++j)
            {
              temp=eli::geom::point::distance(s.f(usample[i], vsample[j]), pt);
//             std::cout << "% point #=" << i << ", " << j << "\tdist_temp=" << temp << std::endl;
              if (temp<=1.01*dist)
              {
                cand_match.u=usample[i];
                cand_match.v=vsample[j];
                cand_match.dist=temp;
                uvinit.push_back(cand_match);
                if (temp<dist)
                {
                  u=cand_match.u;
                  v=cand_match.v;
                  dist=cand_match.dist;
                  it=uvinit.begin();
                  while (it!=uvinit.end())
                  {
                    // check to see if distance is beyond new threshold and remove if so
                    if (it->dist>1.01*dist)
                    {
                      it=uvinit.erase(it);
                    }
                    else
                    {
                      ++it;
                    }
                  }
                }
//               std::cout << "% added point #=" << i << ", "<< j << "\tat (" << cand_match.u << ", " << cand_match.v << ")" << std::endl;
              }
            }
          }
        }

//         std::cout << "% t guesses=" << uvinit.size() << std::endl;

        // cycle through all possible minima to find best
        for (it=uvinit.begin(); it!=uvinit.end(); ++it)
        {
          dd=minimum_distance(uu, vv, s, pt, it->u, it->v);
//           std::cout << "% completed root starting at (" << it->u << ", " << it->v << ") and ending at (" << uu << ", " << vv << ") with distance=" << dd << std::endl;

          // if have valid solution
          if ((uu>=0) && (uu<=1) && (vv>=0) && (vv<=1))
          {
            dd=eli::geom::point::distance(s.f(uu, vv), pt);

//               std::cout << "# dd=" << dd << std::endl;
            // check to see if is closer than previous minimum
            if (dd<dist)
            {
              u=uu;
              v=vv;
              dist=dd;
            }
          }
        }

//         std::cout << "# returning dist=" << dist << std::endl;
        return dist;
      }
    }
  }
}
#endif
<commit_msg>Don't be so picky about improved answers in surface minimum distance.<commit_after>/*********************************************************************************
* Copyright (c) 2013 David D. Marshall <ddmarsha@calpoly.edu>
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
*    David D. Marshall - initial code and implementation
********************************************************************************/

#ifndef eli_geom_intersect_minimum_distance_surface_hpp
#define eli_geom_intersect_minimum_distance_surface_hpp

#include <cmath>
#include <vector>
#include <list>

#ifdef Success  // X11 #define collides with Eigen
#undef Success
#endif

#include "Eigen/Eigen"

#include "eli/mutil/nls/newton_raphson_constrained_system_method.hpp"

#include "eli/geom/intersect/minimum_distance_curve.hpp"
#include "eli/geom/point/distance.hpp"

namespace eli
{
  namespace geom
  {
    namespace intersect
    {
      namespace internal
      {
        template <typename surface__>
        struct surface_g_functor
        {
          const surface__ *ps;
          typename surface__::point_type pt;
          typedef typename Eigen::Matrix<typename surface__::data_type, 2, 1> vec;

          vec operator()(const vec &u) const
          {
            typename surface__::data_type uu(u[0]), vv(u[1]);
            vec rtn;

            assert((uu>=0) && (uu<=1));
            assert((vv>=0) && (vv<=1));

            uu=std::min(std::max(uu, static_cast<typename surface__::data_type>(0)), static_cast<typename surface__::data_type>(1));
            vv=std::min(std::max(vv, static_cast<typename surface__::data_type>(0)), static_cast<typename surface__::data_type>(1));

            typename surface__::point_type tmp;

            tmp=ps->f(uu, vv)-pt;
            rtn(0)=tmp.dot(ps->f_u(uu, vv));
            rtn(1)=tmp.dot(ps->f_v(uu, vv));
            return rtn;
          }
        };

        template <typename surface__>
        struct surface_gp_functor
        {
          const surface__ *ps;
          typename surface__::point_type pt;
          typedef typename Eigen::Matrix<typename surface__::data_type, 2, 1> vec;
          typedef typename Eigen::Matrix<typename surface__::data_type, 2, 2> mat;

          mat operator()(const vec &u) const
          {
            typename surface__::data_type uu(u[0]), vv(u[1]);
            mat rtn;

            assert((uu>=0) && (uu<=1));
            assert((vv>=0) && (vv<=1));

            uu=std::min(std::max(uu, static_cast<typename surface__::data_type>(0)), static_cast<typename surface__::data_type>(1));
            vv=std::min(std::max(vv, static_cast<typename surface__::data_type>(0)), static_cast<typename surface__::data_type>(1));

            typename surface__::point_type tmp, Su, Sv, Suu, Suv, Svv;

            tmp=ps->f(uu, vv)-pt;
            Su=ps->f_u(uu, vv);
            Sv=ps->f_v(uu, vv);
            Suu=ps->f_uu(uu, vv);
            Suv=ps->f_uv(uu, vv);
            Svv=ps->f_vv(uu, vv);

            rtn(0,0)=Su.dot(Su)+tmp.dot(Suu);
            rtn(0,1)=Su.dot(Sv)+tmp.dot(Suv);
            rtn(1,0)=rtn(0,1);
            rtn(1,1)=Sv.dot(Sv)+tmp.dot(Svv);

            // TODO: What to do if matrix becomes singular?

            return rtn;
          }
        };
      }

      template<typename surface__>
      typename surface__::data_type minimum_distance(typename surface__::data_type &u, typename surface__::data_type &v, const surface__ &s, const typename surface__::point_type &pt,
                                                     const typename surface__::data_type &u0, const typename surface__::data_type &v0)
      {
        typedef eli::mutil::nls::newton_raphson_constrained_system_method<typename surface__::data_type, 2, 1> nonlinear_solver_type;
        nonlinear_solver_type nrm;
        int stat;
        internal::surface_g_functor<surface__> g;
        internal::surface_gp_functor<surface__> gp;
        typename surface__::data_type dist0, dist;
        typename surface__::tolerance_type tol;

        // setup the functors
        g.ps=&s;
        g.pt=pt;
        gp.ps=&s;
        gp.pt=pt;

        // setup the solver
        nrm.set_absolute_tolerance(tol.get_absolute_tolerance());
        nrm.set_max_iteration(20);
        nrm.set_norm_type(nonlinear_solver_type::max_norm);
        if (s.open_u())
        {
          nrm.set_lower_condition(0, 0, nonlinear_solver_type::NRC_EXCLUSIVE);
          nrm.set_upper_condition(0, 1, nonlinear_solver_type::NRC_EXCLUSIVE);
        }
        else
        {
          nrm.set_periodic_condition(0, 0, 1);
        }
        if (s.open_v())
        {
          nrm.set_lower_condition(1, 0, nonlinear_solver_type::NRC_EXCLUSIVE);
          nrm.set_upper_condition(1, 1, nonlinear_solver_type::NRC_EXCLUSIVE);
        }
        else
        {
          nrm.set_periodic_condition(1, 0, 1);
        }

        // set the initial guess
        typename nonlinear_solver_type::solution_matrix uinit, rhs, ans;

        uinit(0)=u0;
        uinit(1)=v0;
        nrm.set_initial_guess(uinit);
        rhs.setZero();
        dist0=eli::geom::point::distance(s.f(u0, v0), pt);

        // find the root
        stat = nrm.find_root(ans, g, gp, rhs);
        u=ans(0);
        v=ans(1);

        // if root is within bounds and is closer than initial guess
        {
          assert((u>=0) && (u<=1));
          assert((v>=0) && (v<=1));

          dist = eli::geom::point::distance(s.f(u, v), pt);
          if  (dist<=dist0)
          {
            return dist;
          }
        }
//         else
//         {
//             std::cout << "% not converged";
//             if (stat==nonlinear_solver_type::hit_constraint)
//               std::cout << " because hit constraint" << std::endl;
//             else if (stat==nonlinear_solver_type::max_iteration)
//               std::cout << " reached max iteration" << std::endl;
//             else
//               std::cout << " for out of range parameters (" << ans(0) << ", " << ans(1) << ")" << std::endl;
//         }

        // couldn't find better answer so return initial guess
        u=u0;
        v=v0;
        return dist0;
      }

      namespace internal
      {
        template<typename data__>
        struct surface_point_uv_pairs
        {
          data__ u, v, dist;
        };
      }

      template<typename surface__>
      typename surface__::data_type minimum_distance(typename surface__::data_type &u, typename surface__::data_type &v, const surface__ &s, const typename surface__::point_type &pt)
      {
        typename surface__::tolerance_type tol;
        std::list<internal::surface_point_uv_pairs<typename surface__::data_type>> uvinit;
        typename std::list<internal::surface_point_uv_pairs<typename surface__::data_type>>::iterator it;
        internal::surface_point_uv_pairs<typename surface__::data_type> cand_match;

        // possible that end points are closest, so start by checking them
        typename surface__::data_type dist, uu, vv, dd;

        // first check start and (if needed) end points of edges and middle of surface
        {
          bool openu=s.open_u(), openv=s.open_v();
          u=0;
          v=0;
          dist=eli::geom::point::distance(s.f(u, v), pt);
          uu=0.5;
          vv=0.5;
          dd=eli::geom::point::distance(s.f(uu, vv), pt);
          if (dd<dist)
          {
            u=uu;
            v=vv;
            dist=dd;
          }
          if (openu)
          {
            uu=1;
            vv=0;
            dd=eli::geom::point::distance(s.f(uu, vv), pt);
            if (dd<dist)
            {
              u=uu;
              v=vv;
              dist=dd;
            }
            if (openv)
            {
              uu=1;
              vv=1;
              dd=eli::geom::point::distance(s.f(uu, vv), pt);
              if (dd<dist)
              {
                u=uu;
                v=vv;
                dist=dd;
              }
            }
          }
          if (s.open_v())
          {
            uu=1;
            vv=0;
            dd=eli::geom::point::distance(s.f(uu, vv), pt);
            if (dd<dist)
            {
              u=uu;
              v=vv;
              dist=dd;
            }
          }

          // check center point
          uu=0.5;
          vv=0.5;
          dd=eli::geom::point::distance(s.f(uu, vv), pt);
          if (dd<dist)
          {
            u=uu;
            v=vv;
            dist=dd;
          }
        }

        // take best match so far and add it to cases
        cand_match.u=u;
        cand_match.v=v;
        cand_match.dist=dist;
        uvinit.push_back(cand_match);

        // next first check center and edges
        {
          typename surface__::boundary_curve_type bc;

          // check u-min edge
          u=0;
          s.get_uconst_curve(bc, u);
          dist=eli::geom::intersect::minimum_distance(v, bc, pt);

          // if open in u-direction check u-max edge
          if (s.open_u())
          {
            uu=1;
            s.get_uconst_curve(bc, uu);
            dd=eli::geom::intersect::minimum_distance(vv, bc, pt);
            if (dd<dist)
            {
              u=uu;
              v=vv;
              dist=dd;
            }

            // check v-min edge
            vv=0;
            s.get_vconst_curve(bc, vv);
            dd=eli::geom::intersect::minimum_distance(uu, bc, pt);
            if (dd<dist)
            {
              u=uu;
              v=vv;
              dist=dd;
            }

            // if open in v-direction check v-max edge
            if (s.open_v())
            {
              vv=1;
              s.get_vconst_curve(bc, vv);
              dd=eli::geom::intersect::minimum_distance(uu, bc, pt);
              if (dd<dist)
              {
                u=uu;
                v=vv;
                dist=dd;
              }
            }
          }
        }

        // take best match so far and add it to cases
        cand_match.u=u;
        cand_match.v=v;
        cand_match.dist=dist;
        uvinit.push_back(cand_match);

        // need to pick initial guesses
        typename surface__::index_type i, j, degu(s.degree_u()), degv(s.degree_v()), susize, svsize;
        std::vector<typename surface__::data_type> usample(1*degu+1), vsample(1*degv+1);
        typename surface__::point_type p0, p1;
        typename surface__::data_type temp;

        // determine the sample parameters from the control polygon points
// TODO: need to calculate distance between control points for better distribution of samples
#if 0
        ssize=tsample.size();
        i=0;
        p1=c.get_control_point(i);
        tsample[i]=0;
        for (++i; i<=degu; ++i)
        {
          p0=p1;
          p1=c.get_control_point(i);
          temp=eli::geom::point::distance(p0, p1)/2;
          tsample[2*i-1]=tsample[2*i-2]+temp;
          tsample[2*i]=tsample[2*i-1]+temp;
        }
        tlen=tsample[tsample.size()-1];
#else
          susize=usample.size();
          svsize=vsample.size();
          for (i=0; i<susize; ++i)
          {
            usample[i]=static_cast<typename surface__::data_type>(i)/(susize-1);
          }
          for (j=0; j<svsize; ++j)
          {
            vsample[j]=static_cast<typename surface__::data_type>(j)/(svsize-1);
          }
#endif

        // add points that are minimums
        {
          // find candidate starting locations using distance between sampled points on curve and point
          for (i=0; i<susize; ++i)
          {
            for (j=0; j<svsize; ++j)
            {
              temp=eli::geom::point::distance(s.f(usample[i], vsample[j]), pt);
//             std::cout << "% point #=" << i << ", " << j << "\tdist_temp=" << temp << std::endl;
              if (temp<=1.01*dist)
              {
                cand_match.u=usample[i];
                cand_match.v=vsample[j];
                cand_match.dist=temp;
                uvinit.push_back(cand_match);
                if (temp<dist)
                {
                  u=cand_match.u;
                  v=cand_match.v;
                  dist=cand_match.dist;
                  it=uvinit.begin();
                  while (it!=uvinit.end())
                  {
                    // check to see if distance is beyond new threshold and remove if so
                    if (it->dist>1.01*dist)
                    {
                      it=uvinit.erase(it);
                    }
                    else
                    {
                      ++it;
                    }
                  }
                }
//               std::cout << "% added point #=" << i << ", "<< j << "\tat (" << cand_match.u << ", " << cand_match.v << ")" << std::endl;
              }
            }
          }
        }

//         std::cout << "% t guesses=" << uvinit.size() << std::endl;

        // cycle through all possible minima to find best
        for (it=uvinit.begin(); it!=uvinit.end(); ++it)
        {
          dd=minimum_distance(uu, vv, s, pt, it->u, it->v);
//           std::cout << "% completed root starting at (" << it->u << ", " << it->v << ") and ending at (" << uu << ", " << vv << ") with distance=" << dd << std::endl;

          // if have valid solution
          if ((uu>=0) && (uu<=1) && (vv>=0) && (vv<=1))
          {
            dd=eli::geom::point::distance(s.f(uu, vv), pt);

//               std::cout << "# dd=" << dd << std::endl;
            // check to see if is closer than previous minimum
            if (dd<dist)
            {
              u=uu;
              v=vv;
              dist=dd;
            }
          }
        }

//         std::cout << "# returning dist=" << dist << std::endl;
        return dist;
      }
    }
  }
}
#endif
<|endoftext|>


<commit_before>#include <iostream>
#include <stdio.h>
#include <string.h>
#include <fstream>
#include <math.h>
#include <mpi.h>
using namespace std;

int Rank(int, int, int*);
void mergesort(int*, int*, int, int, int, int, int);
void pmerge(int*, int*, int*, int, int, int);
int log2(int);

int main (int argc, char * argv[]) {
  int my_rank;        // my CPU number for this process
  int p;              // number of CPUs that we have
  int source;         // rank of the sender
  int dest;           // rank of destination
  int tag = 0;        // message number
  MPI_Status status;  // return status for receive

  // Start MPI
  MPI_Init(&argc, &argv);

  // Find out my rank!
  MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

  // Find out the number of processes!
  MPI_Comm_size(MPI_COMM_WORLD, &p);

  /* PROGRAM STARTS HERE */
  ifstream in;                        // if stream to start pulling in file
  in.open("mergepara.txt");

  int n;                              // problem size
  in  >> n;
  // read first line for length of letters in the list of random letters
  int * a = new int [n];
  int * b = new int[n];               // creates an array that will hold all the random letters

  if (my_rank == 0) {                 // if you are process 0 then go down the list in the file and add them to the array.
    for (int x = 0; x < n; x++) {
       in >> a[x] ;
     b[x]= 0;

     cout << "a[" << x << "]: " << a[x] << ", b[" << x << "]: " << b[x] << endl;
    }

    // bcast the entire array A to all processors
    MPI_Bcast(&a[0], n, MPI_INT, 0, MPI_COMM_WORLD);
  }

  if (my_rank == 1) {
    for (int x = 0; x < n; x++) {cout << "a[" << x << "]: " << a[x] << endl;}
  }

  mergesort(&a[0], &b[0], 0, n - 1, n, my_rank, p);

  in.close();
  MPI_Finalize();
}

// sequential mergesort call
void mergesort(int * input, int * output, int first, int last, int size, int my_rank, int p) {
  int mid;
  int * rankArray = new int[size];
  for(int x = 0; x < size; x++){
    rankArray[x] = 0;
  }

  if (first < last) {
    mid = first + ((last - first) / 2);
    mergesort(&input[0], &rankArray[0], first, mid, size, my_rank, p);
    mergesort(&input[size / 2], &rankArray[size / 2], mid + 1 , last, size, my_rank, p);
    pmerge(&rankArray[0], &rankArray[size / 2], &output[0], size, my_rank, p);
  } return;
}

void pmerge(int * L , int * R , int * sortedArray, int n, int my_rank, int p) {
  //cout << "This is totally working...?" << endl;
  int logOfHalf = log2(n / 2);
  int sub_size= ceil((n / 2) / (logOfHalf));
  int local_start = my_rank;    // striping

  int * srankA= new int[n / 2];
  int * srankB= new int[n / 2];
  int * totalsrankA = new int[n / 2];
  int * totalsrankB = new int[n / 2];

  for (int i = 0; i < n / 2; i++) {
    srankA[i] = 0;
    srankB[i] = 0;
    totalsrankA[i] = 0;
    totalsrankB[i] = 0;
  }

  int counter = local_start; int posA; int posB;
  for (int x = local_start; x < sub_size; x += p) {
    counter = counter + x * logOfHalf;

    // srankA: Find position of R to search for its Rank within L
    posA = x * logOfHalf;
    srankA[x] = Rank(R[posA], n / 2, L);      // R[x] in L and R[x] in R

    // srankB: Find position of L to search for its Rank within R
    posB = x * logOfHalf;
    srankB[x] = Rank(L[posB], n / 2, R);      // L[x] in R and R[x] in L
  }

  /* //if (my_rank=0) {
    cout << endl;
    for(int x = 0; x < n/2; x++) {
      cout << "my_rank: " << my_rank << ", srankA["<<x<<"]: " << srankA[x] << endl;
    }
  //} */

  MPI_Allreduce(&srankA, &totalsrankA, n/2, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
  MPI_Allreduce(&srankB, &totalsrankB, n/2, MPI_INT, MPI_SUM, MPI_COMM_WORLD);

  // print srank arrays after reduction
  if (my_rank == 0) {
    cout << "this is the right array" << endl;
    for (int x = 0; x < sub_size; x++) {
      //cout << R[x] <<" Rank ";
      cout << totalsrankA[x] << endl;
    }
    cout << endl;
    cout << "this is the left array" << endl;
    for (int x = 0; x < sub_size; x++) {
      //cout << L[x*logOfHalf] <<" Rank ";
      cout << totalsrankB[x] << endl;
    }
  }
}

// returns log base 2 of x
int log2(int x) {
  return ( log(x) / log(2) );
}

// recursive Rank function (binary search)
// returns the rank for any given index on an array
int Rank(int searchItem, int size, int * array) {
  // base case
  if (size == 1){
    // checks midpoint, returns either 0 or 1 if in 1st or 2nd half
    if (searchItem < array[0]) { return 0; }
    else { return 1; }

  } else {
    // we must go deeper!
    if (searchItem < array[size / 2]) {
      return Rank(searchItem, (size / 2), array);

    // we're just about finished...
    } else {
      return size / 2 + Rank(searchItem, (size / 2), &array[size / 2]);
    }
  }
}

// recursive merge function
void merge(int * a, int first, int last, int mid) {
  int i, j, k, c[50];
  i = first;
  k = first;
  j = mid + 1;
  while (i <= mid && j <= last) {
    if (a[i] < a[j]) {
      c[k] = a[i];
      k++; i++;
    } else {
      c[k] = a[j];
      k++; j++;
    }
  }

  while (i <= mid) {
    c[k] = a[i];
    k++; i++;
  }

  while (j <= last) {
    c[k] = a[j];
    k++; j++;
  }

  for (i = first; i < k; i++) {
    a[i] = c[i];
  }
}
<commit_msg>Update Mergesortpara.cpp<commit_after>#include <iostream>
#include <stdio.h>
#include <string.h>
#include <fstream>
#include <math.h>
#include <mpi.h>
using namespace std;

void mergesort(int *, int , int );
void merge(int *, int , int , int );
int Rank(int, int , int *);
int log2(int);
void pmerge(int *,int*, int , int , int,int,int,int );

int main (int argc, char * argv[]) {

  int my_rank;        // my CPU number for this process
  int p;              // number of CPUs that we have
  int source;         // rank of the sender
  int dest;           // rank of destination
  int tag = 0;        // message number
  MPI_Status status;  // return status for receive

  // Start MPI
  MPI_Init(&argc, &argv);

  // Find out my rank!
  MPI_Comm_rank(MPI_COMM_WORLD, &my_rank);

  // Find out the number of processes!
  MPI_Comm_size(MPI_COMM_WORLD, &p);

  /* PROGRAM STARTS HERE */

  ifstream in;                        // if stream to start pulling in file
  in.open("mergepara.txt");

  int n;                              // problem size
  in  >> n;                                             // read first line for l                                                                                ength of letters in the list of random letters

  int * a = new int [n];                        // creates an array that will ho                                                                                ld all the random letters

    if (my_rank == 0) {                 // if you are process 0 then go down the l                                                                                ist in the file and add them to the array.
        for (int x = 0; x < n; x++) {
            in >> a[x] ;
        }

        /* if (my_rank == 0) {
                cout << " This is processor 0 array A"<<endl;     // Uncomment if need                                                                                to test array is in A
                for (int x=0; x<n; x++) {
                        cout << a[x]<< endl;
                    }
            cout<<endl;
        } */
    }

    // bcast the entire array A to all processors
    MPI_Bcast(&a[0], n, MPI_INT, 0, MPI_COMM_WORLD);

  /* if (my_rank == 1) {
          cout<< endl;
          cout << " This is processor 1 array A"<<endl;                 // Uncom                                                                                ment if needed to test bcast
          for (int x=0; x<n; x++) {
                  cout << a[x] << endl;
                }
  }
  */

    int *L;
    int *R;
    L = new int[32];
    R= new int [32];

    L = &a[0];
    R= &a[32];

    mergesort(L, 0, (n/2)-1);   // works  will look at later ***************                                                                                *********************************************
    mergesort(R, 0, (n/2)-1);  // These 2 sort the array for us thats all I                                                                                wanted out of them
    pmerge(L,R,0,n-1,n/2,n,my_rank,p);

    //mergesort(&a[0],0,n-1);   // does not work segmetation fault
    /*
        if (my_rank == 0){

        cout<< "This is the sorted array"<<endl;         // Use to test if L and                                                                                R went though
                for (int x=0; x<n/2; x++) {
                        cout << L[x] << endl;
                }
    } */

  in.close();
  MPI_Finalize();
}

void pmerge(int * L,int * R, int first, int last, int mid,int size,int my_rank,int p){
    int logOfHalf = log2(size/2);
    int local_start= my_rank;
    int partition = ceil((double(size/2)/(logOfHalf)));

    int *srankA= new int[partition];
    int *srankB= new int[partition];
    int *totalsrankA= new int[partition];
    int *totalsrankB= new int[partition];

    //cout<< " This is the value of partition"<< partition << endl;      //                                                                                uncomment if need to test partiton value

    for (int i =0;i < partition;i++){

            srankA[i]= 0;
            srankB[i]= 0;
            totalsrankA[i]=0;
            totalsrankB[i]=0;

    }

    /*
    if(my_rank==0){
    cout<< "this is srankA"<<endl;
            for (int i =0;i<partition;i++){

            cout<< srankA[i]<<endl;
            }
    } */

    for (int x = local_start; x < partition; x+=p) {
            srankA[x] = Rank(R[x*logOfHalf], size/2, L);
            srankB[x] =     Rank(L[x*logOfHalf], size/2, R);

    }

    /* if (my_rank == 3) {
    cout << "this is the processor 3's array A" << endl;            // Uncom                                                                                ment to see what values should be in each processor
            for (int x = 0; x < partition; x++) {
            cout << srankA[x] << endl;

            }

    } */

    MPI_Allreduce(srankA, totalsrankA, partition, MPI_INT, MPI_SUM, MPI_COMM_WORLD);
    MPI_Allreduce(srankB, totalsrankB, partition, MPI_INT, MPI_SUM, MPI_COMM_WORLD);

    if (my_rank == 0) {
        cout << "This is the ending array A" << endl;
        for (int x = 0; x < partition; x++) {
            cout << totalsrankA[x] <<" "<< x<< endl;

        }

    }

    if (my_rank == 0) {
        cout << "This is the ending array B" << endl;
        for (int x = 0; x < partition; x++) {
            cout << totalsrankB[x] <<" "<< x << endl;
        }
    }
    cout<<endl;
    int * endpointA = new int[2*partition];
    int * endpointB = new int[2*partition];

    for (int x = 0; x < partition; x++) {
        endpointA[x] = totalsrankB[x] * logOfHalf;
        endpointB[x] = totalsrankA[x] * logOfHalf;
    }

    for (int x = 0; x < partition; x++) {
        endpointA[partition + x] = totalsrankA[x];
        endpointB[partition + x] = totalsrankB[x];
    }

    sort(endpointA, endpointA + 2 * partition);
    sort(endpointB, endpointB + 2 * partition);

    for (int x = 0; x < 2* partition; x++) {
        cout << "end A[" << x << "]: " << endpointA[x] << ", end B[" << x << "]: " << endpointB[x] << endl;
    }
}

// returns log base 2 of x
int log2(int x) {
   return (log(x) / log(2) );
}

void mergesort(int * a, int first, int last)
{

    int mid;
    if (first < last)
    {
        mid= first+((last-first)/2);
        mergesort(a,first,mid);
        mergesort(a,mid+1,last);
        merge(a,first,last,mid);
    }
    return;

}
void merge(int * a, int first, int last, int mid)
{
    int i, j, k, c[50];
    i = first;
    k = first;
    j = mid + 1;
    while (i <= mid && j <= last)
    {
        if (a[i] < a[j])
        {
            c[k] = a[i];
            k++;
            i++;
        }
        else
        {
            c[k] = a[j];
            k++;
            j++;
        }
    }
    while (i <= mid)
    {
        c[k] = a[i];
        k++;
        i++;
    }
    while (j <= last)
    {
        c[k] = a[j];
        k++;
        j++;
    }
    for (i = first; i < k; i++)
    {
        a[i] = c[i];
    }
}

int Rank(int value, int size, int * array)
{

    if(size == 1){
            if(value < array[0]){

                    return 0;
            }
            else{
                    return 1;
            }

    }
    else{
        if(value < array[size/2]){
                return Rank(value,size/2,array) ;
        }
        else{
                return size/2 + Rank(value, size/2,&array[size/2]) ;

        }
    }
}
<|endoftext|>


<commit_before>#include <functional>
#include "Common.h"

#include "CGame.h"
#include "CRenderer.h"
#include <SDL/SDL.h>
#include <SDL/SDL_mixer.h>

#include <iostream>

namespace odb {

    SDL_Surface *video;

    CRenderer::CRenderer(CControlCallback keyPressedCallback, CControlCallback keyReleasedCallback) :
            mOnKeyPressedCallback(keyPressedCallback), mOnKeyReleasedCallback(keyReleasedCallback) {
        SDL_Init(SDL_INIT_EVERYTHING);
        video = SDL_SetVideoMode(640, 480, 0, 0);
    }

    void CRenderer::sleep(long ms) {
        SDL_Delay(33);
    }

    void CRenderer::handleSystemEvents() {
        SDL_Event event;

        while (SDL_PollEvent(&event)) {

            if (event.type == SDL_QUIT) {
#ifndef __EMSCRIPTEN__
                exit(0);
#endif
            }

            if (event.type == SDL_KEYUP) {
                switch (event.key.keysym.sym) {
                    case SDLK_q:
#ifndef __EMSCRIPTEN__
                        exit(0);
#endif
                    case SDLK_LEFT:
                        mOnKeyReleasedCallback(ECommand::kLeft);
                        break;

                    case SDLK_RIGHT:
                        mOnKeyReleasedCallback(ECommand::kRight);
                        break;

                    case SDLK_UP:
                        mOnKeyReleasedCallback(ECommand::kUp);
                        break;

                    case SDLK_DOWN:
                        mOnKeyReleasedCallback(ECommand::kDown);
                        break;
                    case SDLK_SPACE:
                        mOnKeyReleasedCallback(ECommand::kFire1);
                        break;
                    default:
                        break;
                }
            }

            if (event.type == SDL_KEYDOWN) {
                switch (event.key.keysym.sym) {
                    case SDLK_LEFT:
                        mOnKeyPressedCallback(ECommand::kLeft);
                        break;
                    case SDLK_RIGHT:
                        mOnKeyPressedCallback(ECommand::kRight);
                        break;

                    case SDLK_UP:
                        mOnKeyPressedCallback(ECommand::kUp);
                        break;

                    case SDLK_DOWN:
                        mOnKeyPressedCallback(ECommand::kDown);
                        break;
                    case SDLK_SPACE:
                        mOnKeyPressedCallback(ECommand::kFire1);
                        break;
                    default:
                        break;
                }
            }

        }
    }

    void CRenderer::render(const CGame &game, long ms) {

        SDL_Rect rect;

        switch (game.gameState) {
            case CGame::EGameState::kTitleScreen:
            case CGame::EGameState::kVictory:
            case CGame::EGameState::kGameOver:
            case CGame::EGameState::kGame:

                rect = {0, 0, 640, 241};
                SDL_FillRect(video, &rect, SDL_MapRGB(video->format, 0, 0, 255));

                int delta = 0;

                if (game.shape == ')') {
                    delta = -1;
                }

                if ( game.shape == '(') {
                    delta = 1;
                }

                for ( int y = 0; y < 240; ++y ) {
                    int roadX = ( (240 * 10 * delta) / (240-y) ) +  320 - (240 - y) - ( ((240 - y) * game.x) / 240);
                    int roadDeltaX = 32 + ((240 - y) * 2);
                    int shade = ( (240 - y) / 4);

                    rect = {0, (240 - y), 640, 1};
                    SDL_FillRect(video, &rect, SDL_MapRGB(video->format, 0, 0, 128 + shade / 2));

                    rect = {0, 240 + (240 - y), 640, 1};
                    SDL_FillRect(video, &rect, SDL_MapRGB(video->format, 0, 128 + shade / 2, 0));

                    rect = { roadX, 240 + (240 - y), roadDeltaX, 1};
                    SDL_FillRect(video, &rect, SDL_MapRGB(video->format, 64 + shade, 64 + shade, 64 + shade));

                }

                rect = SDL_Rect{0, 0, 80, 40};
                rect.x = 320 + (game.x );
                rect.y = 440;

                SDL_FillRect(video, &rect, SDL_MapRGB(video->format, 255, 0, 0));

                SDL_Flip(video);
        }
    }
}
<commit_msg>Add rendering of the track elements with smooth transition<commit_after>#include <functional>
#include "Common.h"

#include "CGame.h"
#include "CRenderer.h"
#include <SDL/SDL.h>
#include <SDL/SDL_mixer.h>

#include <iostream>

namespace odb {

    SDL_Surface *video;

    CRenderer::CRenderer(CControlCallback keyPressedCallback, CControlCallback keyReleasedCallback) :
            mOnKeyPressedCallback(keyPressedCallback), mOnKeyReleasedCallback(keyReleasedCallback) {
        SDL_Init(SDL_INIT_EVERYTHING);
        video = SDL_SetVideoMode(640, 480, 0, 0);
    }

    void CRenderer::sleep(long ms) {
        SDL_Delay(33);
    }

    void CRenderer::handleSystemEvents() {
        SDL_Event event;

        while (SDL_PollEvent(&event)) {

            if (event.type == SDL_QUIT) {
#ifndef __EMSCRIPTEN__
                exit(0);
#endif
            }

            if (event.type == SDL_KEYUP) {
                switch (event.key.keysym.sym) {
                    case SDLK_q:
#ifndef __EMSCRIPTEN__
                        exit(0);
#endif
                    case SDLK_LEFT:
                        mOnKeyReleasedCallback(ECommand::kLeft);
                        break;

                    case SDLK_RIGHT:
                        mOnKeyReleasedCallback(ECommand::kRight);
                        break;

                    case SDLK_UP:
                        mOnKeyReleasedCallback(ECommand::kUp);
                        break;

                    case SDLK_DOWN:
                        mOnKeyReleasedCallback(ECommand::kDown);
                        break;
                    case SDLK_SPACE:
                        mOnKeyReleasedCallback(ECommand::kFire1);
                        break;
                    default:
                        break;
                }
            }

            if (event.type == SDL_KEYDOWN) {
                switch (event.key.keysym.sym) {
                    case SDLK_LEFT:
                        mOnKeyPressedCallback(ECommand::kLeft);
                        break;
                    case SDLK_RIGHT:
                        mOnKeyPressedCallback(ECommand::kRight);
                        break;

                    case SDLK_UP:
                        mOnKeyPressedCallback(ECommand::kUp);
                        break;

                    case SDLK_DOWN:
                        mOnKeyPressedCallback(ECommand::kDown);
                        break;
                    case SDLK_SPACE:
                        mOnKeyPressedCallback(ECommand::kFire1);
                        break;
                    default:
                        break;
                }
            }

        }
    }

    void CRenderer::render(const CGame &game, long ms) {

        SDL_Rect rect;

        switch (game.gameState) {
            case CGame::EGameState::kTitleScreen:
            case CGame::EGameState::kVictory:
            case CGame::EGameState::kGameOver:
            case CGame::EGameState::kGame:

                rect = {0, 0, 640, 241};
                SDL_FillRect(video, &rect, SDL_MapRGB(video->format, 0, 0, 255));

                int delta = 0;

                if (game.track[ game.elementIndex ] == ')') {
                    delta = -1;
                }

                if ( game.track[ game.elementIndex ] == '(') {
                    delta = 1;
                }

                int distance = 0;

                if ( game.distanceToNextElement > 50 ) {
                    distance = ( 100 - game.distanceToNextElement );
                } else {
                    distance = ( game.distanceToNextElement );
                }

                for ( int y = 0; y < 240; ++y ) {
                    int roadX = ( (240 * distance * delta) / (240-y) ) +  320 - (240 - y) - ( ((240 - y) * game.x) / 240);
                    int roadDeltaX = 32 + ((240 - y) * 2);
                    int shade = ( (240 - y) / 4);

                    rect = {0, (240 - y), 640, 1};
                    SDL_FillRect(video, &rect, SDL_MapRGB(video->format, 0, 0, 128 + shade / 2));

                    rect = {0, 240 + (240 - y), 640, 1};
                    SDL_FillRect(video, &rect, SDL_MapRGB(video->format, 0, 128 + shade / 2, 0));

                    rect = { roadX, 240 + (240 - y), roadDeltaX, 1};
                    SDL_FillRect(video, &rect, SDL_MapRGB(video->format, 64 + shade, 64 + shade, 64 + shade));

                }

                rect = SDL_Rect{0, 0, 80, 40};
                rect.x = 320 + (game.x );
                rect.y = 440;

                SDL_FillRect(video, &rect, SDL_MapRGB(video->format, 255, 0, 0));

                SDL_Flip(video);
        }
    }
}
<|endoftext|>


<commit_before>#include "ScreenCache.h"
#include "EE_SP.h"
#include "Sprite.h"
#include "Symbol.h"
#include "Camera.h"

#include <dtex_cs.h>
#include <dtex_screen.h>
#include <dtex_gl.h>
#include <shaderlab.h>
#include <sprite2/RenderParams.h>

#include <gl/glew.h>

namespace ee
{

ScreenCache* ScreenCache::m_instance = NULL;

static dtex_cs* CS;

ScreenCache::ScreenCache()
{
	CS = dtex_cs_create();
}

void ScreenCache::SetSize(int w, int h)
{
	m_width = w;
	m_height = h;
	dtex_cs_on_size(CS, w, h);
}

void ScreenCache::GetSize(int& w, int& h) const
{
	w = m_width;
	h = m_height;
}

void ScreenCache::Reload()
{
	dtex_cs_reload(CS);
}

void ScreenCache::Bind()
{
	dtex_cs_bind(CS);
}

void ScreenCache::Unbind()
{
	dtex_cs_unbind(CS);
}

void ScreenCache::InvalidRect(float xmin, float ymin, float xmax, float ymax)
{
	dtex_cs_rect r;
	r.xmin = xmin;
	r.ymin = ymin;
	r.xmax = xmax;
	r.ymax = ymax;
	dtex_cs_add_inv_rect(CS, &r);
}

static void _cs_draw(struct dtex_cs_rect* r, void* ud)
{
	const Camera* cam = (Camera*)ud;

	float cam_x = cam->GetPosition().x,
		  cam_y = cam->GetPosition().y,
		  cam_scale = cam->GetScale();

	float scr_w, scr_h, scr_s;
	dtex_get_screen(&scr_w, &scr_h, &scr_s);

	int x = static_cast<int>((r->xmin - cam_x) / cam_scale + scr_w * 0.5f),
		y = static_cast<int>((r->ymin - cam_y) / cam_scale + scr_h * 0.5f),
		w = static_cast<int>((r->xmax - r->xmin) / cam_scale),
		h = static_cast<int>((r->ymax - r->ymin) / cam_scale);
	dtex_gl_scissor(x, y, w, h);
	dtex_gl_clear_color(0, 1, 0, 1);

	sm::rect rq;
	rq.xmin = r->xmin;
	rq.ymin = r->ymin;
	rq.xmax = r->xmax;
	rq.ymax = r->ymax;

	std::vector<const Sprite*> sprites;
	SpatialPartition::Instance()->Query(rq, sprites);

	for (int i = 0, n = sprites.size(); i < n; ++i) {
		const Sprite* spr = sprites[i];

		s2::RenderParams params;
		params.mt = spr->GetTransMatrix();
		spr->GetSymbol().Draw(params);
	}

	sl::ShaderMgr::Instance()->GetShader()->Commit();
}

void ScreenCache::Draw(const Camera* cam)
{
	glEnable(GL_SCISSOR_TEST);
	dtex_cs_traverse(CS, &_cs_draw, (Camera*)cam);
	glDisable(GL_SCISSOR_TEST);
}

void ScreenCache::DrawToScreen(void (*before_draw)(void* ud), void* ud)
{
	dtex_cs_draw(CS, before_draw, ud);
}

int ScreenCache::GetTexID() const
{
	return dtex_cs_get_texture_id(CS);
}

ScreenCache* ScreenCache::Instance()
{
	if (!m_instance) {
		m_instance = new ScreenCache();
	}
	return m_instance;
}

}<commit_msg>fixed for dtex changed<commit_after>#include "ScreenCache.h"
#include "EE_SP.h"
#include "Sprite.h"
#include "Symbol.h"
#include "Camera.h"

#include <dtex_cs.h>
#include <dtex_screen.h>
#include <dtex_gl.h>
#include <shaderlab.h>
#include <sprite2/RenderParams.h>

#include <gl/glew.h>

namespace ee
{

ScreenCache* ScreenCache::m_instance = NULL;

static dtex_cs* CS;

ScreenCache::ScreenCache()
{
	CS = dtex_cs_create();
}

void ScreenCache::SetSize(int w, int h)
{
	m_width = w;
	m_height = h;
	dtex_cs_on_size(CS, w, h);
}

void ScreenCache::GetSize(int& w, int& h) const
{
	w = m_width;
	h = m_height;
}

void ScreenCache::Reload()
{
	dtex_cs_reload(CS);
}

void ScreenCache::Bind()
{
	dtex_cs_bind(CS);
}

void ScreenCache::Unbind()
{
	dtex_cs_unbind(CS);
}

void ScreenCache::InvalidRect(float xmin, float ymin, float xmax, float ymax)
{
	dtex_cs_rect r;
	r.xmin = xmin;
	r.ymin = ymin;
	r.xmax = xmax;
	r.ymax = ymax;
	dtex_cs_add_inv_rect(CS, &r);
}

static void _cs_draw(struct dtex_cs_rect* r, void* ud)
{
	const Camera* cam = (Camera*)ud;

	float cam_x = cam->GetPosition().x,
		  cam_y = cam->GetPosition().y,
		  cam_scale = cam->GetScale();

	float scr_w, scr_h, scr_s;
	dtex_get_screen(&scr_w, &scr_h, &scr_s);

	int x = static_cast<int>((r->xmin - cam_x) / cam_scale + scr_w * 0.5f),
		y = static_cast<int>((r->ymin - cam_y) / cam_scale + scr_h * 0.5f),
		w = static_cast<int>((r->xmax - r->xmin) / cam_scale),
		h = static_cast<int>((r->ymax - r->ymin) / cam_scale);
	dtex_gl_scissor(x, y, w, h);
	dtex_gl_clear_color(0, 1, 0, 1);

	sm::rect rq;
	rq.xmin = r->xmin;
	rq.ymin = r->ymin;
	rq.xmax = r->xmax;
	rq.ymax = r->ymax;

	std::vector<const Sprite*> sprites;
	SpatialPartition::Instance()->Query(rq, sprites);

	for (int i = 0, n = sprites.size(); i < n; ++i) {
		const Sprite* spr = sprites[i];

		s2::RenderParams params;
		params.mt = spr->GetTransMatrix();
		spr->GetSymbol().Draw(params);
	}

	sl::ShaderMgr::Instance()->GetShader()->Commit();
}

void ScreenCache::Draw(const Camera* cam)
{
	glEnable(GL_SCISSOR_TEST);
	dtex_cs_traverse(CS, &_cs_draw, (Camera*)cam);
	glDisable(GL_SCISSOR_TEST);
}

void ScreenCache::DrawToScreen(void (*before_draw)(void* ud), void* ud)
{
	dtex_cs_draw(CS, 1, 1, 1, 1, before_draw, ud);
}

int ScreenCache::GetTexID() const
{
	return dtex_cs_get_texture_id(CS);
}

ScreenCache* ScreenCache::Instance()
{
	if (!m_instance) {
		m_instance = new ScreenCache();
	}
	return m_instance;
}

}<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

// Event generator that using an instance of type AliGenReader
// reads particles from a file and applies cuts.
// Example: In your Config.C you can include the following lines
//  AliGenExtFile *gener = new AliGenExtFile(-1);
//  gener->SetMomentumRange(0,999);
//  gener->SetPhiRange(-180.,180.);
//  gener->SetThetaRange(0,180);
//  gener->SetYRange(-999,999);
//  AliGenReaderTreeK * reader = new AliGenReaderTreeK();
//  reader->SetFileName("myFileWithTreeK.root");
//  gener->SetReader(reader);
//  gener->Init();

#include <Riostream.h>

#include "AliGenExtFile.h"
#include "AliRunLoader.h"
#include "AliHeader.h"
#include "AliGenEventHeader.h"

#include <TParticle.h>
#include <TFile.h>
#include <TTree.h>

ClassImp(AliGenExtFile)

AliGenExtFile::AliGenExtFile()
    :AliGenMC(),
     fFileName(0),
     fReader(0)
{
//  Constructor
//
//  Read all particles
    fNpart  =- 1;
}

AliGenExtFile::AliGenExtFile(Int_t npart)
    :AliGenMC(npart),
     fFileName(0),
     fReader(0)
{
//  Constructor
    fName   = "ExtFile";
    fTitle  = "Primaries from ext. File";
}

//____________________________________________________________
AliGenExtFile::~AliGenExtFile()
{
// Destructor
    delete fReader;
}

//___________________________________________________________
void AliGenExtFile::Init()
{
// Initialize
    if (fReader) fReader->Init();
}

void AliGenExtFile::Generate()
{
// Generate particles

  Float_t polar[3]  = {0,0,0};
  //
  Float_t origin[3] = {0,0,0};
  Float_t p[3];
  Float_t random[6];
  Int_t i = 0, j, nt;
  //
  //
  if (fVertexSmear == kPerEvent) Vertex();

  while(1) {
    Int_t nTracks = fReader->NextEvent();
    if (nTracks == 0) {
      // printf("\n No more events !!! !\n");
      Warning("AliGenExtFile::Generate","\nNo more events in external file!!!\nLast event may be empty or incomplete.\n");
      return;
    }

    //
    // Particle selection loop
    //
    // The selection criterium for the external file generator is as follows:
    //
    // 1) All tracks are subject to the cuts defined by AliGenerator, i.e.
    //    fThetaMin, fThetaMax, fPhiMin, fPhiMax, fPMin, fPMax, fPtMin, fPtMax,
    //    fYMin, fYMax.
    //    If the particle does not satisfy these cuts, it is not put on the
    //    stack.
    // 2) If fCutOnChild and some specific child is selected (e.g. if
    //    fForceDecay==kSemiElectronic) the event is rejected if NOT EVEN ONE
    //    child falls into the child-cuts.
    TParticle* iparticle = 0x0;

    if(fCutOnChild) {
      // Count the selected children
      Int_t nSelected = 0;
      while ((iparticle=fReader->NextParticle()) ) {
	  Int_t kf = CheckPDGCode(iparticle->GetPdgCode());
	  kf = TMath::Abs(kf);
	  if (ChildSelected(kf) && KinematicSelection(iparticle, 1)) {
	      nSelected++;
	  }
      }
      if (!nSelected) continue;    // No particle selected:  Go to next event
      fReader->RewindEvent();
    }

    //
    // Stack filling loop
    //
    fNprimaries = 0;
    for (i = 0; i < nTracks; i++) {
	TParticle* jparticle = fReader->NextParticle();
	Bool_t selected = KinematicSelection(jparticle,0);
	if (!selected) continue;
	p[0] = jparticle->Px();
	p[1] = jparticle->Py();
	p[2] = jparticle->Pz();
	Int_t idpart = iparticle->GetPdgCode();
	if(fVertexSmear==kPerTrack)
	{
	    Rndm(random,6);
	    for (j = 0; j < 3; j++) {
		origin[j]=fOrigin[j]+
		    fOsigma[j]*TMath::Cos(2*random[2*j]*TMath::Pi())*
		    TMath::Sqrt(-2*TMath::Log(random[2*j+1]));
	    }
	} else {
	    origin[0] = fVertex[0] + jparticle->Vx();
	    origin[1] = fVertex[1] + jparticle->Vy();
	    origin[2] = fVertex[2] + jparticle->Vz();
	}

	Int_t decayed    = jparticle->GetFirstDaughter();
	Int_t doTracking = fTrackIt && (decayed < 0) && (TMath::Abs(idpart) > 10) && selected;
	Int_t parent     = jparticle->GetFirstMother();

	PushTrack(doTracking, parent, idpart, p, origin, polar, 0, kPPrimary, nt);
	KeepTrack(nt);
	fNprimaries++;
    } // track loop

    // Generated event header

    AliGenEventHeader * header = new AliGenEventHeader();
    header->SetNProduced(fNprimaries);
    header->SetPrimaryVertex(fVertex);
    AddHeader(header);
    break;

  } // event loop

  SetHighWaterMark(nt);
  CdEventFile();
}

void AliGenExtFile::CdEventFile()
{
// CD back to the event file
    (AliRunLoader::GetRunLoader())->CdGAFile();
}

<commit_msg>Fixed copy/paste error<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

// Event generator that using an instance of type AliGenReader
// reads particles from a file and applies cuts.
// Example: In your Config.C you can include the following lines
//  AliGenExtFile *gener = new AliGenExtFile(-1);
//  gener->SetMomentumRange(0,999);
//  gener->SetPhiRange(-180.,180.);
//  gener->SetThetaRange(0,180);
//  gener->SetYRange(-999,999);
//  AliGenReaderTreeK * reader = new AliGenReaderTreeK();
//  reader->SetFileName("myFileWithTreeK.root");
//  gener->SetReader(reader);
//  gener->Init();

#include <Riostream.h>

#include "AliGenExtFile.h"
#include "AliRunLoader.h"
#include "AliHeader.h"
#include "AliGenEventHeader.h"

#include <TParticle.h>
#include <TFile.h>
#include <TTree.h>

ClassImp(AliGenExtFile)

AliGenExtFile::AliGenExtFile()
    :AliGenMC(),
     fFileName(0),
     fReader(0)
{
//  Constructor
//
//  Read all particles
    fNpart  =- 1;
}

AliGenExtFile::AliGenExtFile(Int_t npart)
    :AliGenMC(npart),
     fFileName(0),
     fReader(0)
{
//  Constructor
    fName   = "ExtFile";
    fTitle  = "Primaries from ext. File";
}

//____________________________________________________________
AliGenExtFile::~AliGenExtFile()
{
// Destructor
    delete fReader;
}

//___________________________________________________________
void AliGenExtFile::Init()
{
// Initialize
    if (fReader) fReader->Init();
}

void AliGenExtFile::Generate()
{
// Generate particles

  Float_t polar[3]  = {0,0,0};
  //
  Float_t origin[3] = {0,0,0};
  Float_t p[3];
  Float_t random[6];
  Int_t i = 0, j, nt;
  //
  //
  if (fVertexSmear == kPerEvent) Vertex();

  while(1) {
    Int_t nTracks = fReader->NextEvent();
    if (nTracks == 0) {
      // printf("\n No more events !!! !\n");
      Warning("AliGenExtFile::Generate","\nNo more events in external file!!!\nLast event may be empty or incomplete.\n");
      return;
    }

    //
    // Particle selection loop
    //
    // The selection criterium for the external file generator is as follows:
    //
    // 1) All tracks are subject to the cuts defined by AliGenerator, i.e.
    //    fThetaMin, fThetaMax, fPhiMin, fPhiMax, fPMin, fPMax, fPtMin, fPtMax,
    //    fYMin, fYMax.
    //    If the particle does not satisfy these cuts, it is not put on the
    //    stack.
    // 2) If fCutOnChild and some specific child is selected (e.g. if
    //    fForceDecay==kSemiElectronic) the event is rejected if NOT EVEN ONE
    //    child falls into the child-cuts.
    TParticle* iparticle = 0x0;

    if(fCutOnChild) {
      // Count the selected children
      Int_t nSelected = 0;
      while ((iparticle=fReader->NextParticle()) ) {
	  Int_t kf = CheckPDGCode(iparticle->GetPdgCode());
	  kf = TMath::Abs(kf);
	  if (ChildSelected(kf) && KinematicSelection(iparticle, 1)) {
	      nSelected++;
	  }
      }
      if (!nSelected) continue;    // No particle selected:  Go to next event
      fReader->RewindEvent();
    }

    //
    // Stack filling loop
    //
    fNprimaries = 0;
    for (i = 0; i < nTracks; i++) {
	TParticle* jparticle = fReader->NextParticle();
	Bool_t selected = KinematicSelection(jparticle,0);
	if (!selected) continue;
	p[0] = jparticle->Px();
	p[1] = jparticle->Py();
	p[2] = jparticle->Pz();
	Int_t idpart = jparticle->GetPdgCode();
	if(fVertexSmear==kPerTrack)
	{
	    Rndm(random,6);
	    for (j = 0; j < 3; j++) {
		origin[j]=fOrigin[j]+
		    fOsigma[j]*TMath::Cos(2*random[2*j]*TMath::Pi())*
		    TMath::Sqrt(-2*TMath::Log(random[2*j+1]));
	    }
	} else {
	    origin[0] = fVertex[0] + jparticle->Vx();
	    origin[1] = fVertex[1] + jparticle->Vy();
	    origin[2] = fVertex[2] + jparticle->Vz();
	}

	Int_t decayed    = jparticle->GetFirstDaughter();
	Int_t doTracking = fTrackIt && (decayed < 0) && (TMath::Abs(idpart) > 10) && selected;
	Int_t parent     = jparticle->GetFirstMother();

	PushTrack(doTracking, parent, idpart, p, origin, polar, 0, kPPrimary, nt);
	KeepTrack(nt);
	fNprimaries++;
    } // track loop

    // Generated event header

    AliGenEventHeader * header = new AliGenEventHeader();
    header->SetNProduced(fNprimaries);
    header->SetPrimaryVertex(fVertex);
    AddHeader(header);
    break;

  } // event loop

  SetHighWaterMark(nt);
  CdEventFile();
}

void AliGenExtFile::CdEventFile()
{
// CD back to the event file
    (AliRunLoader::GetRunLoader())->CdGAFile();
}

<|endoftext|>


<commit_before>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

// Event generator that using an instance of type AliGenReader
// reads particles from a file and applies cuts.
// Example: In your Config.C you can include the following lines
//  AliGenExtFile *gener = new AliGenExtFile(-1);
//  gener->SetMomentumRange(0,999);
//  gener->SetPhiRange(-180.,180.);
//  gener->SetThetaRange(0,180);
//  gener->SetYRange(-999,999);
//  AliGenReaderTreeK * reader = new AliGenReaderTreeK();
//  reader->SetFileName("myFileWithTreeK.root");
//  gener->SetReader(reader);
//  gener->Init();

#include <Riostream.h>

#include "AliGenExtFile.h"
#include "AliRunLoader.h"
#include "AliHeader.h"
#include "AliGenEventHeader.h"

#include <TParticle.h>
#include <TFile.h>
#include <TTree.h>

ClassImp(AliGenExtFile)

AliGenExtFile::AliGenExtFile()
  :AliGenMC()
{
//  Constructor
//
//  Read all particles
    fNpart  =- 1;
    fReader =  0;
}

AliGenExtFile::AliGenExtFile(Int_t npart)
    :AliGenMC(npart)
{
//  Constructor
    fName   = "ExtFile";
    fTitle  = "Primaries from ext. File";
    fReader = 0;
}

AliGenExtFile::AliGenExtFile(const AliGenExtFile & ExtFile):
    AliGenMC(ExtFile)
{
// Copy constructor
    ExtFile.Copy(*this);
}
//____________________________________________________________
AliGenExtFile::~AliGenExtFile()
{
// Destructor
    delete fReader;
}

//___________________________________________________________
void AliGenExtFile::Init()
{
// Initialize
    if (fReader) fReader->Init();
}

void AliGenExtFile::Generate()
{
// Generate particles

  Float_t polar[3]  = {0,0,0};
  //
  Float_t origin[3] = {0,0,0};
  Float_t p[3];
  Float_t random[6];
  Int_t i = 0, j, nt;
  //
  //
  if (fVertexSmear == kPerEvent) Vertex();

  while(1) {
    Int_t nTracks = fReader->NextEvent();
    if (nTracks == 0) {
      // printf("\n No more events !!! !\n");
      Warning("AliGenExtFile::Generate","\nNo more events in external file!!!\nLast event may be empty or incomplete.\n");
      return;
    }

    // Generated event header

    AliRunLoader * inRunLoader = fReader->GetRunLoader();
    if(inRunLoader) {
      AliGenEventHeader * inHeader = inRunLoader->GetHeader()->GenEventHeader();
      if (inHeader) {
	AliGenEventHeader * header = new AliGenEventHeader(*inHeader);
	AliRunLoader::GetRunLoader()->GetHeader()->SetGenEventHeader(header);
      }
    }
    //
    // Particle selection loop
    //
    // The selection criterium for the external file generator is as follows:
    //
    // 1) All tracks are subject to the cuts defined by AliGenerator, i.e.
    //    fThetaMin, fThetaMax, fPhiMin, fPhiMax, fPMin, fPMax, fPtMin, fPtMax,
    //    fYMin, fYMax.
    //    If the particle does not satisfy these cuts, it is not put on the
    //    stack.
    // 2) If fCutOnChild and some specific child is selected (e.g. if
    //    fForceDecay==kSemiElectronic) the event is rejected if NOT EVEN ONE
    //    child falls into the child-cuts.
    TParticle* iparticle = 0x0;

    if(fCutOnChild) {
      // Count the selected children
      Int_t nSelected = 0;
      while ((iparticle=fReader->NextParticle()) ) {
	  Int_t kf = CheckPDGCode(iparticle->GetPdgCode());
	  kf = TMath::Abs(kf);
	  if (ChildSelected(kf) && KinematicSelection(iparticle, 1)) {
	      nSelected++;
	  }
      }
      if (!nSelected) continue;    // No particle selected:  Go to next event
      fReader->RewindEvent();
    }

    //
    // Stack filling loop
    //
    for (i = 0; i < nTracks; i++) {
	TParticle* iparticle = fReader->NextParticle();
	Bool_t selected = KinematicSelection(iparticle,0);
	if (!selected) continue;
	p[0] = iparticle->Px();
	p[1] = iparticle->Py();
	p[2] = iparticle->Pz();
	Int_t idpart = iparticle->GetPdgCode();
	if(fVertexSmear==kPerTrack)
	{
	    Rndm(random,6);
	    for (j = 0; j < 3; j++) {
		origin[j]=fOrigin[j]+
		    fOsigma[j]*TMath::Cos(2*random[2*j]*TMath::Pi())*
		    TMath::Sqrt(-2*TMath::Log(random[2*j+1]));
	    }
	} else {
	    origin[0] = fVertex[0] + iparticle->Vx();
	    origin[1] = fVertex[1] + iparticle->Vy();
	    origin[2] = fVertex[2] + iparticle->Vz();
	}

	Int_t decayed    = iparticle->GetFirstDaughter();
	Int_t doTracking = fTrackIt && (decayed < 0) && (TMath::Abs(idpart) > 10) && selected;
	Int_t parent     = iparticle->GetFirstMother();

	PushTrack(doTracking,parent,idpart,p,origin,polar,0,kPPrimary,nt);
	KeepTrack(nt);
    } // track loop

    break;

  } // event loop

  SetHighWaterMark(nt);
  CdEventFile();
}

void AliGenExtFile::CdEventFile()
{
// CD back to the event file
    (AliRunLoader::GetRunLoader())->CdGAFile();
}

AliGenExtFile& AliGenExtFile::operator=(const  AliGenExtFile& rhs)
{
// Assignment operator
    rhs.Copy(*this);
    return *this;
}

void AliGenExtFile::Copy(TObject&) const
{
    //
    // Copy
    //
    Fatal("Copy","Not implemented!\n");
}

<commit_msg>Do not copy, but create the generated event header<commit_after>/**************************************************************************
 * Copyright(c) 1998-1999, ALICE Experiment at CERN, All rights reserved. *
 *                                                                        *
 * Author: The ALICE Off-line Project.                                    *
 * Contributors are mentioned in the code where appropriate.              *
 *                                                                        *
 * Permission to use, copy, modify and distribute this software and its   *
 * documentation strictly for non-commercial purposes is hereby granted   *
 * without fee, provided that the above copyright notice appears in all   *
 * copies and that both the copyright notice and this permission notice   *
 * appear in the supporting documentation. The authors make no claims     *
 * about the suitability of this software for any purpose. It is          *
 * provided "as is" without express or implied warranty.                  *
 **************************************************************************/

/* $Id$ */

// Event generator that using an instance of type AliGenReader
// reads particles from a file and applies cuts.
// Example: In your Config.C you can include the following lines
//  AliGenExtFile *gener = new AliGenExtFile(-1);
//  gener->SetMomentumRange(0,999);
//  gener->SetPhiRange(-180.,180.);
//  gener->SetThetaRange(0,180);
//  gener->SetYRange(-999,999);
//  AliGenReaderTreeK * reader = new AliGenReaderTreeK();
//  reader->SetFileName("myFileWithTreeK.root");
//  gener->SetReader(reader);
//  gener->Init();

#include <Riostream.h>

#include "AliGenExtFile.h"
#include "AliRunLoader.h"
#include "AliHeader.h"
#include "AliGenEventHeader.h"

#include <TParticle.h>
#include <TFile.h>
#include <TTree.h>

ClassImp(AliGenExtFile)

AliGenExtFile::AliGenExtFile()
  :AliGenMC()
{
//  Constructor
//
//  Read all particles
    fNpart  =- 1;
    fReader =  0;
}

AliGenExtFile::AliGenExtFile(Int_t npart)
    :AliGenMC(npart)
{
//  Constructor
    fName   = "ExtFile";
    fTitle  = "Primaries from ext. File";
    fReader = 0;
}

AliGenExtFile::AliGenExtFile(const AliGenExtFile & ExtFile):
    AliGenMC(ExtFile)
{
// Copy constructor
    ExtFile.Copy(*this);
}
//____________________________________________________________
AliGenExtFile::~AliGenExtFile()
{
// Destructor
    delete fReader;
}

//___________________________________________________________
void AliGenExtFile::Init()
{
// Initialize
    if (fReader) fReader->Init();
}

void AliGenExtFile::Generate()
{
// Generate particles

  Float_t polar[3]  = {0,0,0};
  //
  Float_t origin[3] = {0,0,0};
  Float_t p[3];
  Float_t random[6];
  Int_t i = 0, j, nt;
  //
  //
  if (fVertexSmear == kPerEvent) Vertex();

  while(1) {
    Int_t nTracks = fReader->NextEvent();
    if (nTracks == 0) {
      // printf("\n No more events !!! !\n");
      Warning("AliGenExtFile::Generate","\nNo more events in external file!!!\nLast event may be empty or incomplete.\n");
      return;
    }

    //
    // Particle selection loop
    //
    // The selection criterium for the external file generator is as follows:
    //
    // 1) All tracks are subject to the cuts defined by AliGenerator, i.e.
    //    fThetaMin, fThetaMax, fPhiMin, fPhiMax, fPMin, fPMax, fPtMin, fPtMax,
    //    fYMin, fYMax.
    //    If the particle does not satisfy these cuts, it is not put on the
    //    stack.
    // 2) If fCutOnChild and some specific child is selected (e.g. if
    //    fForceDecay==kSemiElectronic) the event is rejected if NOT EVEN ONE
    //    child falls into the child-cuts.
    TParticle* iparticle = 0x0;

    if(fCutOnChild) {
      // Count the selected children
      Int_t nSelected = 0;
      while ((iparticle=fReader->NextParticle()) ) {
	  Int_t kf = CheckPDGCode(iparticle->GetPdgCode());
	  kf = TMath::Abs(kf);
	  if (ChildSelected(kf) && KinematicSelection(iparticle, 1)) {
	      nSelected++;
	  }
      }
      if (!nSelected) continue;    // No particle selected:  Go to next event
      fReader->RewindEvent();
    }

    //
    // Stack filling loop
    //
    for (i = 0; i < nTracks; i++) {
	TParticle* iparticle = fReader->NextParticle();
	Bool_t selected = KinematicSelection(iparticle,0);
	if (!selected) continue;
	p[0] = iparticle->Px();
	p[1] = iparticle->Py();
	p[2] = iparticle->Pz();
	Int_t idpart = iparticle->GetPdgCode();
	if(fVertexSmear==kPerTrack)
	{
	    Rndm(random,6);
	    for (j = 0; j < 3; j++) {
		origin[j]=fOrigin[j]+
		    fOsigma[j]*TMath::Cos(2*random[2*j]*TMath::Pi())*
		    TMath::Sqrt(-2*TMath::Log(random[2*j+1]));
	    }
	} else {
	    origin[0] = fVertex[0] + iparticle->Vx();
	    origin[1] = fVertex[1] + iparticle->Vy();
	    origin[2] = fVertex[2] + iparticle->Vz();
	}

	Int_t decayed    = iparticle->GetFirstDaughter();
	Int_t doTracking = fTrackIt && (decayed < 0) && (TMath::Abs(idpart) > 10) && selected;
	Int_t parent     = iparticle->GetFirstMother();

	PushTrack(doTracking,parent,idpart,p,origin,polar,0,kPPrimary,nt);
	KeepTrack(nt);
    } // track loop

    // Generated event header

    AliGenEventHeader * header = new AliGenEventHeader();
    header->SetNProduced(nt+1);
    header->SetPrimaryVertex(fVertex);
    AliRunLoader::GetRunLoader()->GetHeader()->SetGenEventHeader(header);

    break;

  } // event loop

  SetHighWaterMark(nt);
  CdEventFile();
}

void AliGenExtFile::CdEventFile()
{
// CD back to the event file
    (AliRunLoader::GetRunLoader())->CdGAFile();
}

AliGenExtFile& AliGenExtFile::operator=(const  AliGenExtFile& rhs)
{
// Assignment operator
    rhs.Copy(*this);
    return *this;
}

void AliGenExtFile::Copy(TObject&) const
{
    //
    // Copy
    //
    Fatal("Copy","Not implemented!\n");
}

<|endoftext|>


<commit_before>/**
 *
 *  \file gene.cc
 *
 *  \author Manlio Morini
 *  \date 2011/05/11
 *
 *  This file is part of VITA
 *
 */

#include "gene.h"

#include "random.h"
#include "symbol.h"

namespace vita
{

  ///
  /// \param[in] sset the set of symbols to choose from.
  ///
  gene::gene(const symbol_set &sset)
  {
    sym = sset.roulette(true);

    if (sym->parametric())
      par = sym->init();
  }

  ///
  /// \param[in] sset the set of symbols to choose from.
  /// \param[in] from minimum index for function arguments.
  /// \param[in] sup upper bound for the indexes of function arguments.
  ///
  gene::gene(const symbol_set &sset, unsigned from, unsigned sup)
  {
    assert(from <= sup);
    sym = sset.roulette(from==sup);

    if (sym->parametric())
      par = sym->init();
    else
    {
      const unsigned argc(sym->argc());
      for (unsigned j(0); j < argc; ++j)
        args[j] = random::between<unsigned>(from,sup);
    }
  }

  ///
  /// \param[in] sset the set of symbols to choose from.
  /// \param[in] i index of a special symbol in the \a symbol_set.
  ///
  gene::gene(const symbol_set &sset, unsigned i)
  {
    sym = sset.get_special(i);
    if (sym->parametric())
      par = sym->init();
  }

  ///
  /// \param[in] g second term of comparison.
  /// \return true if \c this == \a g
  ///
  bool
  gene::operator==(const gene &g) const
  {
    if (sym != g.sym)
      return false;

    if (sym->parametric())
      return par==g.par;

    const unsigned n(sym->argc());
    for (unsigned i(0); i < n; ++i)
      if (args[i] != g.args[i])
        return false;

    return true;
  }

}  // namespace vita
<commit_msg>gene: GPL disclaimer and Google C++ Style Guide related adaptations.<commit_after>/**
 *
 *  \file gene.cc
 *
 *  Copyright (c) 2011 EOS di Manlio Morini.
 *
 *  This file is part of VITA.
 *
 *  VITA 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.
 *
 *  VITA 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 VITA. If not, see <http://www.gnu.org/licenses/>.
 *
 */

#include "kernel/gene.h"
#include "kernel/random.h"
#include "kernel/symbol.h"

namespace vita
{
  ///
  /// \param[in] sset the set of symbols used to build individuals.
  ///
  gene::gene(const symbol_set &sset)
  {
    sym = sset.roulette(true);

    if (sym->parametric())
      par = sym->init();
  }

  ///
  /// \param[in] sset the set of symbols used to build individuals.
  /// \param[in] from minimum index for function arguments.
  /// \param[in] sup upper bound for the indexes of function arguments.
  ///
  gene::gene(const symbol_set &sset, unsigned from, unsigned sup)
  {
    assert(from <= sup);
    sym = sset.roulette(from == sup);

    if (sym->parametric())
      par = sym->init();
    else
    {
      const unsigned argc(sym->argc());
      for (unsigned j(0); j < argc; ++j)
        args[j] = random::between<unsigned>(from, sup);
    }
  }

  ///
  /// \param[in] sset the set of symbols used to build individuals.
  /// \param[in] i index of a special symbol in the \a symbol_set.
  ///
  gene::gene(const symbol_set &sset, unsigned i)
  {
    sym = sset.get_special(i);
    if (sym->parametric())
      par = sym->init();
  }

  ///
  /// \param[in] g second term of comparison.
  /// \return \c true if \c this == \a g
  ///
  bool gene::operator==(const gene &g) const
  {
    if (sym != g.sym)
      return false;

    if (sym->parametric())
      return par == g.par;

    const unsigned n(sym->argc());
    for (unsigned i(0); i < n; ++i)
      if (args[i] != g.args[i])
        return false;

    return true;
  }
}  // namespace vita
<|endoftext|>


<commit_before>#include "types.h"
#include "mmu.h"
#include "kernel.hh"
#include "spinlock.h"
#include "condvar.h"
#include "queue.h"
#include "proc.hh"
#include "fs.h"
#include "file.hh"
#include "cpu.hh"
#include "ilist.hh"
#include "uk/unistd.h"

#define PIPESIZE 512

struct pipe {
  virtual int write(const char *addr, int n) = 0;
  virtual int read(char *addr, int n) = 0;
  virtual int close(int writable) = 0;
  NEW_DELETE_OPS(pipe);
};

struct ordered : pipe {
  struct spinlock lock;
  struct condvar  cv;
  int readopen;   // read fd is still open
  int writeopen;  // write fd is still open
  u32 nread;      // number of bytes read
  u32 nwrite;     // number of bytes written
  char data[PIPESIZE];

  ordered() : readopen(1), writeopen(1), nread(0), nwrite(0) {
    lock = spinlock("pipe", LOCKSTAT_PIPE);
    cv = condvar("pipe");
  };
  ~ordered() {
  };
  NEW_DELETE_OPS(ordered);

  virtual int write(const char *addr, int n) {
    acquire(&lock);
    for(int i = 0; i < n; i++){
      while(nwrite == nread + PIPESIZE){
        if(readopen == 0 || myproc()->killed){
          release(&lock);
          return -1;
        }
        cv.wake_all();
        cv.sleep(&lock);
      }
      data[nwrite++ % PIPESIZE] = addr[i];
    }
    cv.wake_all();
    release(&lock);
    return n;
  }

  virtual int read(char *addr, int n) {
    int i;
    acquire(&lock);
    while(nread == nwrite && writeopen) {
      if(myproc()->killed){
        release(&lock);
        return -1;
      }
      cv.sleep(&lock);
    }
    for(i = 0; i < n; i++) {
      if(nread == nwrite)
        break;
      addr[i] = data[nread++ % PIPESIZE];
    }
    cv.wake_all();
    release(&lock);
    return i;
  }

  virtual int close(int writable) {
    acquire(&lock);
    if(writable){
      writeopen = 0;
    } else {
      readopen = 0;
    }
    cv.wake_all();
    if(readopen == 0 && writeopen == 0){
      release(&lock);
      return 1;
    } else
      release(&lock);
    return 0;
  }
};

// Initial support for unordered pipes by having per-core pipes.  A writer
// writes n bytes as a single unit in its local per-core pipe, from which the
// neighbor is intended to read the n bytes.  If a writer's local pipe is full,
// it sleeps until a reader to wake it up.  A reader cycles through all per-core
// pipes, starting from the next core.  If it reads from a full pipe, it wakes up
// the local writer.  If all pipes are empty, then it keeps trying.
//
// tension between load balance and performance: if there is no need for load
// balance, reader and writer should agree on a given pipe and use only that
// one.
//
// tension between space sharing and time sharing: maybe should read from local
// pipe, maybe should give up cpu when no pipe has data.
//
// XXX shouldn't cpuid has index in pipes because process may be rescheduled.
//
// XXX Should pipe track #readers, #writers?  so that we don't have to allocate
// NCPU per-core pipes.

struct corepipe {
  u32 nread;
  u32 nwrite;
  int readopen;
  char data[PIPESIZE];
  struct spinlock lock;
  struct condvar  cv;
  corepipe() : nread(0), nwrite(0), readopen(1) {
    lock = spinlock("corepipe", LOCKSTAT_PIPE);
    cv = condvar("pipe");
  };
  ~corepipe();
  NEW_DELETE_OPS(corepipe);

  int write(const char *addr, int n, int sleep) {
    int r = -1;
    acquire(&lock);
    while (1) {
      if(readopen == 0 || myproc()->killed)
        break;
      if (nwrite + n < nread + PIPESIZE) {
        for (int i = 0; i < n; i++)
          data[nwrite++ % PIPESIZE] = addr[i];
        r = n;
        break;
      } else if (sleep) {
        cprintf("w");
        cv.sleep(&lock);
      } else {
        break;
      }
    }
    release(&lock);
    return r;
  }

  int read(char *addr, int n) {
    int r = 0;
    acquire(&lock);
    if (nread + n <= nwrite) {
      for(int i = 0; i < n; i++)
        addr[i] = data[nread++ % PIPESIZE];
      r = n;
      cv.wake_all();   // XXX only wakeup when it was full?
    }
    release(&lock);
    return r;
  }
};

struct unordered : pipe {
  corepipe *pipes[NCPU];
  int writeopen;
  unordered() : writeopen(1) {
    for (int i = 0; i < NCPU; i++) {
      pipes[i] = new corepipe();
    }
  };
  ~unordered() {
  };
  NEW_DELETE_OPS(unordered);

  int write(const char *addr, int n) {
    int r;
    corepipe *cp = pipes[(mycpu()->id) % NCPU];
    r = cp->write(addr, n, 1);    // XXX we could try to write in another pipe
    assert (n == r);
    return r;
  };

  int read(char *addr, int n) {
    int r;
    while (1) {
      for (int i = (mycpu()->id + 1) % NCPU; i != mycpu()->id;
           i = (i + 1) % NCPU) {
        r = pipes[i]->read(addr, n);
        if (r == n) return r;
      }
      if (writeopen == 0 || myproc()->killed) return -1;

      // XXX should we give up the CPU at some point?
    }

    return r;
  }

  int close(int writeable) {
    int readopen = 1;
    int r = 0;
    for (int i = 0; i < NCPU; i++) acquire(&pipes[i]->lock);
    if(writeable){
      writeopen = 0;
    } else {
      for (int i = 0; i < NCPU; i++) pipes[i]->readopen = 0;
      readopen = 0;
    }
    for (int i = 0; i < NCPU; i++) pipes[i]->cv.wake_all();
    if(readopen == 0 && writeopen == 0) {
      r = 1;
    }
    for (int i = 0; i < NCPU; i++) release(&pipes[i]->lock);
    return r;
  }
};

int
pipealloc(struct file **f0, struct file **f1, int flag)
{
  struct pipe *p;

  p = 0;
  *f0 = *f1 = 0;
  if((*f0 = file::alloc()) == 0 || (*f1 = file::alloc()) == 0)
    goto bad;
  if (flag & PIPE_UNORDED) {
    p = new unordered();
  } else {
    p = new ordered();
  }
  (*f0)->type = file::FD_PIPE;
  (*f0)->readable = 1;
  (*f0)->writable = 0;
  (*f0)->pipe = p;
  (*f1)->type = file::FD_PIPE;
  (*f1)->readable = 0;
  (*f1)->writable = 1;
  (*f1)->pipe = p;
  return 0;

 bad:
  if(p)
    delete p;
  if(*f0)
    (*f0)->dec();
  if(*f1)
    (*f1)->dec();
  return -1;
}

void
pipeclose(struct pipe *p, int writable)
{
  if (p->close(writable))
    delete p;
}

int
pipewrite(struct pipe *p, const char *addr, int n)
{
  return p->write(addr, n);
}

int
piperead(struct pipe *p, char *addr, int n)
{
  return p->read(addr, n);
}
<commit_msg>pipe: pipe base class needs a virtual destructor<commit_after>#include "types.h"
#include "mmu.h"
#include "kernel.hh"
#include "spinlock.h"
#include "condvar.h"
#include "queue.h"
#include "proc.hh"
#include "fs.h"
#include "file.hh"
#include "cpu.hh"
#include "ilist.hh"
#include "uk/unistd.h"

#define PIPESIZE 512

struct pipe {
  virtual ~pipe() { };
  virtual int write(const char *addr, int n) = 0;
  virtual int read(char *addr, int n) = 0;
  virtual int close(int writable) = 0;
  NEW_DELETE_OPS(pipe);
};

struct ordered : pipe {
  struct spinlock lock;
  struct condvar  cv;
  int readopen;   // read fd is still open
  int writeopen;  // write fd is still open
  u32 nread;      // number of bytes read
  u32 nwrite;     // number of bytes written
  char data[PIPESIZE];

  ordered() : readopen(1), writeopen(1), nread(0), nwrite(0) {
    lock = spinlock("pipe", LOCKSTAT_PIPE);
    cv = condvar("pipe");
  };
  ~ordered() {
  };
  NEW_DELETE_OPS(ordered);

  virtual int write(const char *addr, int n) {
    acquire(&lock);
    for(int i = 0; i < n; i++){
      while(nwrite == nread + PIPESIZE){
        if(readopen == 0 || myproc()->killed){
          release(&lock);
          return -1;
        }
        cv.wake_all();
        cv.sleep(&lock);
      }
      data[nwrite++ % PIPESIZE] = addr[i];
    }
    cv.wake_all();
    release(&lock);
    return n;
  }

  virtual int read(char *addr, int n) {
    int i;
    acquire(&lock);
    while(nread == nwrite && writeopen) {
      if(myproc()->killed){
        release(&lock);
        return -1;
      }
      cv.sleep(&lock);
    }
    for(i = 0; i < n; i++) {
      if(nread == nwrite)
        break;
      addr[i] = data[nread++ % PIPESIZE];
    }
    cv.wake_all();
    release(&lock);
    return i;
  }

  virtual int close(int writable) {
    acquire(&lock);
    if(writable){
      writeopen = 0;
    } else {
      readopen = 0;
    }
    cv.wake_all();
    if(readopen == 0 && writeopen == 0){
      release(&lock);
      return 1;
    } else
      release(&lock);
    return 0;
  }
};

// Initial support for unordered pipes by having per-core pipes.  A writer
// writes n bytes as a single unit in its local per-core pipe, from which the
// neighbor is intended to read the n bytes.  If a writer's local pipe is full,
// it sleeps until a reader to wake it up.  A reader cycles through all per-core
// pipes, starting from the next core.  If it reads from a full pipe, it wakes up
// the local writer.  If all pipes are empty, then it keeps trying.
//
// tension between load balance and performance: if there is no need for load
// balance, reader and writer should agree on a given pipe and use only that
// one.
//
// tension between space sharing and time sharing: maybe should read from local
// pipe, maybe should give up cpu when no pipe has data.
//
// XXX shouldn't cpuid has index in pipes because process may be rescheduled.
//
// XXX Should pipe track #readers, #writers?  so that we don't have to allocate
// NCPU per-core pipes.

struct corepipe {
  u32 nread;
  u32 nwrite;
  int readopen;
  char data[PIPESIZE];
  struct spinlock lock;
  struct condvar  cv;
  corepipe() : nread(0), nwrite(0), readopen(1) {
    lock = spinlock("corepipe", LOCKSTAT_PIPE);
    cv = condvar("pipe");
  };
  ~corepipe();
  NEW_DELETE_OPS(corepipe);

  int write(const char *addr, int n, int sleep) {
    int r = -1;
    acquire(&lock);
    while (1) {
      if(readopen == 0 || myproc()->killed)
        break;
      if (nwrite + n < nread + PIPESIZE) {
        for (int i = 0; i < n; i++)
          data[nwrite++ % PIPESIZE] = addr[i];
        r = n;
        break;
      } else if (sleep) {
        cprintf("w");
        cv.sleep(&lock);
      } else {
        break;
      }
    }
    release(&lock);
    return r;
  }

  int read(char *addr, int n) {
    int r = 0;
    acquire(&lock);
    if (nread + n <= nwrite) {
      for(int i = 0; i < n; i++)
        addr[i] = data[nread++ % PIPESIZE];
      r = n;
      cv.wake_all();   // XXX only wakeup when it was full?
    }
    release(&lock);
    return r;
  }
};

struct unordered : pipe {
  corepipe *pipes[NCPU];
  int writeopen;
  unordered() : writeopen(1) {
    for (int i = 0; i < NCPU; i++) {
      pipes[i] = new corepipe();
    }
  };
  ~unordered() {
  };
  NEW_DELETE_OPS(unordered);

  int write(const char *addr, int n) {
    int r;
    corepipe *cp = pipes[(mycpu()->id) % NCPU];
    r = cp->write(addr, n, 1);    // XXX we could try to write in another pipe
    assert (n == r);
    return r;
  };

  int read(char *addr, int n) {
    int r;
    while (1) {
      for (int i = (mycpu()->id + 1) % NCPU; i != mycpu()->id;
           i = (i + 1) % NCPU) {
        r = pipes[i]->read(addr, n);
        if (r == n) return r;
      }
      if (writeopen == 0 || myproc()->killed) return -1;

      // XXX should we give up the CPU at some point?
    }

    return r;
  }

  int close(int writeable) {
    int readopen = 1;
    int r = 0;
    for (int i = 0; i < NCPU; i++) acquire(&pipes[i]->lock);
    if(writeable){
      writeopen = 0;
    } else {
      for (int i = 0; i < NCPU; i++) pipes[i]->readopen = 0;
      readopen = 0;
    }
    for (int i = 0; i < NCPU; i++) pipes[i]->cv.wake_all();
    if(readopen == 0 && writeopen == 0) {
      r = 1;
    }
    for (int i = 0; i < NCPU; i++) release(&pipes[i]->lock);
    return r;
  }
};

int
pipealloc(struct file **f0, struct file **f1, int flag)
{
  struct pipe *p;

  p = 0;
  *f0 = *f1 = 0;
  if((*f0 = file::alloc()) == 0 || (*f1 = file::alloc()) == 0)
    goto bad;
  if (flag & PIPE_UNORDED) {
    p = new unordered();
  } else {
    p = new ordered();
  }
  (*f0)->type = file::FD_PIPE;
  (*f0)->readable = 1;
  (*f0)->writable = 0;
  (*f0)->pipe = p;
  (*f1)->type = file::FD_PIPE;
  (*f1)->readable = 0;
  (*f1)->writable = 1;
  (*f1)->pipe = p;
  return 0;

 bad:
  if(p)
    delete p;
  if(*f0)
    (*f0)->dec();
  if(*f1)
    (*f1)->dec();
  return -1;
}

void
pipeclose(struct pipe *p, int writable)
{
  if (p->close(writable))
    delete p;
}

int
pipewrite(struct pipe *p, const char *addr, int n)
{
  return p->write(addr, n);
}

int
piperead(struct pipe *p, char *addr, int n)
{
  return p->read(addr, n);
}
<|endoftext|>


<commit_before>class {{class_symbol}} : public Select<{{consume_type}}, {{produce_type}}> {
    using Select<{{produce_type}}, {{produce_type}}::Select;
    protected:
        bool predicate({{produce_type}} {{consume_tuple_name}}) {
            return {{expression}}
        }
};<commit_msg>typo template<commit_after>class {{class_symbol}} : public Select<{{consume_type}}, {{produce_type}}> {
    using Select<{{produce_type}}, {{produce_type}}>::Select;
    protected:
        bool predicate({{produce_type}} {{consume_tuple_name}}) {
            return {{expression}}
        }
};<|endoftext|>