Пример #1
0
int main(){
  double a1,a2,b1,b2,c1,c2,a,b,c,s;
  while(1){
    if(scanf("%lf%lf%lf%lf%lf%lf",&a1,&a2,&b1,&b2,&c1,&c2)!=6)return 0;
    a=HYPOT(a1,a2,b1,b2);b=HYPOT(b1,b2,c1,c2);c=HYPOT(c1,c2,a1,a2);s=a+b+c;
    printf("%.2lf\n",2*3.141592653589793*(a*b*c)/sqrt(s*(s-2*a)*(s-2*b)*(s-2*c)));
  }
}
Пример #2
0
/* DO_ANGLE: Calculate angle (degrees) between vector 1 at (0,0; x1,y1) and
 *          vector 2 at (0,0; x2,y2).
 */
double do_angled(double x1, double y1, double x2, double y2)
{
  double temp;
  temp = ((x1 * x2) + (y1 * y2)) / (HYPOT(x1, y1) * HYPOT(x2, y2));
  errno = 0;
  temp = r2d(acos(temp));
  MATH_ERROR("angled");
  return (temp);
}
Пример #3
0
// ##########added by liu xiang ###########
//find the radiu of the image
void FindRadius1(unsigned char *Y[CAMNUM], double *CenX, double *CenY,int size)
{
	int				x, y;
	double			temp_radius;
	unsigned char	*pImage;
	int				i;

	// Find maximum radius from center of mass
	m_radius = 0;
	for(i=0; i<size; i++)
	{
		pImage = Y[i];
		for(y=0 ; y<HEIGHT; y++)
			for(x=0 ; x<WIDTH ; x++)
			{
				if( *pImage < 255 )
				{
					//					temp_radius = HYPOT(x - CENTER_X, y - CENTER_Y);
					temp_radius = HYPOT(x - CenX[i], y - CenY[i]);
					if(temp_radius > m_radius)
						m_radius = temp_radius;
				}
				pImage++;
			}
	}

	//ART_LUT_RADIUS =50
	//这里要除以50是因为需要把他们归一化到半径为50的圆中
	r_radius = ART_LUT_RADIUS / m_radius;
}
Пример #4
0
// speed up this function later
//作用即设定全局变量r_radius,即扫描图像中所有点,找到与中心点欧式距离最大值
//最后再用ART_LUT_RADIUS(50)除以最大值赋值
void FindRadius(unsigned char *Y[CAMNUM], double *CenX, double *CenY)
{
	int				x, y;
	double			temp_radius;
	unsigned char	*pImage;
	int				i;

	// Find maximum radius from center of mass
	m_radius = 0;
	for(i=0; i<CAMNUM; i++)
	{
		pImage = Y[i];
		for(y=0 ; y<HEIGHT; y++)
			for(x=0 ; x<WIDTH ; x++)
			{
//				if( *pImage < 127 )
				if( *pImage < 255 )
				{
//					temp_radius = HYPOT(x - CENTER_X, y - CENTER_Y);
					temp_radius = HYPOT(x - CenX[i], y - CenY[i]);
					if(temp_radius > m_radius)
						m_radius = temp_radius;
				}
				pImage++;
			}
	}

	r_radius = ART_LUT_RADIUS / m_radius;
}
Пример #5
0
void GenerateBasisLUT()
{
	double	angle, temp, radius;
	int		p, r, x, y;
	int		maxradius;

	maxradius = ART_LUT_RADIUS;

	for(y=0 ; y<ART_LUT_SIZE ; y++)
	for(x=0 ; x<ART_LUT_SIZE ; x++)
	{
		radius = HYPOT(x-maxradius, y-maxradius);
		if(radius < maxradius)
		{
			angle = atan2(y-maxradius, x-maxradius);

			for(p=0 ; p<ART_ANGULAR ; p++)
			for(r=0 ; r<ART_RADIAL ; r++)
			{
				temp = cos(radius*PI*r/maxradius);
				m_pBasisR[p][r][x][y] = temp*cos(angle*p);
				m_pBasisI[p][r][x][y] = temp*sin(angle*p);
			}
		}
		else
		{
			for(p=0 ; p<ART_ANGULAR ; p++)
			for(r=0 ; r<ART_RADIAL ; r++)
			{
				m_pBasisR[p][r][x][y] = 0;
				m_pBasisI[p][r][x][y] = 0;
			}
		}
	}
}
Пример #6
0
/**
 * print_line_from_here_to_there() takes two cartesian coordinates and draws a line from one
 * to the other. But there are really three sets of coordinates involved. The first coordinate
 * is the present location of the nozzle. We don't necessarily want to print from this location.
 * We first need to move the nozzle to the start of line segment where we want to print. Once
 * there, we can use the two coordinates supplied to draw the line.
 *
 * Note:  Although we assume the first set of coordinates is the start of the line and the second
 * set of coordinates is the end of the line, it does not always work out that way. This function
 * optimizes the movement to minimize the travel distance before it can start printing. This saves
 * a lot of time and eliminates a lot of nonsensical movement of the nozzle. However, it does
 * cause a lot of very little short retracement of th nozzle when it draws the very first line
 * segment of a 'circle'. The time this requires is very short and is easily saved by the other
 * cases where the optimization comes into play.
 */
