예제 #1
0
bool polygon_ctrl_impl::check_edge(unsigned i, double x, double y) const {
  bool ret = false;

  unsigned n1 = i;
  unsigned n2 = (i + m_num_points - 1) % m_num_points;
  double x1 = xn(n1);
  double y1 = yn(n1);
  double x2 = xn(n2);
  double y2 = yn(n2);

  double dx = x2 - x1;
  double dy = y2 - y1;

  if (sqrt(dx * dx + dy * dy) > 0.0000001) {
    double x3 = x;
    double y3 = y;
    double x4 = x3 - dy;
    double y4 = y3 + dx;

    double den = (y4 - y3) * (x2 - x1) - (x4 - x3) * (y2 - y1);
    double u1 = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / den;

    double xi = x1 + u1 * (x2 - x1);
    double yi = y1 + u1 * (y2 - y1);

    dx = xi - x;
    dy = yi - y;

    if (u1 > 0.0 && u1 < 1.0 && sqrt(dx * dx + dy * dy) <= m_point_radius) {
      ret = true;
    }
  }
  return ret;
}
예제 #2
0
 unsigned polygon_ctrl_impl::vertex(double* x, double* y)
 {
     unsigned cmd = path_cmd_stop;
     double r = m_point_radius;
     if(m_status == 0)
     {
         cmd = m_stroke.vertex(x, y);
         if(!is_stop(cmd)) 
         {
             transform_xy(x, y);
             return cmd;
         }
         if(m_node >= 0 && m_node == int(m_status)) r *= 1.2;
         m_ellipse.init(xn(m_status), yn(m_status), r, r, 32);
         ++m_status;
     }
     cmd = m_ellipse.vertex(x, y);
     if(!is_stop(cmd)) 
     {
         transform_xy(x, y);
         return cmd;
     }
     if(m_status >= m_num_points) return path_cmd_stop;
     if(m_node >= 0 && m_node == int(m_status)) r *= 1.2;
     m_ellipse.init(xn(m_status), yn(m_status), r, r, 32);
     ++m_status;
     cmd = m_ellipse.vertex(x, y);
     if(!is_stop(cmd)) 
     {
         transform_xy(x, y);
     }
     return cmd;
 }
예제 #3
0
    //======= Crossings Multiply algorithm of InsideTest ======================== 
    //
    // By Eric Haines, 3D/Eye Inc, [email protected]
    //
    // This version is usually somewhat faster than the original published in
    // Graphics Gems IV; by turning the division for testing the X axis crossing
    // into a tricky multiplication test this part of the test became faster,
    // which had the additional effect of making the test for "both to left or
    // both to right" a bit slower for triangles than simply computing the
    // intersection each time.  The main increase is in triangle testing speed,
    // which was about 15% faster; all other polygon complexities were pretty much
    // the same as before.  On machines where division is very expensive (not the
    // case on the HP 9000 series on which I tested) this test should be much
    // faster overall than the old code.  Your mileage may (in fact, will) vary,
    // depending on the machine and the test data, but in general I believe this
    // code is both shorter and faster.  This test was inspired by unpublished
    // Graphics Gems submitted by Joseph Samosky and Mark Haigh-Hutchinson.
    // Related work by Samosky is in:
    //
    // Samosky, Joseph, "SectionView: A system for interactively specifying and
    // visualizing sections through three-dimensional medical image data",
    // M.S. Thesis, Department of Electrical Engineering and Computer Science,
    // Massachusetts Institute of Technology, 1993.
    //
    // Shoot a test ray along +X axis.  The strategy is to compare vertex Y values
    // to the testing point's Y and quickly discard edges which are entirely to one
    // side of the test ray.  Note that CONVEX and WINDING code can be added as
    // for the CrossingsTest() code; it is left out here for clarity.
    //
    // Input 2D polygon _pgon_ with _numverts_ number of vertices and test point
    // _point_, returns 1 if inside, 0 if outside.
    bool polygon_ctrl_impl::point_in_polygon(double tx, double ty) const
    {
        if(m_num_points < 3) return false;
        if(!m_in_polygon_check) return false;

        unsigned j;
        int yflag0, yflag1, inside_flag;
        double  vtx0, vty0, vtx1, vty1;

        vtx0 = xn(m_num_points - 1);
        vty0 = yn(m_num_points - 1);

        // get test bit for above/below X axis
        yflag0 = (vty0 >= ty);

        vtx1 = xn(0);
        vty1 = yn(0);

        inside_flag = 0;
        for (j = 1; j <= m_num_points; ++j) 
        {
            yflag1 = (vty1 >= ty);
            // Check if endpoints straddle (are on opposite sides) of X axis
            // (i.e. the Y's differ); if so, +X ray could intersect this edge.
            // The old test also checked whether the endpoints are both to the
            // right or to the left of the test point.  However, given the faster
            // intersection point computation used below, this test was found to
            // be a break-even proposition for most polygons and a loser for
            // triangles (where 50% or more of the edges which survive this test
            // will cross quadrants and so have to have the X intersection computed
            // anyway).  I credit Joseph Samosky with inspiring me to try dropping
            // the "both left or both right" part of my code.
            if (yflag0 != yflag1) 
            {
                // Check intersection of pgon segment with +X ray.
                // Note if >= point's X; if so, the ray hits it.
                // The division operation is avoided for the ">=" test by checking
                // the sign of the first vertex wrto the test point; idea inspired
                // by Joseph Samosky's and Mark Haigh-Hutchinson's different
                // polygon inclusion tests.
                if ( ((vty1-ty) * (vtx0-vtx1) >=
                      (vtx1-tx) * (vty0-vty1)) == yflag1 ) 
                {
                    inside_flag ^= 1;
                }
            }

            // Move to the next pair of vertices, retaining info as possible.
            yflag0 = yflag1;
            vtx0 = vtx1;
            vty0 = vty1;

            unsigned k = (j >= m_num_points) ? j - m_num_points : j;
            vtx1 = xn(k);
            vty1 = yn(k);
        }
        return inside_flag != 0;
    }
