#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <unistd.h>
#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <libintl.h>
#include <rtapi_math.h>
#include "rs274ngc.hh"
#include "rs274ngc_return.hh"
#include "rs274ngc_interp.hh"
#include "interp_internal.hh"
#define _(s) gettext(s)
char Interp::arc_axis1(int plane) {
switch(plane) {
case CANON_PLANE_XY: return 'X';
case CANON_PLANE_XZ: return 'Z';
case CANON_PLANE_YZ: return 'Y';
default: return '!';
}
}
char Interp::arc_axis2(int plane) {
switch(plane) {
case CANON_PLANE_XY: return 'Y';
case CANON_PLANE_XZ: return 'X';
case CANON_PLANE_YZ: return 'Z';
default: return '!';
}
}
int Interp::arc_data_comp_ijk(int move, int plane, int side, double tool_radius, double current_x, double current_y, double end_x, double end_y, int ij_absolute, double i_number, double j_number, int p_number,
double *center_x, double *center_y, int *turn, double radius_tolerance, double spiral_abs_tolerance, double spiral_rel_tolerance)
{
double arc_radius;
double radius2;
char a = arc_axis1(plane), b = arc_axis2(plane);
if ( ij_absolute ) {
*center_x = (i_number);
*center_y = (j_number);
} else {
*center_x = (current_x + i_number);
*center_y = (current_y + j_number);
}
arc_radius = hypot((*center_x - current_x), (*center_y - current_y));
radius2 = hypot((*center_x - end_x), (*center_y - end_y));
CHKS(((arc_radius < radius_tolerance) || (radius2 < radius_tolerance)),
_("Zero-radius arc: "
"start=(%c%.4f,%c%.4f) center=(%c%.4f,%c%.4f) end=(%c%.4f,%c%.4f) r1=%.4f r2=%.4f"),
a, current_x, b, current_y,
a, *center_x, b, *center_y,
a, end_x, b, end_y, arc_radius, radius2);
double abs_err = fabs(arc_radius - radius2);
double rel_err = abs_err / std::max(arc_radius, radius2);
CHKS((abs_err > spiral_abs_tolerance * 100.0) ||
(rel_err > spiral_rel_tolerance && abs_err > spiral_abs_tolerance),
_("Radius to end of arc differs from radius to start: "
"start=(%c%.4f,%c%.4f) center=(%c%.4f,%c%.4f) end=(%c%.4f,%c%.4f) "
"r1=%.4f r2=%.4f abs_err=%.4g rel_err=%.4f%%"),
a, current_x, b, current_y,
a, *center_x, b, *center_y,
a, end_x, b, end_y, arc_radius, radius2,
abs_err, rel_err*100);
CHKS(((arc_radius <= tool_radius) && (((side == LEFT) && (move == G_3)) ||
((side == RIGHT) && (move == G_2)))),
NCE_TOOL_RADIUS_NOT_LESS_THAN_ARC_RADIUS_WITH_COMP);
if (move == G_2)
*turn = -1 * p_number;
else if (move == G_3)
*turn = 1 * p_number;
else
ERS(NCE_BUG_CODE_NOT_G2_OR_G3);
return INTERP_OK;
}
int Interp::arc_data_comp_r(int move, int plane,
int side, double tool_radius, double current_x, double current_y, double end_x, double end_y, double big_radius, int p_number,
double *center_x, double *center_y, int *turn, double tolerance) {
double abs_radius;
abs_radius = fabs(big_radius);
CHKS(((abs_radius <= tool_radius) && (((side == LEFT) && (move == G_3)) ||
((side == RIGHT) && (move == G_2)))),
NCE_TOOL_RADIUS_NOT_LESS_THAN_ARC_RADIUS_WITH_COMP);
return arc_data_r(move, plane, current_x, current_y, end_x, end_y, big_radius, p_number,
center_x, center_y, turn, tolerance);
}
int Interp::arc_data_ijk(int move, int plane,
double current_x, double current_y, double end_x, double end_y, int ij_absolute, double i_number, double j_number, int p_number,
double *center_x, double *center_y, int *turn, double radius_tolerance, double spiral_abs_tolerance, double spiral_rel_tolerance)
{
double radius;
double radius2;
char a = arc_axis1(plane), b = arc_axis2(plane);
if ( ij_absolute ) {
*center_x = (i_number);
*center_y = (j_number);
} else {
*center_x = (current_x + i_number);
*center_y = (current_y + j_number);
}
radius = hypot((*center_x - current_x), (*center_y - current_y));
radius2 = hypot((*center_x - end_x), (*center_y - end_y));
CHKS(((radius < radius_tolerance) || (radius2 < radius_tolerance)),_("Zero-radius arc: "
"start=(%c%.4f,%c%.4f) center=(%c%.4f,%c%.4f) end=(%c%.4f,%c%.4f) r1=%.4f r2=%.4f"),
a, current_x, b, current_y,
a, *center_x, b, *center_y,
a, end_x, b, end_y, radius, radius2);
double abs_err = fabs(radius - radius2);
double rel_err = abs_err / std::max(radius, radius2);
CHKS((abs_err > spiral_abs_tolerance * 100.0) ||
(rel_err > spiral_rel_tolerance && abs_err > spiral_abs_tolerance),
_("Radius to end of arc differs from radius to start: "
"start=(%c%.4f,%c%.4f) center=(%c%.4f,%c%.4f) end=(%c%.4f,%c%.4f) "
"r1=%.4f r2=%.4f abs_err=%.4g rel_err=%.4f%%"),
a, current_x, b, current_y,
a, *center_x, b, *center_y,
a, end_x, b, end_y, radius, radius2,
abs_err, rel_err*100);
if (move == G_2)
*turn = -1 * p_number;
else if (move == G_3)
*turn = 1 * p_number;
else
ERS(NCE_BUG_CODE_NOT_G2_OR_G3);
return INTERP_OK;
}
int Interp::arc_data_r(int move, int plane,
double current_x, double current_y, double end_x, double end_y, double radius, int p_number,
double *center_x, double *center_y, int *turn, double tolerance) {
double abs_radius;
double half_length;
double mid_x;
double mid_y;
double offset;
double theta;
double turn2;
CHKS(((end_x == current_x) && (end_y == current_y)),
NCE_CURRENT_POINT_SAME_AS_END_POINT_OF_ARC);
abs_radius = fabs(radius);
mid_x = (end_x + current_x) / 2.0;
mid_y = (end_y + current_y) / 2.0;
half_length = hypot((mid_x - end_x), (mid_y - end_y));
CHKS(((half_length - abs_radius) > tolerance),
NCE_ARC_RADIUS_TOO_SMALL_TO_REACH_END_POINT);
if ((half_length / abs_radius) > (1 - TINY))
half_length = abs_radius;
if (((move == G_2) && (radius > 0)) || ((move == G_3) && (radius < 0)))
theta = atan2((end_y - current_y), (end_x - current_x)) - M_PI_2l;
else
theta = atan2((end_y - current_y), (end_x - current_x)) + M_PI_2l;
turn2 = asin(half_length / abs_radius);
offset = abs_radius * cos(turn2);
*center_x = mid_x + (offset * cos(theta));
*center_y = mid_y + (offset * sin(theta));
*turn = (move == G_2) ? -1 * p_number : 1 * p_number;
return INTERP_OK;
}