void print_line_from_here_to_there(const float &sx, const float &sy, const float &sz, const float &ex, const float &ey, const float &ez) {
  const float dx_s = current_position[X_AXIS] - sx,   // find our distance from the start of the actual line segment
              dy_s = current_position[Y_AXIS] - sy,
              dist_start = HYPOT2(dx_s, dy_s),        // We don't need to do a sqrt(), we can compare the distance^2
                                                      // to save computation time
              dx_e = current_position[X_AXIS] - ex,   // find our distance from the end of the actual line segment
              dy_e = current_position[Y_AXIS] - ey,
              dist_end = HYPOT2(dx_e, dy_e),

              line_length = HYPOT(ex - sx, ey - sy);

  // If the end point of the line is closer to the nozzle, flip the direction,
  // moving from the end to the start. On very small lines the optimization isn't worth it.
  if (dist_end < dist_start && (INTERSECTION_CIRCLE_RADIUS) < ABS(line_length))
    return print_line_from_here_to_there(ex, ey, ez, sx, sy, sz);

  // Decide whether to retract & bump

  if (dist_start > 2.0) {
    retract_filament(destination);
    //todo:  parameterize the bump height with a define
    move_to(current_position[X_AXIS], current_position[Y_AXIS], current_position[Z_AXIS] + 0.500, 0.0);  // Z bump to minimize scraping
    move_to(sx, sy, sz + 0.500, 0.0); // Get to the starting point with no extrusion while bumped
  }

  move_to(sx, sy, sz, 0.0); // Get to the starting point with no extrusion / un-Z bump

  const float e_pos_delta = line_length * g26_e_axis_feedrate * g26_extrusion_multiplier;

  recover_filament(destination);
  move_to(ex, ey, ez, e_pos_delta);  // Get to the ending point with an appropriate amount of extrusion
}
Пример #7
0
    void debug_current_and_destination(PGM_P title) {

      // if the title message starts with a '!' it is so important, we are going to
      // ignore the status of the g26_debug_flag
      if (*title != '!' && !g26_debug_flag) return;

      const float de = destination[E_AXIS] - current_position[E_AXIS];

      if (de == 0.0) return; // Printing moves only

      const float dx = destination[X_AXIS] - current_position[X_AXIS],
                  dy = destination[Y_AXIS] - current_position[Y_AXIS],
                  xy_dist = HYPOT(dx, dy);

      if (xy_dist == 0.0) return;

      const float fpmm = de / xy_dist;
      SERIAL_ECHOPAIR_F("   fpmm=", fpmm, 6);
      SERIAL_ECHOPAIR_F("    current=( ", current_position[X_AXIS], 6);
      SERIAL_ECHOPAIR_F(", ", current_position[Y_AXIS], 6);
      SERIAL_ECHOPAIR_F(", ", current_position[Z_AXIS], 6);
      SERIAL_ECHOPAIR_F(", ", current_position[E_AXIS], 6);
      SERIAL_ECHOPGM(" )   destination=( "); debug_echo_axis(X_AXIS);
      SERIAL_ECHOPGM(", "); debug_echo_axis(Y_AXIS);
      SERIAL_ECHOPGM(", "); debug_echo_axis(Z_AXIS);
      SERIAL_ECHOPGM(", "); debug_echo_axis(E_AXIS);
      SERIAL_ECHOPGM(" )   ");
      serialprintPGM(title);
      SERIAL_EOL();
    }