예제 #4
0
 bool polygon_ctrl_impl::on_mouse_move(double x, double y, bool button_flag)
 {
     bool ret = false;
     double dx;
     double dy;
     inverse_transform_xy(&x, &y);
     if(m_node == int(m_num_points))
     {
         dx = x - m_dx;
         dy = y - m_dy;
         unsigned i;
         for(i = 0; i < m_num_points; i++)
         {
             xn(i) += dx;
             yn(i) += dy;
         }
         m_dx = x;
         m_dy = y;
         ret = true;
     }
     else
     {
         if(m_edge >= 0)
         {
             unsigned n1 = m_edge;
             unsigned n2 = (n1 + m_num_points - 1) % m_num_points;
             dx = x - m_dx;
             dy = y - m_dy;
             xn(n1) += dx;
             yn(n1) += dy;
             xn(n2) += dx;
             yn(n2) += dy;
             m_dx = x;
             m_dy = y;
             ret = true;
         }
         else
         {
             if(m_node >= 0)
             {
                 xn(m_node) = x - m_dx;
                 yn(m_node) = y - m_dy;
                 ret = true;
             }
         }
     }
     return ret;
 }
예제 #5
0
void dampnewton(const FuncType &F, const JacType &DF,
                Eigen::VectorXd &x, double rtol = 1e-4,double atol = 1e-6)
{
    const int n = x.size();
    const double lmin = 1E-3; // Minimal damping factor
    double lambda = 1.0; // Initial and actual damping factor
    Eigen::VectorXd s(n),st(n); // Newton corrections
    Eigen::VectorXd xn(n);      // Tentative new iterate
    double sn,stn;    // Norms of Newton corrections
    
    do {
        auto jacfac = DF(x).lu(); // LU-factorize Jacobian
        
        s = jacfac.solve(F(x));   // Newton correction
        sn = s.norm();            // Norm of Newton correction
        lambda *= 2.0;
        do {
            lambda /= 2;
            if (lambda < lmin) throw "No convergence: lambda -> 0";
            xn = x-lambda*s;           // {\bf Tentative next iterate}
            st = jacfac.solve(F(xn));  // Simplified Newton correction
            stn = st.norm();
        }
        while (stn > (1-lambda/2)*sn); // {\bf Natural monotonicity test}
        x = xn; // Now: xn accepted as new iterate
        lambda = std::min(2.0*lambda,1.0); // Try to mitigate damping
    }
    // Termination based on simplified Newton correction
    while ((stn > rtol*x.norm()) && (stn > atol));
}
예제 #6
0
파일: main.c 프로젝트: xkovacikm2/SPP2
// ukazkovy test
int main(void)
{
  int i;
  for (i = 0; i < 32; i++)
    printf("2^%d = %lf\n", i, xn(2.0, i));
  return 0;
}
예제 #7
0
파일: Polyhedra.cpp 프로젝트: mew-cx/osgtoy
osgToy::OctoStrip::OctoStrip()
{
    osg::Vec3Array* vAry = dynamic_cast<osg::Vec3Array*>( getVertexArray() );

    osg::Vec3Array* nAry = dynamic_cast<osg::Vec3Array*>( getNormalArray() );
    setNormalBinding( osg::Geometry::BIND_PER_VERTEX );

    osg::Vec4Array* cAry = dynamic_cast<osg::Vec4Array*>( getColorArray() );
    setColorBinding( osg::Geometry::BIND_PER_VERTEX );

    osg::Vec3 xp( 1, 0, 0);   osg::Vec4 red(1,0,0,1);
    osg::Vec3 xn(-1, 0, 0);   osg::Vec4 cyan(0,1,1,1);
    osg::Vec3 yp( 0, 1, 0);   osg::Vec4 green(0,1,0,1);
    osg::Vec3 yn( 0,-1, 0);   osg::Vec4 magenta(1,0,1,1);
    osg::Vec3 zp( 0, 0, 1);   osg::Vec4 blue(0,0,1,1);
    osg::Vec3 zn( 0, 0,-1);   osg::Vec4 yellow(1,1,0,1);

    vAry->push_back(zp); nAry->push_back(zp); cAry->push_back(blue);
    vAry->push_back(yp); nAry->push_back(yp); cAry->push_back(green);
    vAry->push_back(xn); nAry->push_back(xn); cAry->push_back(cyan);
    vAry->push_back(zn); nAry->push_back(zn); cAry->push_back(yellow);
    vAry->push_back(yn); nAry->push_back(yn); cAry->push_back(magenta);
    vAry->push_back(xp); nAry->push_back(xp); cAry->push_back(red);
    vAry->push_back(zp); nAry->push_back(zp); cAry->push_back(blue);
    vAry->push_back(yp); nAry->push_back(yp); cAry->push_back(green);

    addPrimitiveSet( new osg::DrawArrays( GL_TRIANGLE_STRIP, 0, vAry->size() ) );
}
예제 #8
0
 bool interactive_polygon::on_mouse_move(double x, double y)
 {
     bool ret = false;
     double dx;
     double dy;
     if(m_node == int(m_num_points))
     {
         dx = x - m_dx;
         dy = y - m_dy;
         unsigned i;
         for(i = 0; i < m_num_points; i++)
         {
             xn(i) += dx;
             yn(i) += dy;
         }
         m_dx = x;
         m_dy = y;
         ret = true;
     }
     else
     {
         if(m_edge >= 0)
         {
             unsigned n1 = m_edge;
             unsigned n2 = (n1 + m_num_points - 1) % m_num_points;
             dx = x - m_dx;
             dy = y - m_dy;
             xn(n1) += dx;
             yn(n1) += dy;
             xn(n2) += dx;
             yn(n2) += dy;
             m_dx = x;
             m_dy = y;
             ret = true;
         }
         else
         {
             if(m_node >= 0)
             {
                 xn(m_node) = x - m_dx;
                 yn(m_node) = y - m_dy;
                 ret = true;
             }
         }
     }
     return ret;
 }
예제 #9
0
    bool polygon_ctrl_impl::on_mouse_button_down(double x, double y)
    {
        unsigned i;
        bool ret = false;
        m_node = -1;
        m_edge = -1;
        inverse_transform_xy(&x, &y);
        for (i = 0; i < m_num_points; i++)
        {
            if(sqrt( (x-xn(i)) * (x-xn(i)) + (y-yn(i)) * (y-yn(i)) ) < m_point_radius)
            {
                m_dx = x - xn(i);
                m_dy = y - yn(i);
                m_node = int(i);
                ret = true;
                break;
            }
        }

        if(!ret)
        {
            for (i = 0; i < m_num_points; i++)
            {
                if(check_edge(i, x, y))
                {
                    m_dx = x;
                    m_dy = y;
                    m_edge = int(i);
                    ret = true;
                    break;
                }
            }
        }

        if(!ret)
        {
            if(point_in_polygon(x, y))
            {
                m_dx = x;
                m_dy = y;
                m_node = int(m_num_points);
                ret = true;
            }
        }
        return ret;
    }
