// move a specifed distance in mm McoStatus TCR::moveDistance(double dx,double dy) { char st[500]; int32 dx_i,dy_i; int32 pos[2]; if (sp == 0L) return MCO_SERIAL_ERROR; getLocation(pos,0); dx_i = (40*(dx)+0.5); dy_i = (40*(dy)+0.5); pos[0] += dx_i; pos[1] += dy_i; pos[0] = MaxVal(pos[0],min_x); pos[0] = MinVal(pos[0],max_x); pos[1] = MaxVal(pos[1],min_y); pos[1] = MinVal(pos[1],max_y); sprintf(st,"PA %ld %ld;",pos[0],pos[1]); current_x = pos[0]; current_y = pos[1]; sp->sendData(st,strlen(st)); waitTenthSec(); return MCO_SUCCESS; }
McoStatus SpectroChart::moveToPatch(int32 patchNum,int ref) { char st[500]; int32 dx_i,dy_i; double dist; int tc; int waitTime; int32 table[2]; int error; McoStatus state; if (sp == 0L) return MCO_SERIAL_ERROR; // turn online state = turnOnline(); if (state != MCO_SUCCESS) return state; translateToTable(&pointArray[patchNum*2],table); table[0] = MaxVal(table[0],min_x); table[0] = MinVal(table[0],max_x); table[1] = MaxVal(table[1],min_y); table[1] = MinVal(table[1],max_y); sprintf(st,"; 208 0 %d %ld %ld\r\n",ref,(long)table[0],(long)table[1]); dx_i = table[0]-current_x; dy_i = table[1]-current_y; sp->sendData(st,strlen(st)); state = CheckErrorChart(); return state; }
McoStatus TCR::moveToPatch(int32 patchNum, int ref) { char st[500]; int32 dx_i,dy_i; double dist; long tc; int waitTime; int32 table[2]; if (sp == 0L) return MCO_SERIAL_ERROR; translateToTable(&pointArray[patchNum*2],table); //dx_i = table[0]-current_x; //dy_i = table[1]-current_y; //sprintf(st,"PR %ld %ld;",dx_i,dy_i); // the move command table[0] = MaxVal(table[0],min_x); table[0] = MinVal(table[0],max_x); table[1] = MaxVal(table[1],min_y); table[1] = MinVal(table[1],max_y); sprintf(st,"PA %ld %ld;",(long)table[0],(long)table[1]); // the move command sp->sendData(st,strlen(st)); dx_i = table[0]-current_x; dy_i = table[1]-current_y; // wait a time that is determined by the distance moved dist = sqrt((double)(dx_i*dx_i+dy_i*dy_i))*0.025; // assume that it moves 250mm/sec waitTime = 36+(int)(60.0*dist/150.0); tc = TickCount(); while (TickCount() - tc < waitTime) {} //current_x = pointArray[patchNum*2]; //current_y = pointArray[patchNum*2+1]; current_x += dx_i; current_y += dy_i; return MCO_SUCCESS; }
// translate a patch location to void Table::translateToTable(int patchnum, int32 *table) { double x,y; x = pointArray[patchnum*2]; y = pointArray[patchnum*2+1]; table[0] = a*x+b*y+Tx+0.5; table[1] = c*x+d*y+Ty+0.5; table[0] = MaxVal(table[0],min_x); table[0] = MinVal(table[0],max_x); table[1] = MaxVal(table[1],min_y); table[1] = MinVal(table[1],max_y); }
// move a specifed distance in mm McoStatus SpectroChart::moveDistance(double dx,double dy) { char st[5000]; int32 dx_i,dy_i; int error; McoStatus state; int32 pos[2]; if (sp == 0L) return MCO_SERIAL_ERROR; getLocation(pos,1); dx_i = (10*(dx)+0.5); dy_i = (-10*(dy)+0.5); pos[0] += dx_i; pos[1] += dy_i; pos[0] = MaxVal(pos[0],min_x); pos[0] = MinVal(pos[0],max_x); pos[1] = MaxVal(pos[1],min_y); pos[1] = MinVal(pos[1],max_y); // turn online state = turnOnline(); if (state != MCO_SUCCESS) return state; sprintf(st,"; 208 0 %ld %ld\r\n",pos[0],pos[1]); sp->sendData(st,strlen(st)); waitTenthSec(); state = CheckErrorChart(); current_x = pos[0]; current_y = pos[1]; return state; }
void ucase_c ( SpiceChar * in, SpiceInt lenout, SpiceChar * out ) /* -Brief_I/O VARIABLE I/O DESCRIPTION -------- --- -------------------------------------------------- in I Input string. lenout I Maximum length of output string. out O Output string, all uppercase. -Detailed_Input in is the input string. lenout is the maximum allowed length of the output string, including the terminating null. -Detailed_Output out is the output string. This is the input string with all lowercase letters converted to uppercase. Non-letters are not affected. If lenout < strlen(in)+1 the output string will be truncated on the right. A terminating null will be placed in out at position min ( strlen(in), lenout-1 ) unless lenout is less than or equal to zero. out may overwrite in. -Parameters None. -Particulars Convert each lowercase character in IN to uppercase. -Examples "This is an example" becomes "THIS IS AN EXAMPLE" "12345 +-=? > * $ &" "12345 +-=? > * $ &" -Restrictions None. -Exceptions 1) If the input string pointer is null, the error SPICE(NULLPOINTER) will be signaled. 2) If the output string pointer is null, the error SPICE(NULLPOINTER) will be signaled. 3) If lenout is less than or equal to zero, the error SPICE(STRINGTOOSHORT) will be signaled. 4) If the output string is shorter than the input string, the result will be truncated on the right. -Files None. -Author_and_Institution N.J. Bachman (JPL) K.R. Gehringer (JPL) I.M. Underwood (JPL) -Literature_References None. -Version -CSPICE Version 1.1.0, 26-JAN-2005 (NJB) Cast to SpiceInt was applied to strlen output to suppress compiler warnings about comparison of signed and unsigned types. -CSPICE Version 2.0.0, 26-AUG-1999 (NJB) Added string error checks. -CSPICE Version 1.0.0, 08-FEB-1998 (NJB) Based on SPICELIB Version 1.1.0, 13-MAR-1996 (KRG) -Index_Entries convert to uppercase -& */ { /* Begin ucase_c */ /* Local macros */ #define LOWA ( (SpiceInt) ('a') ) #define LOWZ ( (SpiceInt) ('z') ) #define SHIFT ( (SpiceInt) ('A') - LOWA ) /* Local variables */ SpiceInt i; SpiceInt ich; SpiceInt nmove; /* Check the input string pointer to make sure it's non-null. */ CHKPTR( CHK_DISCOVER, "ucase_c", in ); /* Make sure the output string has at least enough room for one output character and a null terminator. Also check for a null pointer. */ CHKOSTR ( CHK_DISCOVER, "ucase_c", out, lenout ); /* Move the string from in to out. Step through in one character at a time, translating letters between 'a' and 'z' to uppercase. First, determine how many characters to move. */ nmove = MinVal ( (SpiceInt)strlen(in), lenout-1 ); for ( i = 0; i < nmove; i++ ) { ich = (SpiceInt) in[i]; if ( ( ich >= LOWA ) && ( ich <= LOWZ ) ) { out[i] = (char) ( ich + SHIFT ); } else { out[i] = in[i]; } } /* Terminate the output string with a null. We know it has room for at least one character. */ out[nmove] = NULLCHAR; } /* End ucase_c */
void npelpt_c ( ConstSpiceDouble point [3], ConstSpiceEllipse * ellips, SpiceDouble pnear [3], SpiceDouble * dist ) /* -Brief_I/O Variable I/O Description -------- --- -------------------------------------------------- point I Point whose distance to an ellipse is to be found. ellips I A CSPICE ellipse. pnear O Nearest point on ellipse to input point. dist O Distance of input point to ellipse. -Detailed_Input ellips is a CSPICE ellipse that represents an ellipse in three-dimensional space. point is a point in 3-dimensional space. -Detailed_Output pnear is the nearest point on ellips to point. dist is the distance between point and pnear. This is the distance between point and the ellipse. -Parameters None. -Exceptions 1) Invalid ellipses will be diagnosed by routines called by this routine. 2) Ellipses having one or both semi-axis lengths equal to zero are turned away at the door; the error SPICE(DEGENERATECASE) is signalled. 3) If the geometric ellipse represented by ellips does not have a unique point nearest to the input point, any point at which the minimum distance is attained may be returned in pnear. -Files None. -Particulars Given an ellipse and a point in 3-dimensional space, if the orthogonal projection of the point onto the plane of the ellipse is on or outside of the ellipse, then there is a unique point on the ellipse closest to the original point. This routine finds that nearest point on the ellipse. If the projection falls inside the ellipse, there may be multiple points on the ellipse that are at the minimum distance from the original point. In this case, one such closest point will be returned. This routine returns a distance, rather than an altitude, in contrast to the CSPICE routine nearpt_c. Because our ellipse is situated in 3-space and not 2-space, the input point is not `inside' or `outside' the ellipse, so the notion of altitude does not apply to the problem solved by this routine. In the case of nearpt_c, the input point is on, inside, or outside the ellipsoid, so it makes sense to speak of its altitude. -Examples 1) For planetary rings that can be modelled as flat disks with elliptical outer boundaries, the distance of a point in space from a ring's outer boundary can be computed using this routine. Suppose center, smajor, and sminor are the center, semi-major axis, and semi-minor axis of the ring's boundary. Suppose also that scpos is the position of a spacecraft. scpos, center, smajor, and sminor must all be expressed in the same coordinate system. We can find the distance from the spacecraft to the ring using the code fragment #include "SpiceUsr.h" . . . /. Make a CSPICE ellipse representing the ring, then use npelpt_c to find the distance between the spacecraft position and RING. ./ cgv2el_c ( center, smajor, sminor, ring ); npelpt_c ( scpos, ring, pnear, &dist ); 2) The problem of finding the distance of a line from a tri-axial ellipsoid can be reduced to the problem of finding the distance between the same line and an ellipse; this problem in turn can be reduced to the problem of finding the distance between an ellipse and a point. The routine npedln_c carries out this process and uses npelpt_c to find the ellipse-to-point distance. -Restrictions None. -Literature_References None. -Author_and_Institution N.J. Bachman (JPL) -Version -CSPICE Version 1.0.0, 02-SEP-1999 (NJB) -Index_Entries nearest point on ellipse to point -& */ { /* Begin npelpt_c */ /* Local variables */ SpiceDouble center [3]; SpiceDouble majlen; SpiceDouble minlen; SpiceDouble rotate [3][3]; SpiceDouble scale; SpiceDouble smajor [3]; SpiceDouble sminor [3]; SpiceDouble tmppnt [3]; SpiceDouble prjpnt [3]; /* Participate in error tracing. */ chkin_c ( "npelpt_c" ); /* Here's an overview of our solution: Let ELPL be the plane containing the ELLIPS, and let PRJ be the orthogonal projection of the POINT onto ELPL. Let X be any point in the plane ELPL. According to the Pythagorean Theorem, 2 2 2 || POINT - X || = || POINT - PRJ || + || PRJ - X ||. Then if we can find a point X on ELLIPS that minimizes the rightmost term, that point X is the closest point on the ellipse to POINT. So, we find the projection PRJ, and then solve the problem of finding the closest point on ELLIPS to PRJ. To solve this problem, we find a triaxial ellipsoid whose intersection with the plane ELPL is precisely ELLIPS, and two of whose axes lie in the plane ELPL. The closest point on ELLIPS to PRJ is also the closest point on the ellipsoid to ELLIPS. But we have the SPICELIB routine NEARPT on hand to find the closest point on an ellipsoid to a specified point, so we've reduced our problem to a solved problem. There is a subtle point to worry about here: if PRJ is outside of ELLIPS (PRJ is in the same plane as ELLIPS, so `outside' does make sense here), then the closest point on ELLIPS to PRJ coincides with the closest point on the ellipsoid to PRJ, regardless of how we choose the z-semi-axis length of the ellipsoid. But the correspondence may be lost if PRJ is inside the ellipse, if we don't choose the z-semi-axis length correctly. Though it takes some thought to verify this (and we won't prove it here), making the z-semi-axis of the ellipsoid longer than the other two semi-axes is sufficient to maintain the coincidence of the closest point on the ellipsoid to PRJPNT and the closest point on the ellipse to PRJPNT. */ /* Find the ellipse's center and semi-axes. */ el2cgv_c ( ellips, center, smajor, sminor ); /* Find the lengths of the semi-axes, and scale the vectors to try to prevent arithmetic unpleasantness. Degenerate ellipses are turned away at the door. */ minlen = vnorm_c (sminor); majlen = vnorm_c (smajor); if ( MinVal ( majlen, minlen ) == 0.0 ) { setmsg_c ( "Ellipse semi-axis lengths: # #." ); errdp_c ( "#", majlen ); errdp_c ( "#", minlen ); sigerr_c ( "SPICE(DEGENERATECASE)" ); chkout_c ( "npelpt_c" ); return; } scale = 1.0 / majlen; vscl_c ( scale, smajor, smajor ); vscl_c ( scale, sminor, sminor ); /* Translate ellipse and point so that the ellipse is centered at the origin. Scale the point's coordinates to maintain the correct relative position to the scaled ellipse. */ vsub_c ( point, center, tmppnt ); vscl_c ( scale, tmppnt, tmppnt ); /* We want to reduce the problem to a two-dimensional one. We'll work in a coordinate system whose x- and y- axes are aligned with the semi-major and semi-minor axes of the input ellipse. The z-axis is picked to give us a right-handed system. We find the matrix that transforms coordinates to our new system using twovec_c. */ twovec_c ( smajor, 1, sminor, 2, rotate ); /* Apply the coordinate transformation to our scaled input point. */ mxv_c ( rotate, tmppnt, tmppnt ); /* We must find the distance between the orthogonal projection of tmppnt onto the x-y plane and the ellipse. The projection is just ( TMPPNT[0], TMPPNT[1], 0 ); we'll call this projection prjpnt. */ vpack_c ( tmppnt[0], tmppnt[1], 0.0, prjpnt ); /* Now we're ready to find the distance between and a triaxial ellipsoid whose intersection with the x-y plane is the ellipse and whose third semi-axis lies on the z-axis. Because we've scaled the ellipse's axes so as to give the longer axis length 1, a length of 2.0 suffices for the ellipsoid's z-semi-axis. Find the nearest point to prjpnt on the ellipoid, pnear. */ nearpt_c ( prjpnt, 1.0, minlen/majlen, 2.0, pnear, dist ); /* Scale the near point coordinates back to the original scale. */ vscl_c ( majlen, pnear, pnear ); /* Apply the required inverse rotation and translation to pnear. Compute the point-to-ellipse distance. */ mtxv_c ( rotate, pnear, pnear ); vadd_c ( pnear, center, pnear ); *dist = vdist_c ( pnear, point ); chkout_c ( "npelpt_c" ); } /* End npelpt_c */
SpiceDouble mind_c ( SpiceInt n, ... ) /* -Brief_I/O Variable I/O Description -------- --- -------------------------------------------------- n I The number of double precision values to compare. ... I The numbers to be compared, separated by commas. -Detailed_Input n is the number of double precision values in the set whose minimum is to be determined. ... represents a variable argument list. The number of double precision values supplied must be that indicated by n. The values are separated by commas. Section 5.2.4.1 of the ANSI C Standard, titled "Translation Limits," specifies that argument lists containing at least 31 items must be supported. In the interest of portability, no more than 30 double precision values should be supplied. -Detailed_Output The function returns the minimum of the set of input double precision values. -Parameters None. -Exceptions Error free. 1) If n is less than 1, the value 0.0 is returned. 2) If the number of double precision values supplied does not match the argument n, the action of this routine is not defined. 3) If the number of double precision values supplied exceeds 30, the action of this routine is not defined. -Files None. -Particulars None. -Examples 1) Find the minimum of four double precision values. #include "SpiceUsr.h" . . . SpiceDouble min; SpiceDouble a; SpiceDouble b; SpiceDouble c; SpiceDouble d; . . . min = mind_c ( 4, a, b, c, d ); -Restrictions 1) The ANSI C Standard specifies that argument lists containing 31 actual arguments must be supported. Larger sets of values may not be handled properly by this routine. -Literature_References 1) "American National Standard for Programming Languages---C." Section 5.4.2.1, "Translation Limits," p. 13. Published by American National Standards Institute, 11 West 42nd St., New York, NY 10035. Copyright 1990. -Author_and_Institution N.J. Bachman (JPL) -Version -CSPICE Version 1.0.1, 11-NOV-2006 (EDW) Added "None." text to Particulars section, required for API doc script (cspicehtml.pl) integrity checks. -CSPICE Version 1.0.0, 16-SEP-1999 (NJB) -Index_Entries minimum of double precision values -& */ { /* Begin mind_c */ /* Local variables */ SpiceDouble next; SpiceDouble retval; SpiceInt i; /* ap is the argument pointer. Its type va_list is declared in the header stdarg.h. */ va_list ap; /* If there are no values to compare, return zero. */ if ( n < 1 ) { return ( 0.0 ); } /* Initialize the argument pointer with the last named argument, namely n. */ va_start ( ap, n ); /* Initialize the minimum with the first value. */ retval = va_arg ( ap, double ); /* Now compute a running minimum of the values, if there are more. By the way, we capture the argument in the variable next rather than make the va_arg call as a MinVal argument, because the MinVal macro would make the va_arg call twice. */ for ( i = 1; i < n; i++ ) { next = va_arg ( ap, double ); retval = MinVal ( retval, next ); } /* Terminate the argument fetching process. */ va_end ( ap ); /* Return the value we've found. */ return ( retval ); } /* End mind_c */