Пример #8
0
void FindRadius2(unsigned char *Y, double *CenX, double *CenY)
{
	int				x, y;
	double			temp_radius;
	unsigned char	*pImage;
	int				i;

	// Find maximum radius from center of mass
	m_radius = 0;

	pImage = Y;
	for(y=0 ; y<HEIGHT; y++)
		for(x=0 ; x<WIDTH ; x++)
		{
			if( *pImage < 255 )
			{
				//					temp_radius = HYPOT(x - CENTER_X, y - CENTER_Y);
				temp_radius = HYPOT(x - *CenX, y - *CenY);
				if(temp_radius > m_radius)
					m_radius = temp_radius;
			}
			pImage++;
		}

	//ART_LUT_RADIUS =50
	//这里要除以50是因为需要把他们归一化到半径为50的圆中
	r_radius = ART_LUT_RADIUS / m_radius;
}
Пример #9
0
/* DO_DIST: Calculate distance between point 1 at (x1,y1) and
 *          point 2 at (x2,y2).
 */
double do_dist(double x1, double y1, double x2, double y2)
{
  double temp;
  errno = 0;
  temp = HYPOT((x1 - x2), (y1 - y2));
  MATH_ERROR("hypot");
  return (temp);
}
Пример #10
0
double *point_distance(Point *pt1, Point *pt2)
{
    double	*result;
    
    result = PALLOCTYPE(double);
    *result = HYPOT( pt1->x - pt2->x, pt1->y - pt2->y );
    return(result);
}
Пример #11
0
double *dist_pl(Point *pt, LINE *line)
{
    double	*result;
    
    result = PALLOCTYPE(double);
    *result = (line->A * pt->x + line->B * pt->y + line->C) /
	HYPOT(line->A, line->B);
    
    return(result);
}
Пример #12
0
static void compute_block(CSOUND *csound, PAULSTRETCH *p)
{
    uint32_t istart_pos = floor(p->start_pos);
    uint32_t pos;
    uint32_t i;
    uint32_t windowsize = p->windowsize;
    uint32_t half_windowsize = p->half_windowsize;
    MYFLT *hinv_buf = p->hinv_buf;
    MYFLT *old_windowed_buf= p->old_windowed_buf;
    MYFLT *tbl = p->ft->ftable;
    MYFLT *window = p->window;
    MYFLT *output= p->output;
    MYFLT *tmp = p->tmp;
    for (i = 0; i < windowsize; i++) {
      pos = istart_pos + i;
      if (pos < p->ft->flen) {
        tmp[i] = tbl[pos] * window[i];
      } else {
        tmp[i] = 0;
      }
    }
    /* re-order bins and take FFT */
    tmp[p->windowsize] = tmp[1];
    tmp[p->windowsize + 1] = 0.0;
    csoundRealFFTnp2(csound, tmp, p->windowsize);

    /* randomize phase */
    for (i = 0; i < windowsize + 2; i += 2) {
      MYFLT mag = HYPOT(tmp[i], tmp[i + 1]);
      // Android 5.1 does not seem to have cexpf ...
      // complex ph = cexpf(I * ((MYFLT)rand() / RAND_MAX) * 2 * M_PI);
      // so ...
      MYFLT  x = (((MYFLT)rand() / RAND_MAX) * 2 * M_PI);
      complex ph =  cos(x) + I*sin(x);
      tmp[i] = mag * (MYFLT)crealf(ph);
      tmp[i + 1] = mag * (MYFLT)cimagf(ph);
    }

    /* re-order bins and take inverse FFT */
    tmp[1] = tmp[p->windowsize];
    csoundInverseRealFFTnp2(csound, tmp, p->windowsize);

    /* apply window and overlap */
    for (i = 0; i < windowsize; i++) {
      tmp[i] *= window[i];
      if (i < half_windowsize) {
        output[i] = (MYFLT)(tmp[i] + old_windowed_buf[half_windowsize + i]);
        output[i] *= hinv_buf[i];
      }
      old_windowed_buf[i] = tmp[i];
    }
    p->start_pos += p->displace_pos;
}
Пример #13
0
/*	box_dt	-	returns the distance between the
 *			  center points of two boxes.
 */