예제 #10
0
 unsigned interactive_polygon::vertex(double* x, double* y)
 {
     unsigned cmd = path_cmd_stop;
     double r = m_point_radius;
     if(m_status == 0)
     {
         cmd = m_stroke.vertex(x, y);
         if(!is_stop(cmd)) return cmd;
         if(m_node >= 0 && m_node == int(m_status)) r *= 1.2;
         m_ellipse.init(xn(m_status), yn(m_status), r, r, 32);
         ++m_status;
     }
     cmd = m_ellipse.vertex(x, y);
     if(!is_stop(cmd)) return cmd;
     if(m_status >= m_num_points) return path_cmd_stop;
     if(m_node >= 0 && m_node == int(m_status)) r *= 1.2;
     m_ellipse.init(xn(m_status), yn(m_status), r, r, 32);
     ++m_status;
     return m_ellipse.vertex(x, y);
 }
예제 #11
0
void rlMain::addToStateVector(int& destino,int origem, int mudanca)
{
	State x(StateVector[origem].currentState, mudanca);
	int temp = returnIndexOfMatch(x);

	if (temp == -1){
		temp = ++destino;
		StateNode xn(x);
		StateVector[temp] = xn;
	}
	StateVector[origem].children[mudanca] = temp;
}
예제 #12
0
    bool polygon_ctrl_impl::check_edge(unsigned i, real x, real y) const
    {
       bool ret = false;

       unsigned n1 = i;
       unsigned n2 = (i + m_num_points - 1) % m_num_points;
       real x1 = xn(n1);
       real y1 = yn(n1);
       real x2 = xn(n2);
       real y2 = yn(n2);

       real dx = x2 - x1;
       real dy = y2 - y1;

       if(SQRT(dx*dx + dy*dy) > 0.0000001)
       {
          real x3 = x;
          real y3 = y;
          real x4 = x3 - dy;
          real y4 = y3 + dx;

          real den = (y4-y3) * (x2-x1) - (x4-x3) * (y2-y1);
          real u1 = ((x4-x3) * (y1-y3) - (y4-y3) * (x1-x3)) / den;

          real xi = x1 + u1 * (x2 - x1);
          real yi = y1 + u1 * (y2 - y1);

          dx = xi - x;
          dy = yi - y;

          if (u1 > 0.0f && u1 < 1.0f && SQRT(dx*dx + dy*dy) <= m_point_radius)
          {
             ret = true;
          }
       }
       return ret;
    }
예제 #13
0
파일: problem.hpp 프로젝트: 0x0all/nanocv
                        // implementation: approximate gradient (if no analytic gradient provided)
                        void eval_grad(const tvector& x, tvector& g) const
                        {
                                // accuracy epsilon as defined in:
                                //      see "Numerical optimization", Nocedal & Wright, 2nd edition, p.197
                                const tscalar dx = std::cbrt(tscalar(10) * std::numeric_limits<tscalar>::epsilon());

                                const tsize n = size();

                                tvector xp = x, xn = x;

                                g.resize(n);
                                for (tsize i = 0; i < n; i ++)
                                {
                                        if (i > 0)
                                        {
                                                xp(i - 1) -= dx;
                                                xn(i - 1) += dx;
                                        }
                                        xp(i) += dx;
                                        xn(i) -= dx;

                                        g(i) = (m_op_fval(xp) - m_op_fval(xn)) / (xp(i) - xn(i));
                                }
                        }
