25 extern int refchg_(integer *frame1, integer *frame2, doublereal *et,
27 extern int frmchg_(integer *frame1, integer *frame2, doublereal *et,
29 extern int invstm_(doublereal *mat, doublereal *invmat);
32 extern int ck3sdn(
double sdntol,
bool avflag,
int *nrec,
33 double *sclkdp,
double *quats,
double *avvs,
34 int nints,
double *starts,
double *dparr,
99 QString key =
"INS" +
toString(frameCode) +
"_TRANSX";
100 SpiceDouble transX[2];
104 gdpool_c(key.toAscii().data(), 1, 2, &number, transX, &found);
107 QString msg =
"Cannot find [" + key +
"] in text kernels";
112 if (transX[0] < transX[1])
p_axisV = 1;
147 for (
int i = 0; i < 3; i++)
221 if (
p_et == et)
return;
226 SetEphemerisTimeMemcache();
231 SetEphemerisTimePolyFunction();
235 SetEphemerisTimePolyFunctionOverSpice();
239 SetEphemerisTimeSpice();
245 SetEphemerisTimeNadir();
293 QString msg =
"Argument cacheSize must not be less or equal to zero";
297 if (startTime > endTime) {
298 QString msg =
"Argument startTime must be less than or equal to endTime";
302 if ((startTime != endTime) && (size == 1)) {
303 QString msg =
"Cache size must be more than 1 if startTime endTime differ";
309 QString msg =
"A SpiceRotation cache has already been created";
325 for (
int i = 0; i < cacheSize; i++) {
389 for (
int i = 0; i < labelTimeFrames.
size(); i++) {
402 for (
int i = 0; i < labelConstantFrames.
size(); i++) {
407 for (
int i = 0; i < labelConstantRotation.
size(); i++) {
413 ident_c((SpiceDouble( *)[3]) &
p_TC[0]);
427 int recFields = table[0].Fields();
433 if (recFields == 5) {
434 for (
int r = 0; r < table.
Records(); r++) {
437 if (rec.
Fields() != recFields) {
441 std::vector<double> j2000Quat;
442 j2000Quat.push_back((
double)rec[0]);
443 j2000Quat.push_back((
double)rec[1]);
444 j2000Quat.push_back((
double)rec[2]);
445 j2000Quat.push_back((
double)rec[3]);
448 std::vector<double> CJ = q.
ToMatrix();
456 else if (recFields == 8) {
457 for (
int r = 0; r < table.
Records(); r++) {
460 if (rec.
Fields() != recFields) {
464 std::vector<double> j2000Quat;
465 j2000Quat.push_back((
double)rec[0]);
466 j2000Quat.push_back((
double)rec[1]);
467 j2000Quat.push_back((
double)rec[2]);
468 j2000Quat.push_back((
double)rec[3]);
472 std::vector<double> CJ = q.
ToMatrix();
475 std::vector<double> av;
476 av.push_back((
double)rec[4]);
477 av.push_back((
double)rec[5]);
478 av.push_back((
double)rec[6]);
488 else if (recFields == 3) {
489 std::vector<double> coeffAng1, coeffAng2, coeffAng3;
491 for (
int r = 0; r < table.
Records() - 1; r++) {
494 if (rec.
Fields() != recFields) {
497 coeffAng1.push_back((
double)rec[0]);
498 coeffAng2.push_back((
double)rec[1]);
499 coeffAng3.push_back((
double)rec[2]);
504 double baseTime = (double)rec[0];
505 double timeScale = (double)rec[1];
506 double degree = (double)rec[2];
515 QString msg =
"Expecting either three, five, or eight fields in the SpiceRotation table";
549 for (std::vector<double>::size_type pos = 0; pos <
p_cacheTime.size(); pos++) {
575 for (std::vector<double>::size_type pos = 0; pos < maxSize; pos++) {
582 QString msg =
"The SpiceRotation has not yet been fit to a function";
609 QString msg =
"Only cached rotations can be returned as a line cache of quaternions and time";
613 return Cache(tableName);
674 Table table(tableName, record);
676 for (
int i = 0; i < (int)
p_cache.size(); i++) {
712 Table table(tableName, record);
714 for (
int cindex = 0; cindex <
p_degree + 1; cindex++) {
725 record[2] = (double) p_degree;
733 QString msg =
"To create table source of data must be either Memcache or PolyFunction";
767 for (
int i = 0; i < (int)
p_TC.size(); i++) {
809 SpiceDouble ang1, ang2, ang3;
810 m2eul_c((SpiceDouble *) &
p_CJ[0], axis3, axis2, axis1, &ang3, &ang2, &ang1);
812 std::vector<double> angles;
813 angles.push_back(ang1);
814 angles.push_back(ang2);
815 angles.push_back(ang3);
862 std::vector<double> jVec;
864 if (rVec.size() == 3) {
866 mxm_c((SpiceDouble *) &
p_TC[0], (SpiceDouble *) &
p_CJ[0], TJ);
868 mtxv_c(TJ, (SpiceDouble *) &rVec[0], (SpiceDouble *) &jVec[0]);
870 else if (rVec.size() == 6) {
876 std::vector<double> stateTJ(36);
880 xpose6_c(&stateTJ[0], (SpiceDouble( *) [6]) &stateTJ[0]);
881 double stateJT[6][6];
882 invstm_((doublereal *) &stateTJ[0], (doublereal *) stateJT);
883 xpose6_c(stateJT, stateJT);
886 mxvg_c(stateJT, (SpiceDouble *) &rVec[0], 6, 6, (SpiceDouble *) &jVec[0]);
905 std::vector<double> rVec(3);
907 if (jVec.size() == 3) {
909 mxm_c((SpiceDouble *) &
p_TC[0], (SpiceDouble *) &
p_CJ[0], TJ);
911 mxv_c(TJ, (SpiceDouble *) &jVec[0], (SpiceDouble *) &rVec[0]);
913 else if (jVec.size() == 6) {
919 std::vector<double> stateTJ(36);
922 mxvg_c((SpiceDouble *) &stateTJ[0], (SpiceDouble *) &jVec[0], 6, 6, (SpiceDouble *) &rVec[0]);
940 std::vector<double> coeffAng1, coeffAng2, coeffAng3;
954 else if (
p_cache.size() == 2) {
977 std::vector<double> time;
983 coeffAng1.push_back(angles[0]);
984 coeffAng2.push_back(angles[1]);
985 coeffAng3.push_back(angles[2]);
987 else if (
p_cache.size() == 2) {
1000 angles2[0] =
WrapAngle(angles1[0], angles2[0]);
1001 angles2[2] =
WrapAngle(angles1[2], angles2[2]);
1003 double intercept[3];
1006 for (
int angleIndex = 0; angleIndex < 3; angleIndex++) {
1008 slope[angleIndex] = angline.
Slope();
1009 intercept[angleIndex] = angline.
Intercept();
1011 coeffAng1.push_back(intercept[0]);
1012 coeffAng1.push_back(slope[0]);
1013 coeffAng2.push_back(intercept[1]);
1014 coeffAng2.push_back(slope[1]);
1015 coeffAng3.push_back(intercept[2]);
1016 coeffAng3.push_back(slope[2]);
1023 for (std::vector<double>::size_type pos = 0; pos <
p_cacheTime.size(); pos++) {
1035 angles[0] =
WrapAngle(start1, angles[0]);
1036 angles[2] =
WrapAngle(start3, angles[2]);
1039 fitAng1->
AddKnown(time, angles[0]);
1040 fitAng2->
AddKnown(time, angles[1]);
1041 fitAng3->
AddKnown(time, angles[2]);
1089 const std::vector<double>& coeffAng2,
1090 const std::vector<double>& coeffAng3,
1141 std::vector<double>& coeffAng2,
1142 std::vector<double>& coeffAng3) {
1197 if (coeffIndex > 0 && coeffIndex <=
p_degree) {
1198 derivative = pow(time, coeffIndex);
1200 else if (coeffIndex == 0) {
1233 int angleIndex = partialVar;
1235 double angle = angles.at(angleIndex);
1237 double dmatrix[3][3];
1238 drotat_(&angle, (integer *) axes + angleIndex, (doublereal *) dmatrix);
1240 xpose_c(dmatrix, dmatrix);
1247 for (
int row = 0; row < 3; row++) {
1248 for (
int col = 0; col < 3; col++) {
1249 dmatrix[row][col] *= dpoly;
1254 switch(angleIndex) {
1256 rotmat_c(dmatrix, angles[1], axes[1], dCJ);
1257 rotmat_c(dCJ, angles[2], axes[2], dCJ);
1260 rotate_c(angles[0], axes[0], dCJ);
1261 mxm_c(dmatrix, dCJ, dCJ);
1262 rotmat_c(dCJ, angles[2], axes[2], dCJ);
1265 rotate_c(angles[0], axes[0], dCJ);
1266 rotmat_c(dCJ, angles[1], axes[1], dCJ);
1267 mxm_c(dmatrix, dCJ, dCJ);
1273 mxm_c((SpiceDouble *) &
p_TC[0], dCJ[0], dTJ);
1276 std::vector<double> lookdT(3);
1278 mxv_c(dTJ, (
const SpiceDouble *) &lookJ[0], (SpiceDouble *) &lookdT[0]);
1295 double diff1 = compareAngle - angle;
1297 if (diff1 < -1 * pi_c()) {
1300 else if (diff1 > pi_c()) {
1338 for (
int icoef =
p_degree + 1; icoef <= degree; icoef++) {
1339 coefAngle1.push_back(0.);
1340 coefAngle2.push_back(0.);
1341 coefAngle3.push_back(0.);
1348 std::vector<double> coefAngle1(degree + 1),
1349 coefAngle2(degree + 1),
1350 coefAngle3(degree + 1);
1352 for (
int icoef = 0; icoef <= degree; icoef++) {
1405 if (axis1 < 1 || axis2 < 1 || axis3 < 1 || axis1 > 3 || axis2 > 3 || axis3 > 3) {
1406 QString msg =
"A rotation axis is outside the valid range of 1 to 3";
1424 double currentTime = observStart;
1425 bool timeLoaded =
false;
1430 ktotal_c(
"ck", (SpiceInt *) &count);
1439 Isis::IString msg =
"Full cache size does NOT match cache size in LoadTimeCache -- should never happen";
1450 SpiceDouble CJ[9] = {
p_cache[r][0],
p_cache[r][1], p_cache[r][2],
1451 p_cache[r][3], p_cache[r][4], p_cache[r][5],
1452 p_cache[r][6], p_cache[r][7], p_cache[r][8]
1454 m2q_c(CJ, quats[r]);
1456 vequ_c((SpiceDouble *) &
p_cacheAv[r][0], avvs[r]);
1460 double cubeStarts = timeSclkdp[0];
1461 double radTol = 0.000000017453;
1462 SpiceInt avflag = 1;
1468 ck3sdn(radTol, avflag, (
int *) &sizOut, timeSclkdp, (doublereal *) quats,
1469 (SpiceDouble *) avvs, nints, &cubeStarts, dparr, (
int *) intarr);
1475 std::vector<double> av;
1478 for (
int r = 0; r < sizOut; r++) {
1483 std::vector<double> CJ(9);
1484 q2m_c(quats[r], (SpiceDouble( *)[3]) &CJ[0]);
1486 vequ_c(avvs[r], (SpiceDouble *) &av[0]);
1500 int SOURCESIZ = 128;
1503 SpiceChar file[FILESIZ];
1504 SpiceChar filtyp[TYPESIZ];
1505 SpiceChar source[SOURCESIZ];
1508 bool observationSpansToNextSegment =
false;
1513 kdata_c(0,
"ck", FILESIZ, TYPESIZ, SOURCESIZ, file, filtyp, source, &handle, &found);
1519 observationSpansToNextSegment =
false;
1530 dafus_c(sum, (SpiceInt) 2, (SpiceInt) 6, dc, ic);
1533 if (ic[2] == 5)
break;
1536 if (ic[0] == spCode && ic[2] == 3) {
1537 sct2e_c((
int) spCode / 1000, dc[0], &segStartEt);
1538 sct2e_c((
int) spCode / 1000, dc[1], &segStopEt);
1543 if (currentTime >= segStartEt && currentTime <= segStopEt) {
1547 if (observationSpansToNextSegment && currentTime > segStartEt) {
1548 QString msg =
"Observation crosses segment boundary--unable to interpolate pointing";
1551 if (observEnd > segStopEt) {
1552 observationSpansToNextSegment =
true;
1556 int dovelocity = ic[3];
1559 dafgda_c(handle, end - 1, end, val);
1561 int ninstances = (int) val[1];
1562 int numvel = dovelocity * 3;
1563 int quatnoff = ic[4] + (4 + numvel) * ninstances - 1;
1565 int sclkdp1off = quatnoff + 1;
1566 int sclkdpnoff = sclkdp1off + ninstances - 1;
1569 int sclkSpCode = spCode / 1000;
1572 std::vector<double> sclkdp(ninstances);
1573 dafgda_c(handle, sclkdp1off, sclkdpnoff, (SpiceDouble *) &sclkdp[0]);
1576 sct2e_c(sclkSpCode, sclkdp[0], &et);
1578 while (instance < (ninstances - 1) && et < currentTime) {
1580 sct2e_c(sclkSpCode, sclkdp[instance], &et);
1583 if (instance > 0) instance--;
1584 sct2e_c(sclkSpCode, sclkdp[instance], &et);
1586 while (instance < (ninstances - 1) && et < observEnd) {
1589 sct2e_c(sclkSpCode, sclkdp[instance], &et);
1593 if (!observationSpansToNextSegment) {
1599 currentTime = segStopEt;
1608 QString msg =
"No camera kernels loaded...Unable to determine time cache to downsize";
1615 double cacheSlope = 0.0;
1632 QString msg =
"Time cache not available -- rerun spiceinit";
1636 std::vector<double> fullCacheTime;
1637 double cacheSlope = 0.0;
1643 return fullCacheTime;
1658 std::vector<int> frameCodes;
1659 std::vector<int> frameTypes;
1662 while (frameCodes[frameCodes.size()-1] != J2000Code) {
1663 frmidx = frameCodes.size() - 1;
1665 frinfo_c((SpiceInt) frameCodes[frmidx], (SpiceInt *) ¢er, (SpiceInt *) &type, (SpiceInt *) &typid, &found);
1670 frameTypes.push_back(0);
1674 QString msg =
"The frame" +
toString((
int) frameCodes[frmidx]) +
" is not supported by Naif";
1678 double matrix[3][3];
1681 if (type == INERTL || type == PCK) {
1682 nextFrame = J2000Code;
1684 else if (type == CK) {
1685 ckfrot_((SpiceInt *) &typid, &et, (
double *) matrix, &nextFrame, (logical *) &found);
1690 frameTypes.push_back(0);
1694 QString msg =
"The ck rotation from frame " +
toString(frameCodes[frmidx]) +
" can not be found"
1695 +
" due to no pointing available at requested time or a problem with the frame";
1699 else if (type == TK) {
1700 tkfram_((SpiceInt *) &typid, (
double *) matrix, &nextFrame, (logical *) &found);
1702 QString msg =
"The tk rotation from frame " +
toString(frameCodes[frmidx]) +
" can not be found";
1706 else if (type == DYN) {
1713 zzdynrot_((SpiceInt *) &typid, (SpiceInt *) ¢er, &et, (
double *) matrix, &nextFrame);
1717 QString msg =
"The frame " +
toString(frameCodes[frmidx]) +
1718 " has a type " +
toString(type) +
" not supported by your version of Naif Spicelib." +
1719 "You need to update.";
1723 frameCodes.push_back(nextFrame);
1724 frameTypes.push_back(type);
1735 while (frameTypes[nConstants] == TK && nConstants < (
int) frameTypes.size()) nConstants++;
1738 for (
int i = 0; i <= nConstants; i++) {
1743 for (
int i = nConstants; i < (int) frameCodes.size(); i++) {
1761 std::vector<double> TJ;
1763 mxm_c((SpiceDouble *) &
p_TC[0], (SpiceDouble *) &
p_CJ[0], (SpiceDouble( *) [3]) &TJ[0]);
1775 std::vector<double> q;
1777 m2q_c((SpiceDouble( *)[3]) &
p_TC[0], &q[0]);
1797 p_TC = constantMatrix;
1807 std::vector<double> q;
1809 m2q_c((SpiceDouble( *)[3]) &
p_CJ[0], &q[0]);
1828 p_CJ = timeBasedMatrix;
1841 refchg_((SpiceInt *) &fromFrame, (SpiceInt *) &targetFrame, &et, (doublereal *) &
p_TC[0]);
1843 xpose_c((SpiceDouble( *)[3]) &
p_TC[0], (SpiceDouble( *)[3]) &
p_TC[0]);
1870 QString msg =
"The SpiceRotation pointing angles must be fit to polynomials in order to compute angular velocity";
1874 std::vector<double> dCJdt;
1878 mtxm_c((SpiceDouble( *)[3]) &dCJdt[0], (SpiceDouble( *)[3]) &
p_CJ[0], omega);
1879 p_av[0] = omega[2][1];
1880 p_av[1] = omega[0][2];
1881 p_av[2] = omega[1][0];
1900 double dmatrix[3][3];
1902 double wmatrix[3][3];
1905 for (
int angleIndex = 0; angleIndex < 3; angleIndex++) {
1906 drotat_(&(angles[angleIndex]), (integer *) axes + angleIndex, (doublereal *) dmatrix);
1908 xpose_c(dmatrix, dmatrix);
1920 for (
int row = 0; row < 3; row++) {
1921 for (
int col = 0; col < 3; col++) {
1922 dmatrix[row][col] *= dangle;
1926 switch(angleIndex) {
1928 rotmat_c(dmatrix, angles[1], axes[1], dmatrix);
1929 rotmat_c(dmatrix, angles[2], axes[2], dmatrix);
1932 rotate_c(angles[0], axes[0], wmatrix);
1933 mxm_c(dmatrix, wmatrix, dmatrix);
1934 rotmat_c(dmatrix, angles[2], axes[2], dmatrix);
1937 rotate_c(angles[0], axes[0], wmatrix);
1938 rotmat_c(wmatrix, angles[1], axes[1], wmatrix);
1939 mxm_c(dmatrix, wmatrix, dmatrix);
1943 for (
int index = 0; index < 9; index++) {
1946 dCJ[index] += dmatrix[i][j];
1957 std::vector<double> stateTJ(36);
1960 double stateCJ[6][6];
1961 rav2xf_c(&
p_CJ[0], &
p_av[0], stateCJ);
1967 for (
int row = 3; row < 6; row++) {
1971 for (
int col = 0; col < 3; col++) {
1974 stateTJ[irow*6 + col] =
p_TC[vpos] * stateCJ[0][col] +
p_TC[vpos+1] * stateCJ[1][col] +
p_TC[vpos+2] * stateCJ[2][col];
1976 stateTJ[row*6 + col] =
p_TC[vpos] * stateCJ[3][col] +
p_TC[vpos+1] * stateCJ[4][col] +
p_TC[vpos+2] * stateCJ[5][col];
1978 stateTJ[irow*6 + jcol] = 0;
1980 stateTJ[row*6 +jcol] = stateTJ[irow*6 + col];
2001 double diffTime = timeEt -
p_et;
2002 std::vector<double> CJ(9, 0.0);
2006 axisar_c((SpiceDouble *) &
p_av[0], diffTime*vnorm_c((SpiceDouble *) &
p_av[0]), dmat);
2009 mxm_c(dmat, (SpiceDouble *) &
p_CJ[0], (SpiceDouble( *)[3]) &CJ[0]);
2028 void SpiceRotation::SetEphemerisTimeMemcache() {
2044 std::vector<double>::iterator pos;
2057 if (cacheIndex < 0) cacheIndex = 0;
2064 std::vector<double> CJ2(
p_cache[cacheIndex+1]);
2065 std::vector<double> CJ1(
p_cache[cacheIndex]);
2066 SpiceDouble J2J1[3][3];
2067 mtxm_c((SpiceDouble( *)[3]) &CJ2[0], (SpiceDouble( *)[3]) &CJ1[0], J2J1);
2068 SpiceDouble axis[3];
2070 raxisa_c(J2J1, axis, &angle);
2071 SpiceDouble delta[3][3];
2072 axisar_c(axis, angle * (SpiceDouble)mult, delta);
2073 mxmt_c((SpiceDouble *) &CJ1[0], delta, (SpiceDouble( *) [3]) &
p_CJ[0]);
2076 double v1[3], v2[3];
2077 vequ_c((SpiceDouble *) &
p_cacheAv[cacheIndex][0], v1);
2078 vequ_c((SpiceDouble *) &
p_cacheAv[cacheIndex+1][0], v2);
2079 vscl_c((1. - mult), v1, v1);
2080 vscl_c(mult, v2, v2);
2081 vadd_c(v1, v2, (SpiceDouble *) &
p_av[0]);
2087 void SpiceRotation::SetEphemerisTimeNadir() {
2096 SpiceDouble stateJ[6];
2099 spkez_c((SpiceInt) spkCode,
p_et,
"J2000",
"LT+S",
2103 SpiceDouble sJ[3], svJ[3];
2104 vpack_c(-1 * stateJ[0], -1 * stateJ[1], -1 * stateJ[2], sJ);
2105 vpack_c(stateJ[3], stateJ[4], stateJ[5], svJ);
2110 (SpiceDouble( *)[3]) &
p_CJ[0]);
2114 void SpiceRotation::SetEphemerisTimeSpice() {
2115 SpiceInt j2000 = J2000Code;
2124 double stateCJ[6][6];
2125 frmchg_((integer *) &j2000, (integer *) &toFrame, &time, (doublereal *) stateCJ);
2130 SpiceBoolean ckfailure = failed_c();
2134 xpose6_c(stateCJ, stateCJ);
2135 xf2rav_c(stateCJ, (SpiceDouble( *)[3]) &
p_CJ[0], (SpiceDouble *) &
p_av[0]);
2139 refchg_((integer *) &j2000, (integer *) &toFrame, &time, (SpiceDouble *) &
p_CJ[0]);
2143 getmsg_c(
"SHORT",
sizeof(naifstr), naifstr);
2146 if (eqstr_c(naifstr,
"SPICE(UNKNOWNFRAME)")) {
2148 "reference frame code. Has the mission frames kernel been loaded?";
2152 Isis::IString msg =
"No pointing available at requested time [" +
2160 xpose_c((SpiceDouble( *)[3]) &
p_CJ[0], (SpiceDouble( *)[3]) &
p_CJ[0]);
2165 std::vector<double> SpiceRotation::EvaluatePolyFunction() {
2175 std::vector<double> rtime;
2177 std::vector<double> angles;
2178 angles.push_back(function1.Evaluate(rtime));
2179 angles.push_back(function2.Evaluate(rtime));
2180 angles.push_back(function3.Evaluate(rtime));
2183 if (angles[0] < -1 * pi_c()) {
2184 angles[0] += twopi_c();
2186 else if (angles[0] > pi_c()) {
2187 angles[0] -= twopi_c();
2193 void SpiceRotation::SetEphemerisTimePolyFunction() {
2203 std::vector<double> rtime;
2205 double angle1 = function1.Evaluate(rtime);
2206 double angle2 = function2.Evaluate(rtime);
2207 double angle3 = function3.Evaluate(rtime);
2210 if (angle1 < -1 * pi_c()) {
2211 angle1 += twopi_c();
2213 else if (angle1 > pi_c()) {
2214 angle1 -= twopi_c();
2217 eul2m_c((SpiceDouble) angle3, (SpiceDouble) angle2, (SpiceDouble) angle1,
2219 (SpiceDouble( *)[3]) &
p_CJ[0]);
2230 void SpiceRotation::SetEphemerisTimePolyFunctionOverSpice() {
2231 SetEphemerisTimeMemcache();
2232 std::vector<double> cacheAngles(3);
2233 std::vector<double> cacheVelocity(3);
2235 cacheVelocity =
p_av;
2236 SetEphemerisTimePolyFunction();
2237 std::vector<double> polyAngles(3);
2240 polyAngles = EvaluatePolyFunction();
2241 std::vector<double> polyVelocity(3);
2242 polyVelocity =
p_av;
2243 std::vector<double> angles(3);
2245 for (
int index = 0; index < 3; index++) {
2246 angles[index] = cacheAngles[index] + polyAngles[index];
2247 p_av[index] += cacheVelocity[index];
2250 if (angles[0] < -1 * pi_c()) {
2251 angles[0] += twopi_c();
2253 else if (angles[0] > pi_c()) {
2254 angles[0] -= twopi_c();
2257 if (angles[2] < -1 * pi_c()) {
2258 angles[2] += twopi_c();
2260 else if (angles[2] > pi_c()) {
2261 angles[2] -= twopi_c();
2264 eul2m_c((SpiceDouble) angles[2], (SpiceDouble) angles[1], (SpiceDouble) angles[0],
2266 (SpiceDouble( *)[3]) &
p_CJ[0]);