double box_dt(BOX *box1, BOX *box2)
{
    double	result;
    Point	*box_center(),
    *a, *b;
    
    a = box_center(box1);
    b = box_center(box2);
    result = HYPOT(a->x - b->x, a->y - b->y);
    
    PFREE(a);
    PFREE(b);
    return(result);
}
Пример #14
0
/*	box_distance	-	returns the distance between the
 *				  center points of two boxes.
 */
double *box_distance(BOX *box1, BOX *box2)
{
    double	*result;
    Point	*box_center(), *a, *b;
    
    result = PALLOCTYPE(double);
    a = box_center(box1);
    b = box_center(box2);
    *result = HYPOT(a->x - b->x, a->y - b->y);
    
    PFREE(a);
    PFREE(b);
    return(result);
}
Пример #15
0
mesh_index_pair find_closest_circle_to_print(const float &X, const float &Y) {
  float closest = 99999.99;
  mesh_index_pair return_val;

  return_val.x_index = return_val.y_index = -1;

  for (uint8_t i = 0; i < GRID_MAX_POINTS_X; i++) {
    for (uint8_t j = 0; j < GRID_MAX_POINTS_Y; j++) {
      if (!is_bitmap_set(circle_flags, i, j)) {
        const float mx = _GET_MESH_X(i),  // We found a circle that needs to be printed
                    my = _GET_MESH_Y(j);

        // Get the distance to this intersection
        float f = HYPOT(X - mx, Y - my);

        // It is possible that we are being called with the values
        // to let us find the closest circle to the start position.
        // But if this is not the case, add a small weighting to the
        // distance calculation to help it choose a better place to continue.
        f += HYPOT(g26_x_pos - mx, g26_y_pos - my) / 15.0;

        // Add in the specified amount of Random Noise to our search
        if (random_deviation > 1.0)
          f += random(0.0, random_deviation);

        if (f < closest) {
          closest = f;              // We found a closer location that is still
          return_val.x_index = i;   // un-printed  --- save the data for it
          return_val.y_index = j;
          return_val.distance = closest;
        }
      }
    }
  }
  bitmap_set(circle_flags, return_val.x_index, return_val.y_index);   // Mark this location as done.
  return return_val;
}
Пример #16
0
void GenerateBasisLUT()
{
	double	angle, temp, radius;
	int		p, r, x, y;
	int		maxradius;

	maxradius = ART_LUT_RADIUS;//50

	//ART_LUT_SIZE =101,为什么是101,是因为要包括100的距离,所以稍微大一点
	//因为将所有的像素点集中到了2*50 * 2*50范围内,所以x,y的范围为0-100
	for(y=0 ; y<ART_LUT_SIZE ; y++)
	for(x=0 ; x<ART_LUT_SIZE ; x++)
	{
		//计算半径
		radius = HYPOT((float)(x-maxradius), (float)(y-maxradius));
		if(radius < maxradius)
		{
			//atan2:返回第一个参数除以第二个参数的反正切值(-Pi/2,Pi/2)
			//计算改点与圆心之间的夹角
			angle = atan2((float)(y-maxradius), (float)(x-maxradius));

            //ART_ANGULAR =12
			//ART_RADIAL = 3
			//中间m_pBasisR[p][r][x][y]中针对不同的x,y;只要pr相同,其值不同,因为r什么的都变了
			for(p=0 ; p<ART_ANGULAR ; p++)
			for(r=0 ; r<ART_RADIAL ; r++)
			{
				//cos接受的参数自能是几π
				temp = cos(radius*PI*r/maxradius);
				m_pBasisR[p][r][x][y] = temp*cos(angle*p);
				m_pBasisI[p][r][x][y] = temp*sin(angle*p);
			}
		}
		else
		{
			for(p=0 ; p<ART_ANGULAR ; p++)
			for(r=0 ; r<ART_RADIAL ; r++)
			{
				m_pBasisR[p][r][x][y] = 0;
				m_pBasisI[p][r][x][y] = 0;
			}
		}
	}
}
Пример #17
0
  /**
   * print_line_from_here_to_there() takes two cartesian coordinates and draws a line from one
   * to the other.  But there are really three sets of coordinates involved.  The first coordinate
   * is the present location of the nozzle.  We don't necessarily want to print from this location.
   * We first need to move the nozzle to the start of line segment where we want to print.  Once
   * there, we can use the two coordinates supplied to draw the line.
   *
   * Note:  Although we assume the first set of coordinates is the start of the line and the second
   * set of coordinates is the end of the line, it does not always work out that way.  This function
   * optimizes the movement to minimize the travel distance before it can start printing.  This saves
   * a lot of time and eleminates a lot of non-sensical movement of the nozzle.   However, it does
   * cause a lot of very little short retracement of th nozzle when it draws the very first line
   * segment of a 'circle'.   The time this requires is very short and is easily saved by the other
   * cases where the optimization comes into play.
   */
  void print_line_from_here_to_there(const float &sx, const float &sy, const float &sz, const float &ex, const float &ey, const float &ez) {
    const float dx_s = current_position[X_AXIS] - sx,   // find our distance from the start of the actual line segment
                dy_s = current_position[Y_AXIS] - sy,
                dist_start = HYPOT2(dx_s, dy_s),        // We don't need to do a sqrt(), we can compare the distance^2
                                                        // to save computation time
                dx_e = current_position[X_AXIS] - ex,   // find our distance from the end of the actual line segment
                dy_e = current_position[Y_AXIS] - ey,
                dist_end = HYPOT2(dx_e, dy_e),

                line_length = HYPOT(ex - sx, ey - sy);

    // If the end point of the line is closer to the nozzle, flip the direction,
    // moving from the end to the start. On very small lines the optimization isn't worth it.
    if (dist_end < dist_start && (SIZE_OF_INTERSECTION_CIRCLES) < abs(line_length)) {
      //if (ubl.g26_debug_flag) SERIAL_ECHOLNPGM("  Reversing start and end of print_line_from_here_to_there()");
      return print_line_from_here_to_there(ex, ey, ez, sx, sy, sz);
    }

    // Decide whether to retract.

    if (dist_start > 2.0) {
      retract_filament(destination);
      //if (ubl.g26_debug_flag) SERIAL_ECHOLNPGM("  filament retracted.");
    }
    move_to(sx, sy, sz, 0.0); // Get to the starting point with no extrusion

    const float e_pos_delta = line_length * g26_e_axis_feedrate * extrusion_multiplier;

    un_retract_filament(destination);

    //if (ubl.g26_debug_flag) {
    //  SERIAL_ECHOLNPGM("  doing printing move.");
    //  debug_current_and_destination(PSTR("doing final move_to() inside print_line_from_here_to_there()"));
    //}
    move_to(ex, ey, ez, e_pos_delta);  // Get to the ending point with an appropriate amount of extrusion
  }