예제 #14
0
파일: Polyhedra.cpp 프로젝트: mew-cx/osgtoy
osgToy::RhombicDodecahedron::RhombicDodecahedron()
{
    setOverallColor( osg::Vec4(0,1,0,1) );

    osg::Vec3 a0(  1,  1,  1 );
    osg::Vec3 a1(  1,  1, -1 );
    osg::Vec3 a2(  1, -1,  1 );
    osg::Vec3 a3(  1, -1, -1 );
    osg::Vec3 a4( -1,  1,  1 );
    osg::Vec3 a5( -1,  1, -1 );
    osg::Vec3 a6( -1, -1,  1 );
    osg::Vec3 a7( -1, -1, -1 );

    osg::Vec3 xp(  2,  0,  0 );
    osg::Vec3 xn( -2,  0,  0 );
    osg::Vec3 yp(  0,  2,  0 );
    osg::Vec3 yn(  0, -2,  0 );
    osg::Vec3 zp(  0,  0,  2 );
    osg::Vec3 zn(  0,  0, -2 );

    addTristrip( yp, a0, a1, xp );
    addTristrip( xp, a2, a3, yn );
    addTristrip( yn, a6, a7, xn );
    addTristrip( xn, a4, a5, yp );

    addTristrip( zp, a0, a4, yp );
    addTristrip( yp, a1, a5, zn );
    addTristrip( zn, a3, a7, yn );
    addTristrip( yn, a2, a6, zp );

    addTristrip( xp, a0, a2, zp );
    addTristrip( zp, a4, a6, xn );
    addTristrip( xn, a5, a7, zn );
    addTristrip( zn, a1, a3, xp );

    osgToy::FacetingVisitor::facet( *this );
}
예제 #15
0
void Strand2dFCBlockSolver::rhsSource(const int& j)
{
  // gradients of qa in n-direction and s-direction
  int j1,nj,nm;
  double dnr=1./deltaN;
  Array2D<double> qan(nSurfNode,nqa);
  Array3D<double> qas(nSurfElem,meshOrder+1,nqa);
  Array3D<double> ss(nSurfElem,meshOrder+1,nq);
  qan.set(0.);
  for (int n=0; n<nSurfNode; n++){
    j1 = icn2[j][0];
    nj = icn2[j][1];
    for (int m=0; m<nj; m++){
      for (int k=0; k<nqa; k++)
	qan(n,k) += dnr*icn1[j][m]*qa(n,j1,k);
      j1++;
    }}
  qas.set(0.);
  for (int n=0; n<nSurfElem; n++)
    for (int i=0; i<meshOrder+1; i++) // ith point in the element
      for (int m=0; m<meshOrder+1; m++){ // mth Lagrange poly. in mapping
	nm = surfElem(n,m);
	for (int k=0; k<nqa; k++)
	  qas(n,i,k) += ls(i,m)*qa(nm,j,k);
      }


  // source computation
  int ni;
  double jac1,xs1,ys1,xn1,yn1,qax[nqa],qay[nqa],f[nq];
  for (int n=0; n<nSurfElem; n++)
    for (int i=0; i<meshOrder+1; i++){
      ni   = surfElem(n,i);
      jac1 = 1./jac(n,i,j);
      xs1  = xs(n,i,j)*jac1;
      ys1  = ys(n,i,j)*jac1;
      xn1  = xn(ni,j)*jac1;
      yn1  = yn(ni,j)*jac1;
      for (int k=0; k<nqa; k++){
	qax[k] = yn1*qas(n,i,k)-ys1*qan(ni,k);
	qay[k] =-xn1*qas(n,i,k)+xs1*qan(ni,k);
      }
      sys->rhsSource(1,&q(ni,j,0),&qa(ni,j,0),&qax[0],&qay[0],&f[0]);
      for (int k=0; k<nq; k++) ss(n,i,k) =-f[k]/jac1;
    }


  // source treatment
  int ne;
  double ns;
  for (int n=0; n<nSurfNode; n++)
    for (int i=psp2S(n); i<psp2S(n+1); i++){
      ne = psp1S(i,0);
      ni = psp1S(i,1);
      ns = wsp1S(i);
      for (int k=0; k<nq; k++) r(n,j,k) += ns*ss(ne,ni,k);
    }


  // clean up
  qan.deallocate();
  qas.deallocate();
  ss.deallocate();
}
예제 #16
0
//"рисует" одну линию поля из начальной точки PointB 
//с помощью функций работающих с Z-буфером
void LineField(HDC hdc,POINT3 PointB,COLORREF rgb, double force)
{

	VECTORS vect;	
	vect.x = PointB.x;
	vect.y = PointB.y;
	vect.z = PointB.z;
	
	//видовые координаты проецируемой точки
	double xe, ye, ze1, ze2;
	//координаты пикселов
	int x1,y1,x2,y2;

	double dt = force > 0 ? 0.1 : -0.1; //длина шага на линии поля
	double x, y, z, Hx, Hy, Hz, Ha;
	int k = 0;

	VECMAG mag;
	int step = 0;
	double xt1,yt1,zt1,xt2,yt2,zt2;
	do
	{
		step++;
		x = vect.x;
		y = vect.y;
		z = vect.z;

		mag = magn(x,y,z);

		Hx = mag.hx;
		Hy = mag.hy;
		Hz = mag.hz;

		Ha = sqrt(Hx*Hx + Hy*Hy + Hz*Hz);
		vect.dx = Hx/Ha;
		vect.dy = Hy/Ha;
		vect.dz = Hz/Ha;

		xt1 = vect.x; yt1 = vect.y; zt1 = vect.z;
		xt2 = xt1 + vect.dx*dt;
		yt2 = yt1 + vect.dy*dt;
		zt2 = zt1 + vect.dz*dt;

		xe = Xe(xt1, yt1, zt1);
		ye=Ye(xt1,yt1,zt1);
		ze1=Ze(xt1,yt1,zt1);
		x1=xn(xe);
		y1=ym(ye);

		xe = Xe(xt2, yt2, zt1);
		ye=Ye(xt2,yt2,zt2);
		ze2=Ze(xt2,yt2,zt2);
		x2=xn(xe);
		y2=ym(ye);

		//"рисуем" отрезок линии поля 
		ZbufLineWidth(hdc,x1,y1,x2,y2,ze1,ze2,3,rgb);

		vect.x = xt2;
		vect.y = yt2;
		vect.z = zt2;

		//после 10-и шагов на лини поля "рисуем" стрелку
		k++;
		if(k == 10)
		{
			arrowVector(hdc,x1,y1,x2,y2,ze2,RGB(0,0,255));
			k = 0;
		}

	//прекращаем рисовать линию поля на границе куба
	} while (step < 1000 && (x>-xmax) && (x<xmax) && (y>-ymax) && (y<ymax) && (z>-zmax) && (z<zmax));
}
예제 #17
0
//рисуем картину приложения
void LinePicture(HWND hwnd, int Context)
{
//выбираем нужный контектс устройства для экрана
//---------------------------------------------
	HDC hdcWin;
	PAINTSTRUCT ps;
	//получаем контест устройства для экрана
	if(Context == 1)
		hdcWin = BeginPaint(hwnd, &ps);
	else
		hdcWin = GetDC(hwnd);
//-----------------------------------------------


//связываем размеры поля вывода с размерами клиентской области окна
//--------------------------------------------------------------------
	RECT rct;
	GetClientRect(hwnd,&rct);

	ne1 = rct.left+50; ne2 = rct.right -50;
	me1 = rct.bottom -50; me2 = rct.top + 50;
//------------------------------------------------------------------

//создаем контекст экрана
//------------------------------------------------------------
	HDC hdc = CreateCompatibleDC(hdcWin); //создаем контекст
                     //памяти связаный с контекстом экрана

   //памяти надо придать вид экрана - подходт битовая карта с форматом
   // как у экрана. В памяти будем рисовать на битовой карте
	HBITMAP hBitmap, hBitmapOld;
	hBitmap = CreateCompatibleBitmap(hdcWin, ne2, me1); //создаем
               //битовую карту совместмую с контекстом экрана
	hBitmapOld = (HBITMAP)SelectObject(hdc, hBitmap); //помещаем
                // битовую карту в контекст памяти
//--------------------------------------------------------------
	

//выводи значения углов в верхней части поля вывода
//--------------------------------------------------------	
	//создание прямоугольной области для вывода углов поворота
	HRGN hrgn2 = CreateRectRgn(ne1,me2-30,ne2,me1);

	//заливаем выделенную область серым цветом
	HBRUSH hBrush2 = CreateSolidBrush(RGB(0x80,0x80,0x80));
	HBRUSH hBrushOld = (HBRUSH)SelectObject(hdc,hBrush2); 
    FillRgn(hdc,hrgn2,hBrush2);

	SelectObject(hdc,hBrushOld);   
	DeleteObject(hBrush2);         
	DeleteObject(hrgn2);         

	
	//вычисление угловых коэффициентов поворота системы координат
	sf=sin(M_PI*angl.fi/180);
	cf=cos(M_PI*angl.fi/180);
	st=sin(M_PI*angl.teta/180);
	ct=cos(M_PI*angl.teta/180);


	//информация об углах поворота системы координат
	TCHAR ss[20];
	SetBkColor(hdc,RGB(0xC0,0xC0,0xC0));
	SetTextColor(hdc,RGB(0,0,0x80));
	swprintf_s(ss,20,L"fi = %4.0lf",angl.fi);
	TextOut(hdc,(ne1+ne2)/2-80,me2-25,ss,9);
	swprintf_s(ss,20,L"teta = %4.0lf",angl.teta);
	TextOut(hdc,(ne1+ne2)/2+20,me2-25,ss,11);
//------------------------------------------------

	
	


//выделение памяти под Z-буфер и начальное его заполнение
//-------------------------------------------------------------
	//вычисляем число пикселей в поле  вывода
	Np = ne2-ne1 + 1, Mp = me1-me2 +1, NM = Np*Mp;

	//выделяем память под Z-буфер для каждого пикселя
	zb = new ZbuffS [NM];

	//начальное заполнение z-буфера для каждого пикселя
	for ( long unsigned p=0; p<NM; p++)
	{
   		zb[p].z = -1000;
   		zb[p].c.R = 0xC0; zb[p].c.G = 0xC0; zb[p].c.B = 0xC0;
	}
//-----------------------------------------------------------

	

//"рисуем" магнитную пластинку заданным цветом заполняя Z-буфер	
//-----------------------------------------------------------------------
	//мировые координаты проецируемой точки
	double xt1,yt1,zt1;
	//видовые координаты проецируемой точки
	double xe,ye,ze1;
	//пиксельные координаты проецируемой точки
	int x1,y1;

	//пиксельные координаты 4-х углов пластинки
	int xp[4], yp[4];
	//видовые z-координаты 4-х углов пластинки
	double ze[4];

	for(int n=0; n<4; n++)
	{
		xt1 = Px[n]; yt1 = Py[n]; zt1 = Pz[n];
		xe = Xe(xt1, yt1, zt1);
		ye=Ye(xt1,yt1,zt1);
		ze1=Ze(xt1,yt1,zt1);
		x1=xn(xe);
		y1=ym(ye);
		xp[n] = x1; yp[n] = y1; ze[n] = ze1;
	}	
	//ZbufParallelogram(hdc,xp[0],yp[0],ze[0],xp[1],yp[1],ze[1],
		//xp[2],yp[2],ze[2],xp[3],yp[3],ze[3],RGB(255,255,0));
//------------------------------------------------------------------



//"рисуем" линии поля заполняя Z-буфер
//----------------------------------------------------------------
	for (int i = 0; i < 20; i++)
	{
		LineField(hdc,PointB[i],RGB(255,0,0),1);
		
	}
	
	for(int i=20; i<40; i++)
	{
		LineField(hdc,PointB[i],RGB(0,0,255), 1);
		
	}

	for (int i = 40; i<60; i++)
	{
		LineField(hdc, PointB[i], RGB(0, 255,0), 1);

	}
	
//-----------------------------------------------------------------------


//выводим содержимое Z-буфера в контекст памяти
//--------------------------------------------------------------------
	//двигаемся по всем пикселям окна вывода
	for (unsigned long ij=0; ij<NM; ij++)
	{
   		x1 = ne1 + ij%Np;
		y1 = me2 + ij/Np;
		SetPixel(hdc,x1,y1,RGB(zb[ij].c.R,zb[ij].c.G,zb[ij].c.B));

	}

	delete [] zb; //очищаем память под Z-буфером
//-------------------------------------------------------------



//рисуем координтные оси
//------------------------------------------------------------------------

	HPEN hPen = CreatePen(PS_SOLID,1,RGB(0,255,255));
	HPEN hPenOld = (HPEN)SelectObject(hdc,hPen);    
	
	int x2,y2;

//ось Ox
	xe=Xe(-xmax/3,0,0);
	ye=Ye(-xmax/3,0,0);
	x1=xn(xe);
	y1=ym(ye);
	xe=Xe(xmax,0,0);
	ye=Ye(xmax,0,0);
	x2=xn(xe);
	y2=ym(ye);
	
	MoveToEx(hdc,x1,y1,NULL);
	LineTo(hdc,x2,y2);

	SetBkColor(hdc,RGB(0xC0,0xC0,0xC0));
	SetTextColor(hdc,RGB(120,120,120));
	TextOut(hdc,x2, y2, _T("X"),1);

//Ось Oy
	xe=Xe(0,-ymax/3, 0);
	ye=Ye(0,-ymax/3,0);
	x1=xn(xe);
	y1=ym(ye);
	xe=Xe(0,ymax, 0);
	ye=Ye(0,ymax,0);
	x2=xn(xe);
	y2=ym(ye);
	
	MoveToEx(hdc,x1,y1,NULL);
	LineTo(hdc,x2,y2);

	SetBkColor(hdc,RGB(0xC0,0xC0,0xC0));
	SetTextColor(hdc,RGB(120,120,120));
	TextOut(hdc,x2, y2, _T("Y"),1);

//Ось Oz
	xe=Xe(0,0, 0);
	ye=Ye(0,0,-zmax/3);
	x1=xn(xe);
	y1=ym(ye);
	xe=Xe(0,0, 0);
	ye=Ye(0,0,zmax);
	x2=xn(xe);
	y2=ym(ye);

	MoveToEx(hdc,x1,y1,NULL);
	LineTo(hdc,x2,y2);

	SetBkColor(hdc,RGB(0xC0,0xC0,0xC0));
	SetTextColor(hdc,RGB(120,120,120));
	TextOut(hdc,x2, y2, _T("Z"),1);


	SelectObject(hdc,hPenOld); 
	DeleteObject(hPen);        
//-----------------------------------------------------------------------------


//рисуем куб
//----------------------------------------------------------------------
	hPen = CreatePen(PS_SOLID,1,RGB(160,160,160));
	hPenOld = (HPEN)SelectObject(hdc,hPen);    

	DrawBox(hwnd, hdc, angl);

	SelectObject(hdc,hPenOld); 
	DeleteObject(hPen);        
//------------------------------------------------------------------------


//копируем контекст памяти в контекст экрана
//-----------------------------------------------------------------------	
	BitBlt(hdcWin,ne1,me2-30,ne2,me1,hdc,ne1,me2-30,SRCCOPY); 
//----------------------------------------------------------------------


//завершаем работу с контекстами и памятью
//-------------------------------------------------------------------
	SelectObject(hdc, hBitmapOld); //востанавливаем контекст памяти
	DeleteObject(hBitmap); //убираем битовую карту
	DeleteDC(hdc);  //  освобождаем контекст памяти

	//освобождаем контекст экрана
	if(Context == 1)
		EndPaint(hwnd, &ps);
	else
		ReleaseDC(hwnd, hdcWin);   
}
예제 #18
0
int Sphere::Triangulate(float3 *outPos, float3 *outNormal, float2 *outUV, int numVertices, bool ccwIsFrontFacing) const
{
	assume(outPos);
	assume(numVertices >= 24 && "At minimum, sphere triangulation will contain at least 8 triangles, which is 24 vertices, but fewer were specified!");
	assume(numVertices % 3 == 0 && "Warning:: The size of output should be divisible by 3 (each triangle takes up 3 vertices!)");

#ifndef MATH_ENABLE_INSECURE_OPTIMIZATIONS
	if (!outPos)
		return 0;
#endif
	assume(this->r > 0.f);

	if (numVertices < 24)
		return 0;

#ifdef MATH_ENABLE_STL_SUPPORT
	std::vector<Triangle> temp;
#else
	Array<Triangle> temp;
#endif
	// Start subdividing from a diamond shape.
	float3 xp(r,0,0);
	float3 xn(-r,0,0);
	float3 yp(0,r,0);
	float3 yn(0,-r,0);
	float3 zp(0,0,r);
	float3 zn(0,0,-r);

	if (ccwIsFrontFacing)
	{
		temp.push_back(Triangle(yp,xp,zp));
		temp.push_back(Triangle(xp,yp,zn));
		temp.push_back(Triangle(yn,zp,xp));
		temp.push_back(Triangle(yn,xp,zn));
		temp.push_back(Triangle(zp,xn,yp));
		temp.push_back(Triangle(yp,xn,zn));
		temp.push_back(Triangle(yn,xn,zp));
		temp.push_back(Triangle(xn,yn,zn));
	}
	else
	{
		temp.push_back(Triangle(yp,zp,xp));
		temp.push_back(Triangle(xp,zn,yp));
		temp.push_back(Triangle(yn,xp,zp));
		temp.push_back(Triangle(yn,zn,xp));
		temp.push_back(Triangle(zp,yp,xn));
		temp.push_back(Triangle(yp,zn,xn));
		temp.push_back(Triangle(yn,zp,xn));
		temp.push_back(Triangle(xn,zn,yn));
	}

	int oldEnd = 0;
	while(((int)temp.size()-oldEnd+3)*3 <= numVertices)
	{
		Triangle cur = temp[oldEnd];
		float3 a = ((cur.a + cur.b) * 0.5f).ScaledToLength(this->r);
		float3 b = ((cur.a + cur.c) * 0.5f).ScaledToLength(this->r);
		float3 c = ((cur.b + cur.c) * 0.5f).ScaledToLength(this->r);

		temp.push_back(Triangle(cur.a, a, b));
		temp.push_back(Triangle(cur.b, c, a));
		temp.push_back(Triangle(cur.c, b, c));
		temp.push_back(Triangle(a, c, b));

		++oldEnd;
	}
	// Check that we really did tessellate as many new triangles as possible.
	assert(((int)temp.size()-oldEnd)*3 <= numVertices && ((int)temp.size()-oldEnd)*3 + 9 > numVertices);

	for(size_t i = oldEnd, j = 0; i < temp.size(); ++i, ++j)
	{
		outPos[3*j] = this->pos + temp[i].a;
		outPos[3*j+1] = this->pos + temp[i].b;
		outPos[3*j+2] = this->pos + temp[i].c;
	}

	if (outNormal)
		for(size_t i = oldEnd, j = 0; i < temp.size(); ++i, ++j)
		{
			outNormal[3*j] = temp[i].a.Normalized();
			outNormal[3*j+1] = temp[i].b.Normalized();
			outNormal[3*j+2] = temp[i].c.Normalized();
		}

	if (outUV)
		for(size_t i = oldEnd, j = 0; i < temp.size(); ++i, ++j)
		{
			outUV[3*j] = float2(atan2(temp[i].a.y, temp[i].a.x) / (2.f * 3.141592654f) + 0.5f, (temp[i].a.z + r) / (2.f * r));
			outUV[3*j+1] = float2(atan2(temp[i].b.y, temp[i].b.x) / (2.f * 3.141592654f) + 0.5f, (temp[i].b.z + r) / (2.f * r));
			outUV[3*j+2] = float2(atan2(temp[i].c.y, temp[i].c.x) / (2.f * 3.141592654f) + 0.5f, (temp[i].c.z + r) / (2.f * r));
		}

	return ((int)temp.size() - oldEnd) * 3;
}
예제 #19
0
//рисуем куб, связанный с подвижной системой координат
void DrawBox(HWND hwnd, HDC hdc, ANGLS an)
{
	sf=sin(M_PI*an.fi/180);
	cf=cos(M_PI*an.fi/180);
	st=sin(M_PI*an.teta/180);
	ct=cos(M_PI*an.teta/180);

	double xe, ye;
	int x1,y1,x2,y2;
	double xt1,yt1,zt1,xt2,yt2,zt2;
	int j;

	for(int i=0; i<4; i++)
	{
		j = i + 1;
		if(j==4)
			j = 0;
		xt1 = Point[i].x; yt1 = Point[i].y; zt1 = Point[i].z;
		xt2 = Point[j].x; yt2 = Point[j].y; zt2 = Point[j].z;

		xe = Xe(xt1, yt1, zt1);
		ye=Ye(xt1,yt1,zt1);
		x1=xn(xe);
		y1=ym(ye);

		xe = Xe(xt2, yt2, zt2);
		ye=Ye(xt2,yt2,zt2);
		x2=xn(xe);
		y2=ym(ye);

		MoveToEx(hdc,x1,y1,NULL);
		LineTo(hdc,x2,y2);
	}



	for(int i=4; i<8; i++)
	{
		j = i + 1;
		if(j==8)
			j = 4;
		xt1 = Point[i].x; yt1 = Point[i].y; zt1 = Point[i].z;
		xt2 = Point[j].x; yt2 = Point[j].y; zt2 = Point[j].z;

		xe = Xe(xt1, yt1, zt1);
		ye=Ye(xt1,yt1,zt1);
		x1=xn(xe);
		y1=ym(ye);

		xe = Xe(xt2, yt2, zt2);
		ye=Ye(xt2,yt2,zt2);
		x2=xn(xe);
		y2=ym(ye);

		MoveToEx(hdc,x1,y1,NULL);
		LineTo(hdc,x2,y2);
	}

	for(int i=0; i<4; i++)
	{
		xt1 =   Point[i].x; yt1 =   Point[i].y; zt1 =   Point[i].z;
		xt2 = Point[i+4].x; yt2 = Point[i+4].y; zt2 = Point[i+4].z;

		xe = Xe(xt1, yt1, zt1);
		ye=Ye(xt1,yt1,zt1);
		x1=xn(xe);
		y1=ym(ye);

		xe = Xe(xt2, yt2, zt2);
		ye=Ye(xt2,yt2,zt2);
		x2=xn(xe);
		y2=ym(ye);

		MoveToEx(hdc,x1,y1,NULL);
		LineTo(hdc,x2,y2);
	}


	for(int i=0; i<2; i++)
	{
		xt1 =   Point[i].x; yt1 =   Point[i].y; zt1 =   Point[i].z;
		xt2 = Point[i+2].x; yt2 = Point[i+2].y; zt2 = Point[i+2].z;

		xe = Xe(xt1, yt1, zt1);
		ye=Ye(xt1,yt1,zt1);
		x1=xn(xe);
		y1=ym(ye);

		xe = Xe(xt2, yt2, zt2);
		ye=Ye(xt2,yt2,zt2);
		x2=xn(xe);
		y2=ym(ye);

		MoveToEx(hdc,x1,y1,NULL);
		LineTo(hdc,x2,y2);
	}


}
예제 #20
0
vector<double> CNelderMead::NelderMeadFunction(double (*f)(vector<double>, RMSEinputs rmsein), NMsettings nmset, vector<vector<double> > x)
{
	int NumIters = 0;
	int i,j;

	double MaxIters   = nmset.MaxIters;
	double tolerance  = nmset.tolerance;
	int N = nmset.N;
	RMSEinputs rmsein = nmset.RMSEinp;
	double S = rmsein.S;
	double T = rmsein.T;
	double r = rmsein.r;

	// Value of the function at the vertices
	vector<vector<double> > F(N+1, vector<double>(2));

	// Step 0.  Ordering and Best and Worst points
	// Order according to the functional values, compute the best and worst points
	step0:
	NumIters += 1;
	for (j=0; j<=N; j++){
		vector<double> z(N, 0.0);								// Create vector to contain
		for (i=0; i<=N-1; i++)
			z[i] = x[i][j];
		F[j][0] = f(z,rmsein);		       						// Function values
		F[j][1] = j;											// Original index positions
	}
	sort(F.begin(), F.end());

	// New vertices order first N best initial vectors and
	// last (N+1)st vertice is the worst vector
	// y is the matrix of vertices, ordered so that the worst vertice is last
	vector<vector<double> > y(N, vector<double>(N+1));
	for (j=0; j<=N; j++)
		for (i=0; i<=N-1; i++)
			y[i][j] = x[i][F[j][1]];

	//  First best vector y(1) and function value f1
	vector<double> x1(N, 0.0); for (i=0; i<=N-1; i++) x1[i] = y[i][0];
	double f1 = f(x1,rmsein);

	// Last best vector y(N) and function value fn
	vector<double> xn(N, 0.0); for (i=0; i<=N-1; i++) xn[i] = y[i][N-1];
	double fn = f(xn,rmsein);

	// Worst vector y(N+1) and function value fn1
	vector<double> xn1(N, 0.0); for (i=0; i<=N-1; i++) xn1[i] = y[i][N];
	double fn1 = f(xn1,rmsein);

	// z is the first N vectors from y, excludes the worst y(N+1)
	vector<vector<double> > z(N, vector<double>(N));
	for (j=0; j<=N-1; j++)
		for (i=0; i<=N-1; i++)
			z[i][j] = y[i][j];

	// Mean of best N values and function value fm
	vector<double> xm(N, 0.0); xm = CNelderMead::VMean(z,N);
	double fm = f(xm,rmsein);

	// Reflection point xr and function fr
	vector<double> xr(N, 0.0); xr = CNelderMead::VSub(VAdd(xm, xm), xn1);
	double fr = f(xr,rmsein);

	// Expansion point xe and function fe
	vector<double> xe(N, 0.0); xe = CNelderMead::VSub(VAdd(xr, xr), xm);
	double fe = f(xe,rmsein);

	// Outside contraction point and function foc
	vector<double> xoc(N, 0.0);	xoc = CNelderMead::VAdd(CNelderMead::VMult(xr, 0.5), VMult(xm, 0.5));
	double foc = f(xoc,rmsein);

	// Inside contraction point and function foc
	vector<double> xic(N, 0.0);	xic = CNelderMead::VAdd(CNelderMead::VMult(xm, 0.5), CNelderMead::VMult(xn1, 0.5));
	double fic = f(xic,rmsein);

	while ((NumIters <= MaxIters) && (abs(f1-fn1) >= tolerance))
	{
		// Step 1. Reflection Rule
		if ((f1<=fr) && (fr<fn)) {
			for (j=0; j<=N-1; j++)
				for (i=0; i<=N-1; i++)
					x[i][j] = y[i][j];
			for (i=0; i<=N-1; i++)
				x[i][N] = xr[i];
			goto step0;
		}

		// Step 2.  Expansion Rule
		if (fr<f1) {
			for (j=0; j<=N-1; j++) {
				for (i=0; i<=N-1; i++)  x[i][j] = y[i][j]; }
			if (fe<fr)
				for (i=0; i<=N-1; i++)	x[i][N] = xe[i];
			else
				for (i=0; i<=N-1; i++)	x[i][N] = xr[i];
			goto step0;
		}

		// Step 3.  Outside contraction Rule
		if ((fn<=fr) && (fr<fn1) && (foc<=fr)) {
			for (j=0; j<=N-1; j++) {
				for (i=0; i<=N-1; i++)  x[i][j] = y[i][j]; }
			for (i=0; i<=N-1; i++)	x[i][N] = xoc[i];
			goto step0;
		}

		// Step 4.  Inside contraction Rule
		if ((fr>=fn1) && (fic<fn1)) {
			for (j=0; j<=N-1; j++) {
				for (i=0; i<=N-1; i++)  x[i][j] = y[i][j]; }
			for (i=0; i<=N-1; i++)	x[i][N] = xic[i];
			goto step0;
		}

		// Step 5. Shrink Step
		for (i=0; i<=N-1; i++)
			x[i][0] = y[i][0];
		for (i=0; i<=N-1; i++) {
			for (j=1; j<=N; j++)
				x[i][j] = 0.5*(y[i][j] + x[i][0]);
		}
		goto step0;
	}

	// Output component
	// Return N parameter values, value of objective function, and number of iterations
	vector<double> out(N+2);
	for (i=0; i<=N-1; i++)
		out[i] = x1[i];
	out[N] = f1;
	out[N+1] = NumIters;
	return out;
}
예제 #21
0
void Strand2dFCBlockSolver::gradSetupSub(Array3D<double>& gx)
{
  // initialize coefficient array
  gx.set(0.);


  // form quadratic sub elements
  int meshOrderL=2,nElemLocalL=meshOrder-1,nSurfElemL=nSurfElem*nElemLocalL;
  Array3D<int> surfElemL(nSurfElemL,meshOrderL+1,2);
  Array3D<int> elemLocalL(nElemLocalL,meshOrderL+1,2);
  if (meshOrder == 2){
    elemLocalL(0,0,0) = 0; elemLocalL(0,0,1) = 1;
    elemLocalL(0,1,0) = 1; elemLocalL(0,1,1) = 1;
    elemLocalL(0,2,0) = 2; elemLocalL(0,2,1) = 1;
  }
  else if (meshOrder == 3){
    elemLocalL(0,0,0) = 0; elemLocalL(0,0,1) = 1;
    elemLocalL(0,1,0) = 3; elemLocalL(0,1,1) = 0;
    elemLocalL(0,2,0) = 2; elemLocalL(0,2,1) = 1;
    elemLocalL(1,0,0) = 2; elemLocalL(1,0,1) = 0;
    elemLocalL(1,1,0) = 1; elemLocalL(1,1,1) = 1;
    elemLocalL(1,2,0) = 3; elemLocalL(1,2,1) = 1;
  }
  else if (meshOrder == 4){
    elemLocalL(0,0,0) = 0; elemLocalL(0,0,1) = 1;
    elemLocalL(0,1,0) = 3; elemLocalL(0,1,1) = 0;
    elemLocalL(0,2,0) = 2; elemLocalL(0,2,1) = 1;
    elemLocalL(1,0,0) = 2; elemLocalL(1,0,1) = 0;
    elemLocalL(1,1,0) = 4; elemLocalL(1,1,1) = 0;
    elemLocalL(1,2,0) = 3; elemLocalL(1,2,1) = 1;
    elemLocalL(2,0,0) = 3; elemLocalL(2,0,1) = 0;
    elemLocalL(2,1,0) = 1; elemLocalL(2,1,1) = 1;
    elemLocalL(2,2,0) = 4; elemLocalL(2,2,1) = 1;
  }
  
  int k=0;
  for (int n=0; n<nSurfElem; n++)
    for (int i=0; i<nElemLocalL; i++){
      for (int m=0; m<meshOrderL+1; m++){
	surfElemL(k,m,0) = surfElem(n,elemLocalL(i,m,0));
	surfElemL(k,m,1) = elemLocalL(i,m,1);
      }
      k++;
    }
  if (k != nSurfElemL){
    cout << "\n***Problem forming sub-elements in initialize.C***"
	 << endl;
    exit(0);
  }
 

  // Lagrange polynomial derivatives for lower order elements
  int spacing=0; // assume equally spaced points in surface elements for now
  Array1D<double> ss(meshOrderL+1);
  solutionPoints1D(meshOrderL,
		   spacing,
		   &ss(0));

  bool test=false;
  Array2D<double> lc(meshOrderL+1,meshOrderL+1);
  lagrangePoly1D(test, // coefficients to form Lagrange polynomials
		 meshOrderL,
		 &ss(0),
		 &lc(0,0));

  // ls(i,j) = (dl_j/ds)_i (a row is all Lagrange polynomials (derivatives)
  // evaluated at a single mesh point i)
  Array2D<double> lsL(meshOrderL+1,meshOrderL+1);
  lsL.set(0.);
  int km;
  for (int i=0; i<meshOrderL+1; i++) // ith mesh point
    for (int j=0; j<meshOrderL+1; j++) // jth Lagrange polynomial
      for (int k=0; k<meshOrderL+1; k++){
	km        = max(0,k-1);
	lsL(i,j) +=((double)k)*pow(ss(i),km)*lc(j,k);
      }


  // mapping terms for lower order elements
  Array3D<double> xsL(nSurfElemL,meshOrderL+1,nStrandNode);
  Array3D<double> ysL(nSurfElemL,meshOrderL+1,nStrandNode);
  Array3D<double> jacL(nSurfElemL,meshOrderL+1,nStrandNode);
  xsL.set(0.);
  ysL.set(0.);
  int ni,nm;
  double x0,y0,nx,ny;
  for (int n=0; n<nSurfElemL; n++)
    for (int i=0; i<meshOrderL+1; i++){ // ith point in the element
      ni = surfElemL(n,i,0);
      for (int m=0; m<meshOrderL+1; m++){ // mth Lagrange poly. in mapping
	nm = surfElemL(n,m,0);
	x0 = surfX(nm,0);
	y0 = surfX(nm,1);
	nx = pointingVec(nm,0);
	ny = pointingVec(nm,1);
	for (int j=0; j<nStrandNode; j++){
	  xsL(n,i,j) += lsL(i,m)*(x0+nx*strandX(j));
	  ysL(n,i,j) += lsL(i,m)*(y0+ny*strandX(j));
	}}
      for (int j=0; j<nStrandNode; j++)
	jacL(n,i,j) = xsL(n,i,j)*yn(ni,j)-ysL(n,i,j)*xn(ni,j);
    }


  // degree at each surface node
  Array1D<int> sum(nSurfNode);
  sum.set(0);
  for (int n=0; n<nSurfElemL; n++)
    for (int i=0; i<meshOrderL+1; i++)
      sum(surfElemL(n,i,0)) += surfElemL(n,i,1);


  // use elements to form gradient coefficients
  double xnj,ynj;
  Array3D<double> a(nSurfNode,nStrandNode,2);
  a.set(0.);
  for (int n=0; n<nSurfElemL; n++)
    for (int i=0; i<meshOrderL+1; i++){ //ith point in the element
      if (surfElemL(n,i,1) == 1){ //if a contributing node
	ni = surfElemL(n,i,0);
	for (int m=0; m<meshOrderL+1; m++){ //mth Lagrange poly. in mapping
	  nm = surfElemL(n,m,0);
	  for (int j=0; j<nStrandNode; j++){ //local gradient coefficients
	    xnj       = xn(ni,j)/(jacL(n,i,j)*(double)sum(ni));
	    ynj       = yn(ni,j)/(jacL(n,i,j)*(double)sum(ni));
	    a(nm,j,0) = lsL(i,m)*ynj;
	    a(nm,j,1) =-lsL(i,m)*xnj;
	  }}
	for (int m=psp2(ni); m<psp2(ni+1); m++){ //add to coefficient array
	  nm = psp1(m);
	  for (int j=0; j<nStrandNode; j++){
	    gx(m,j,0) += a(nm,j,0);
	    gx(m,j,1) += a(nm,j,1);
	  }}
	for (int m=0; m<meshOrderL+1; m++){ //reset helper array to zero
	  nm = surfElemL(n,m,0);
	  for (int j=0; j<nStrandNode; j++){
	    a(nm,j,0) = 0.;
	    a(nm,j,1) = 0.;
	  }}}}


  // clean up
  sum.deallocate();
  a.deallocate();
  surfElemL.deallocate();
  elemLocalL.deallocate();
  xsL.deallocate();
  ysL.deallocate();
  ss.deallocate();
  lc.deallocate();
  lsL.deallocate();
}