Пример #18
0
double point_dt(Point *pt1, Point *pt2)
{
    return( HYPOT( pt1->x - pt2->x, pt1->y - pt2->y ) );
}
Пример #19
0
//Y表示照片的指针
void ExtractCoefficients(unsigned char *Y, double m_Coeff[ART_ANGULAR][ART_RADIAL], unsigned char *Edge, double CenX, double CenY)
{
	int				x, y, ix, iy;
	int				p, r;
	double			dx, dy, tx, ty, x1, x2;
	int				count;
	double			m_pCoeffR[ART_ANGULAR][ART_RADIAL];
	double			m_pCoeffI[ART_ANGULAR][ART_RADIAL];
//	double			norm;

	unsigned char *pImage;
//	unsigned char *pEdge;

	memset(m_pCoeffR, 0, ART_ANGULAR * ART_RADIAL * sizeof(double) );
	memset(m_pCoeffI, 0, ART_ANGULAR * ART_RADIAL * sizeof(double) );
//	for(p=0 ; p<ART_ANGULAR ; p++)
//	for(r=0 ; r<ART_RADIAL ; r++)
//	{
//		m_pCoeffR[p][r] = 0;
//		m_pCoeffI[p][r] = 0;
//	}

	count = 0;
	pImage = Y;
//	pEdge = Edge;
	for (y=0 ; y<HEIGHT ; y++)
	for (x=0 ; x<WIDTH; x++)
	{
//		if( *pImage < 127 )
		if( *pImage < 255 )
		{
			// 1.0 is for silhouette, another one is for depth, both weighting is 0.5
			// both depth and silhouette
//			norm = (1.0 + (255.0-*pImage) / 255.0) / 2;
			// depth only
//			norm = (255.0-*pImage) / 255.0;
			// silhouette only
//			norm = 1.0;
			// edge (from depth) only
//			norm = *pEdge / 255.0;
			// edge (from depth) + depth + silhouette
//			norm = (*pEdge/255.0 + (255.0-*pImage)/255.0 + 1.0) / 3;
			// edge (from silhouette) only
//			norm = 1.0;
			// edge (from silhouette) + silhouette
//			norm = (255.0-*pImage) / 255.0;

			// map image coordinate (x,y) to basis function coordinate (tx,ty)
//			dx = x - CENTER_X;
//			dy = y - CENTER_Y;
			dx = x - CenX;
			dy = y - CenY;
			tx = dx * r_radius + ART_LUT_RADIUS;//r_radius由上一个函数计算
			ty = dy * r_radius + ART_LUT_RADIUS;//为什么要加上50的ART_LUT_RADIUS,因为dx是负的
			ix = (int)tx;
			iy = (int)ty;
			dx = tx - ix;//dx表示小数部分,为啥要小数,用来干嘛?
			dy = ty - iy;

			//这里即通过分割地方法来近似积分
			// summation of basis function
//			if(tx >= 0 && tx < ART_LUT_SIZE && ty >= 0 && ty < ART_LUT_SIZE)
			for(p=0 ; p<ART_ANGULAR ; p++)
			for(r=0 ; r<ART_RADIAL ; r++)
			{
				// GetReal (if call function, the speed will be very slow)
				// m_pCoeffR[p][r] += GetReal(p, r, tx, ty);
				x1 = m_pBasisR[p][r][ix][iy] + (m_pBasisR[p][r][ix+1][iy]-m_pBasisR[p][r][ix][iy]) * dx;
				x2 = m_pBasisR[p][r][ix][iy+1] + (m_pBasisR[p][r][ix+1][iy+1]-m_pBasisR[p][r][ix][iy+1]) * dx;
//				m_pCoeffR[p][r] += norm * (x1 + (x2-x1) * dy);
				m_pCoeffR[p][r] += (x1 + (x2-x1) * dy);

				// GetImg (if call function, the speed will be very slow)
				// m_pCoeffI[p][r] -= GetImg(p, r, tx, ty);
				x1 = m_pBasisI[p][r][ix][iy] + (m_pBasisI[p][r][ix+1][iy]-m_pBasisI[p][r][ix][iy]) * dx;
				x2 = m_pBasisI[p][r][ix][iy+1] + (m_pBasisI[p][r][ix+1][iy+1]-m_pBasisI[p][r][ix][iy+1]) * dx;
//				m_pCoeffI[p][r] -= norm * (x1 + (x2-x1) * dy);
				m_pCoeffI[p][r] -= (x1 + (x2-x1) * dy);
			}

			count ++;		// how many pixels
		}
		pImage++;
//		pEdge++;
	}

	// if the 3D model is flat, some camera will render nothing, so count=0 in this case
	if( count > 0 )
	{
		for(p=0 ; p<ART_ANGULAR ; p++)
		for(r=0 ; r<ART_RADIAL ; r++)
			m_Coeff[p][r] = HYPOT( m_pCoeffR[p][r]/count, m_pCoeffI[p][r]/count );

		// normalization
		for(p=0 ; p<ART_ANGULAR ; p++)
		for(r=0 ; r<ART_RADIAL ; r++)
			m_Coeff[p][r] /= m_Coeff[0][0];
			
	}
	else
	{
		// if didn't add this, the result will also be saved as 0
		for(p=0 ; p<ART_ANGULAR ; p++)
		for(r=0 ; r<ART_RADIAL ; r++)
			m_Coeff[p][r] = 0.0;
		// use a line to test the number to approximate
/*		for(p=0 ; p<ART_ANGULAR ; p++)
		for(r=0 ; r<ART_RADIAL ; r++)
			m_Coeff[p][r] = 0.010256410;
		for(p=0 ; p<ART_ANGULAR ; p+=2)
			m_Coeff[p][0] = 0.980129780;*/
	}
}
Пример #20
0
    bool _O2 unified_bed_leveling::prepare_segmented_line_to(const float (&rtarget)[XYZE], const float &feedrate) {

      if (!position_is_reachable(rtarget[X_AXIS], rtarget[Y_AXIS]))  // fail if moving outside reachable boundary
        return true; // did not move, so current_position still accurate

      const float total[XYZE] = {
        rtarget[X_AXIS] - current_position[X_AXIS],
        rtarget[Y_AXIS] - current_position[Y_AXIS],
        rtarget[Z_AXIS] - current_position[Z_AXIS],
        rtarget[E_AXIS] - current_position[E_AXIS]
      };

      const float cartesian_xy_mm = HYPOT(total[X_AXIS], total[Y_AXIS]);  // total horizontal xy distance

      #if IS_KINEMATIC
        const float seconds = cartesian_xy_mm / feedrate;                                  // seconds to move xy distance at requested rate
        uint16_t segments = lroundf(delta_segments_per_second * seconds),                  // preferred number of segments for distance @ feedrate
                 seglimit = lroundf(cartesian_xy_mm * (1.0f / (DELTA_SEGMENT_MIN_LENGTH))); // number of segments at minimum segment length
        NOMORE(segments, seglimit);                                                        // limit to minimum segment length (fewer segments)
      #else
        uint16_t segments = lroundf(cartesian_xy_mm * (1.0f / (DELTA_SEGMENT_MIN_LENGTH))); // cartesian fixed segment length
      #endif

      NOLESS(segments, 1U);                        // must have at least one segment
      const float inv_segments = 1.0f / segments;  // divide once, multiply thereafter

      #if IS_SCARA // scale the feed rate from mm/s to degrees/s
        scara_feed_factor = cartesian_xy_mm * inv_segments * feedrate;
        scara_oldA = planner.get_axis_position_degrees(A_AXIS);
        scara_oldB = planner.get_axis_position_degrees(B_AXIS);
      #endif

      const float diff[XYZE] = {
        total[X_AXIS] * inv_segments,
        total[Y_AXIS] * inv_segments,
        total[Z_AXIS] * inv_segments,
        total[E_AXIS] * inv_segments
      };

      // Note that E segment distance could vary slightly as z mesh height
      // changes for each segment, but small enough to ignore.

      float raw[XYZE] = {
        current_position[X_AXIS],
        current_position[Y_AXIS],
        current_position[Z_AXIS],
        current_position[E_AXIS]
      };

      // Only compute leveling per segment if ubl active and target below z_fade_height.
      if (!planner.leveling_active || !planner.leveling_active_at_z(rtarget[Z_AXIS])) {   // no mesh leveling
        while (--segments) {
          LOOP_XYZE(i) raw[i] += diff[i];
          ubl_buffer_segment_raw(raw, feedrate);
        }
        ubl_buffer_segment_raw(rtarget, feedrate);
        return false; // moved but did not set_current_from_destination();
      }

      // Otherwise perform per-segment leveling

      #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
        const float fade_scaling_factor = planner.fade_scaling_factor_for_z(rtarget[Z_AXIS]);
      #endif

      // increment to first segment destination
      LOOP_XYZE(i) raw[i] += diff[i];

      for (;;) {  // for each mesh cell encountered during the move

        // Compute mesh cell invariants that remain constant for all segments within cell.
        // Note for cell index, if point is outside the mesh grid (in MESH_INSET perimeter)
        // the bilinear interpolation from the adjacent cell within the mesh will still work.
        // Inner loop will exit each time (because out of cell bounds) but will come back
        // in top of loop and again re-find same adjacent cell and use it, just less efficient
        // for mesh inset area.

        int8_t cell_xi = (raw[X_AXIS] - (MESH_MIN_X)) * (1.0f / (MESH_X_DIST)),
               cell_yi = (raw[Y_AXIS] - (MESH_MIN_Y)) * (1.0f / (MESH_Y_DIST));

        cell_xi = constrain(cell_xi, 0, (GRID_MAX_POINTS_X) - 1);
        cell_yi = constrain(cell_yi, 0, (GRID_MAX_POINTS_Y) - 1);

        const float x0 = mesh_index_to_xpos(cell_xi),   // 64 byte table lookup avoids mul+add
                    y0 = mesh_index_to_ypos(cell_yi);

        float z_x0y0 = z_values[cell_xi  ][cell_yi  ],  // z at lower left corner
              z_x1y0 = z_values[cell_xi+1][cell_yi  ],  // z at upper left corner
              z_x0y1 = z_values[cell_xi  ][cell_yi+1],  // z at lower right corner
              z_x1y1 = z_values[cell_xi+1][cell_yi+1];  // z at upper right corner

        if (isnan(z_x0y0)) z_x0y0 = 0;              // ideally activating planner.leveling_active (G29 A)
        if (isnan(z_x1y0)) z_x1y0 = 0;              //   should refuse if any invalid mesh points
        if (isnan(z_x0y1)) z_x0y1 = 0;              //   in order to avoid isnan tests per cell,
        if (isnan(z_x1y1)) z_x1y1 = 0;              //   thus guessing zero for undefined points

        float cx = raw[X_AXIS] - x0,   // cell-relative x and y
              cy = raw[Y_AXIS] - y0;

        const float z_xmy0 = (z_x1y0 - z_x0y0) * (1.0f / (MESH_X_DIST)),   // z slope per x along y0 (lower left to lower right)
                    z_xmy1 = (z_x1y1 - z_x0y1) * (1.0f / (MESH_X_DIST));   // z slope per x along y1 (upper left to upper right)

              float z_cxy0 = z_x0y0 + z_xmy0 * cx;            // z height along y0 at cx (changes for each cx in cell)

        const float z_cxy1 = z_x0y1 + z_xmy1 * cx,            // z height along y1 at cx
                    z_cxyd = z_cxy1 - z_cxy0;                 // z height difference along cx from y0 to y1

              float z_cxym = z_cxyd * (1.0f / (MESH_Y_DIST));  // z slope per y along cx from y0 to y1 (changes for each cx in cell)

        //    float z_cxcy = z_cxy0 + z_cxym * cy;            // interpolated mesh z height along cx at cy (do inside the segment loop)

        // As subsequent segments step through this cell, the z_cxy0 intercept will change
        // and the z_cxym slope will change, both as a function of cx within the cell, and
        // each change by a constant for fixed segment lengths.

        const float z_sxy0 = z_xmy0 * diff[X_AXIS],                                     // per-segment adjustment to z_cxy0
                    z_sxym = (z_xmy1 - z_xmy0) * (1.0f / (MESH_Y_DIST)) * diff[X_AXIS];  // per-segment adjustment to z_cxym

        for (;;) {  // for all segments within this mesh cell

          if (--segments == 0)                      // if this is last segment, use rtarget for exact
            COPY(raw, rtarget);

          const float z_cxcy = (z_cxy0 + z_cxym * cy) // interpolated mesh z height along cx at cy
            #if ENABLED(ENABLE_LEVELING_FADE_HEIGHT)
              * fade_scaling_factor                   // apply fade factor to interpolated mesh height
            #endif
          ;

          const float z = raw[Z_AXIS];
          raw[Z_AXIS] += z_cxcy;
          ubl_buffer_segment_raw(raw, feedrate);
          raw[Z_AXIS] = z;

          if (segments == 0)                        // done with last segment
            return false;                           // did not set_current_from_destination()

          LOOP_XYZE(i) raw[i] += diff[i];

          cx += diff[X_AXIS];
          cy += diff[Y_AXIS];

          if (!WITHIN(cx, 0, MESH_X_DIST) || !WITHIN(cy, 0, MESH_Y_DIST))    // done within this cell, break to next
            break;

          // Next segment still within same mesh cell, adjust the per-segment
          // slope and intercept to compute next z height.

          z_cxy0 += z_sxy0;   // adjust z_cxy0 by per-segment z_sxy0
          z_cxym += z_sxym;   // adjust z_cxym by per-segment z_sxym

        } // segment loop
      } // cell loop

      return false; // caller will update current_position
    }