void CIrrMeshFileLoader::readMeshBuffer(io::IXMLReader* reader, int vertexCount, SMeshBufferLightMap* sbuffer)
{
	core::stringc data = reader->getNodeData();
	const c8* p = &data[0];

	if (sbuffer)
	{
		video::S3DVertex2TCoords vtx;

		for (int i=0; i<vertexCount && *p; ++i)
		{
			// position

			findNextNoneWhiteSpace(&p);
			vtx.Pos.X = readFloat(&p);
			findNextNoneWhiteSpace(&p);
			vtx.Pos.Y = readFloat(&p);
			findNextNoneWhiteSpace(&p);
			vtx.Pos.Z = readFloat(&p);

			// normal

			findNextNoneWhiteSpace(&p);
			vtx.Normal.X = readFloat(&p);
			findNextNoneWhiteSpace(&p);
			vtx.Normal.Y = readFloat(&p);
			findNextNoneWhiteSpace(&p);
			vtx.Normal.Z = readFloat(&p);

			// color

			findNextNoneWhiteSpace(&p);
			sscanf(p, "%08x", &vtx.Color.color);
			skipCurrentNoneWhiteSpace(&p);

			// tcoord1

			findNextNoneWhiteSpace(&p);
			vtx.TCoords.X = readFloat(&p);
			findNextNoneWhiteSpace(&p);
			vtx.TCoords.Y = readFloat(&p);

			// tcoord2

			findNextNoneWhiteSpace(&p);
			vtx.TCoords2.X = readFloat(&p);
			findNextNoneWhiteSpace(&p);
			vtx.TCoords2.Y = readFloat(&p);

			sbuffer->Vertices.push_back(vtx);
		}
	}
}
PathSegmentData SVGPathByteStreamSource::parseSegment()
{
    ASSERT(hasMoreData());
    PathSegmentData segment;
    segment.command = static_cast<SVGPathSegType>(readSVGSegmentType());

    switch (segment.command) {
    case PathSegCurveToCubicRel:
    case PathSegCurveToCubicAbs:
        segment.point1 = readFloatPoint();
        /* fall through */
    case PathSegCurveToCubicSmoothRel:
    case PathSegCurveToCubicSmoothAbs:
        segment.point2 = readFloatPoint();
        /* fall through */
    case PathSegMoveToRel:
    case PathSegMoveToAbs:
    case PathSegLineToRel:
    case PathSegLineToAbs:
    case PathSegCurveToQuadraticSmoothRel:
    case PathSegCurveToQuadraticSmoothAbs:
        segment.targetPoint = readFloatPoint();
        break;
    case PathSegLineToHorizontalRel:
    case PathSegLineToHorizontalAbs:
        segment.targetPoint.setX(readFloat());
        break;
    case PathSegLineToVerticalRel:
    case PathSegLineToVerticalAbs:
        segment.targetPoint.setY(readFloat());
        break;
    case PathSegClosePath:
        break;
    case PathSegCurveToQuadraticRel:
    case PathSegCurveToQuadraticAbs:
        segment.point1 = readFloatPoint();
        segment.targetPoint = readFloatPoint();
        break;
    case PathSegArcRel:
    case PathSegArcAbs: {
        segment.arcRadii() = readFloatPoint();
        segment.setArcAngle(readFloat());
        segment.arcLarge = readFlag();
        segment.arcSweep = readFlag();
        segment.targetPoint = readFloatPoint();
        break;
    }
    default:
        ASSERT_NOT_REACHED();
    }
    return segment;
}
Example #3
0
/** ------------------------------------------------------------------------ **
 * \internal                                                                  *
 * \brief Get a Translate Transform                                           *
 *                                                                            *
 * \param pDecISF structure used to decode the ISF file.                      *
 *                                                                            *
 * \returns the error code given while processing                             *
 ** ------------------------------------------------------------------------ **/
int getTransformTranslate (decodeISF_t * pDecISF)
{
    int err = OK;
    transform_t * pTransform;

    /**
     * This tag consists of 2 values describing a translate transform matrix.\n
     * Those two values are coded in the stream as floats (IEEE 754)\n
     * We have in order:
     * - dx
     * - dy
     *
     * The transform matrix is :\n
     * \f[
     *	\mbox{T} = \left( \begin{array}{ccc} 0 & 0 & \mbox{dx} \\ 0 & 0 & \mbox{dy} \\ 0 & 0 & 1\\ \end{array} \right)
     * \f]
     *
     * In fact the transform matrix shouldn't be like that cause that
     * transformation don't translate.\n
     * Anyway, it seems to work this way with the .Net 3.0 framework ...
     * The transform matrix should be :\n
     * \f[
     *	\mbox{T} = \left( \begin{array}{ccc} \mbox{1} & 0 & \mbox{dx} \\ 0 & \mbox{1} & \mbox{dy} \\ 0 & 0 & 1\\ \end{array} \right)
     * \f]
     */

    /* Check whether we should add a transform or use the default one */
    if (pDecISF->lastTransform != &(pDecISF->transforms) )
    {
        err = createTransform(&pTransform);
        if (err != OK)
            return err;
    } else {
        pTransform = *(pDecISF->lastTransform);
    }

    err = readFloat (pDecISF, &pTransform->m13);
    if (err != OK) return err;
    err = readFloat (pDecISF, &pTransform->m23);
    if (err != OK) return err;

    LOG(stdout,"(TRANSFORM_TRANSLATE) m13 = %f\n", pTransform->m13);
    LOG(stdout,"(TRANSFORM_TRANSLATE) m23 = %f\n", pTransform->m23);

    /* Insert the current Transform */
    *(pDecISF->lastTransform) = pTransform;
    pDecISF->lastTransform = &(pTransform->next);

    return err;
}
Example #4
0
void readHotstartFile(void)
//
//  Input:   none
//  Output:  none
//  Purpose: reads initial state of all nodes and links from hotstart file.
//
{
    int   i, j;
    long  pos, size;
    float x;

    // --- check that file has correct size
    pos = ftell(Fhotstart1.file);
    fseek(Fhotstart1.file, 0L, SEEK_END);
    size = ( ftell(Fhotstart1.file) - pos ) / sizeof(float);
    if ( size < Nobjects[NODE] * (2 + 2*Nobjects[POLLUT]) +
                Nobjects[LINK] * (3 + Nobjects[POLLUT]) )
    {
         report_writeErrorMsg(ERR_HOTSTART_FILE_READ, "");
         return;
    }
    fseek(Fhotstart1.file, pos, SEEK_SET);

    // --- read node states
    for (i = 0; i < Nobjects[NODE]; i++)
    {
        if ( !readFloat(&x) ) return;
        Node[i].newDepth = x;
        if ( !readFloat(&x) ) return;
        Node[i].newLatFlow = x;
        for (j = 0; j < Nobjects[POLLUT]; j++)
        {
            if ( !readFloat(&x) ) return;
            Node[i].newQual[j] = x;
        }

        // --- read in zero here for back compatibility
        for (j = 0; j < Nobjects[POLLUT]; j++)
        {
            if ( !readFloat(&x) ) return;
        }
    }

    // --- read link states
    for (i = 0; i < Nobjects[LINK]; i++)
    {
        if ( !readFloat(&x) ) return;
        Link[i].newFlow = x;
        if ( !readFloat(&x) ) return;
        Link[i].newDepth = x;
        if ( !readFloat(&x) ) return;
        Link[i].setting = x;
        for (j = 0; j < Nobjects[POLLUT]; j++)
        {
            if ( !readFloat(&x) ) return;
            Link[i].newQual[j] = x;
        }
    }
}
Example #5
0
void Noise::parse(vector<string> args) {
    assert(args.size() < 3, "-noise takes zero, one, or two arguments\n");

    float maxVal = 1;
    float minVal = 0;
    if (args.size() == 1) {
        maxVal = readFloat(args[0]);
    } else if (args.size() == 2) {
        minVal = readFloat(args[0]);
        maxVal = readFloat(args[1]);
    }

    apply(stack(0), minVal, maxVal);

}
Example #6
0
void Quantize::parse(vector<string> args) {
    assert(args.size() <= 1, "-quantize takes zero or one arguments\n");
 
    if (args.size()) apply(stack(0), readFloat(args[0]));
    else apply(stack(0), 1);
                           
}
float
RemotePluginClient::getParameterDefault(int p)
{
    writeOpcode(m_controlRequestFd, RemotePluginGetParameterDefault);
    writeInt(m_controlRequestFd, p);
    return readFloat(m_controlResponseFd);
}
float
RemotePluginClient::getVersion()
{
//!!! client code needs to be testing this
    writeOpcode(m_controlRequestFd, RemotePluginGetVersion);
    return readFloat(m_controlResponseFd);
}
WalkingEngineKick::Value* WalkingEngineKick::readValue(char*& buf)
{
  while(*buf == ' ' || *buf == '\t')
    ++buf;
  switch(*buf)
  {
  case '(':
  {
    ++buf;
    Value* result = readPlusFormula(buf);
    while(*buf == ' ' || *buf == '\t')
      ++buf;
    if(*buf != ')')
      throw ParseException("expected ')'");
    ++buf;
    return result;
  }
  case '$':
  {
    ++buf;
    unsigned int i = readUInt(buf);
    return new ParameterValue(i, *this);
  }
  default:
  {
    float f = readFloat(buf);
    return new ConstantValue(f, *this);
  }
  }
}
Example #10
0
bool BranchState::readFloat( Token::Argument& argument )
{
	assert( argument.type() == Token::Argument::FLOAT_REGISTER );

	if( argument.content() == Token::Argument::REGISTER )
	{
		return readFloat( argument.regNumber(), argument.fields() );
	}
	else if( argument.content() == Token::Argument::ALIAS )
	{
		std::map< std::string, State >::iterator i = m_floats.find( argument.alias() );

		// has this alias been written already?

		if( i == m_floats.end() )
			return false;

		// make sure no uninitialized portion of the alias is read

		if( argument.fields() & (~(i->second.fields())) )
			return false;

		// update dependency information

		updateDependency( argument, i->second, Alias::FLOAT, i->first, true );
	}
	else return false;

	return true;
}
Example #11
0
bool CCBReader::readSequences()
{
    auto& sequences = _animationManager->getSequences();

    int numSeqs = readInt(false);

    for (int i = 0; i < numSeqs; i++)
    {
        CCBSequence *seq = new (std::nothrow) CCBSequence();
        seq->autorelease();

        seq->setDuration(readFloat());
        seq->setName(readCachedString().c_str());
        seq->setSequenceId(readInt(false));
        seq->setChainedSequenceId(readInt(true));

        if(!readCallbackKeyframesForSeq(seq)) return false;
        if(!readSoundKeyframesForSeq(seq)) return false;

        sequences.pushBack(seq);
    }

    _animationManager->setAutoPlaySequenceId(readInt(true));
    return true;
}
Example #12
0
double TokenStream::readRational() {
    Token t;

    double val=readFloat();
    if (!isEOF()) {
	nextToken(t);
	if (t.type == TT_SYMBOL && t.sval[0] == '/') {
	    double div=readFloat();
	    val /= div;
	} else {
	    pushBack();
	}
    }
    return val;

}
Example #13
0
static TACommandVerdict acoshf_cmd(TAThread thread,TAInputStream stream)
{
    float x, res;

    // Prepare

    x = readFloat(&stream);
    errno = 0;
    
    START_TARGET_OPERATION(thread);
    
    // Execute

    res = acoshf(x);
    
    END_TARGET_OPERATION(thread);
    
    // Response
    
    writeFloat(thread, res);
    writeInt(thread, errno);

    sendResponse(thread);
    return taDefaultVerdict;
}
Example #14
0
// Leeremos, dentro de la etiqueta strEtiqueta, nNumF floats, que
// almacenaremos en el array de floats fltArray. Al llamar a este metodo
// debemos garantizar que fltArray puede almacenar nNumF floats.
bool Parser::readBloqueFloats(const std::string &strEtiqueta, const int nNumF, float *fltArray)
{
	std::string	strBufferEtq,
				strCierre("/");
	char		cSep;
	
	if(!ignorarChars())
        return false;
    if(!readToken(strBufferEtq))
        return false;
	if(strEtiqueta != strBufferEtq)
        return false;
		
	for(int i = 0; i < nNumF; i++) {
		if(i == nNumF - 1) // Ultimo float a leer
			cSep = '<';
		else
			cSep = ',';
			
		if(!readFloat(fltArray[i], cSep))
			return false;
	}
	
	strCierre += strBufferEtq;
    strBufferEtq.clear();
        
    if(!readToken(strBufferEtq))
        return false;
    
    if(strCierre != strBufferEtq)
        return false;

    return true;
}
void MD5Model::readFrameEl(std::ifstream &fin, Anim &anim) {
	// numAnimatedComponents has to have been set before frame element
	if (0 == anim.numAnimatedComponents)
		throw Exception("MD5Model::readFrameEl(): numAnimatedComponents must be set before 'frame' block");

	// read frame index
	int frameIndex = readInt(fin);

	if (frameIndex < 0 || frameIndex >= anim.numFrames)
		throw Exception("MD5Model::readFrameEl(): invalid frame index");

	// get reference to frame and set number of animated components
	Frame &frame = anim.frames[frameIndex];
	frame.animatedComponents.resize(anim.numAnimatedComponents);

	TOKEN t = getNextToken(fin);

	// expect an opening brace { to begin block
	if (t != TOKEN_LBRACE)
		throw Exception("MD5Model::readFrameEl(): expected { to follow frame index");

	for (int i = 0; i < anim.numAnimatedComponents; i++)
		frame.animatedComponents[i] = readFloat(fin); // 刚好读取frame中的位置数加上方位数总flaot数

	t = getNextToken(fin);

	// expect a closing brace } to end block
	if (t != TOKEN_RBRACE)
		throw Exception("MD5Model::readFrameEl(): expected }");
}
Example #16
0
File: gtm.cpp Project: OSGeo/gdal
bool GTM::readTrackPoints( double& latitude, double& longitude,
                           GIntBig& datetime,
                           unsigned char& start, float& altitude)
{
    /* Point to the actual trackpoint offset */
    if ( VSIFSeekL(pGTMFile, actualTrackpointOffset, SEEK_SET) != 0)
        return false;

    /* Read latitude */
    latitude = readDouble(pGTMFile);

    /* Read longitude */
    longitude = readDouble(pGTMFile);

    /* Read trackpoint date */
    datetime = readInt(pGTMFile);
    if (datetime != 0)
        datetime += GTM_EPOCH;

    /* Read start flag */
    if ( !readFile( &start, 1, 1 ) )
        return false;

    /* Read altitude */
    altitude = readFloat(pGTMFile);

    ++trackpointFetched;
    if (trackpointFetched < ntcks)
    {
        actualTrackpointOffset += 8 + 8 + 4 + 1 + 4;
    }
    return true;
}
Example #17
0
Material* SceneParser::parsePhongMaterial() {
	char token[MAX_PARSER_TOKEN_LENGTH];
	Vec3f diffuseColor(1, 1, 1);
	Vec3f specularColor(0, 0, 0);
	float exponent = 1;
	getToken(token); assert(!strcmp(token, "{"));
	while (1) {
		getToken(token);
		if (!strcmp(token, "diffuseColor")) {
			diffuseColor = readVec3f();
		}
		else if (!strcmp(token, "specularColor")) {
			specularColor = readVec3f();
		}
		else if (!strcmp(token, "exponent")) {
			exponent = readFloat();
		}
		else {
			assert(!strcmp(token, "}"));
			break;
		}
	}
	Material *answer = new PhongMaterial(diffuseColor, specularColor, exponent);
	return answer;
}
Example #18
0
static Literal readLiteral(FILE *f) {
  int tag = readTag(f);
  switch (tag) {
    case LIT_STR:
      { 
	LiteralStr lit = (LiteralStr) malloc(sizeof(struct _LiteralStr));
        lit->_.tag = tag;
        lit->val   = readString(f);
        return ((Literal) lit);
      }
    case LIT_INT:
      { 
	LiteralInt lit = (LiteralInt) malloc(sizeof(struct _LiteralInt));
        lit->_.tag = tag;
        lit->val   = readInt(f);
        return ((Literal) lit);
      }
    case LIT_FLOAT:
      {
        LiteralFloat lit = (LiteralFloat) malloc(sizeof(struct _LiteralFloat));
        lit->_.tag = tag;
        lit->val   = readFloat(f);
        return ((Literal) lit);
      }
    default:
      __pgf_panic("Unknown literal tag");
  }
}
Example #19
0
//! reads floats from inside of xml element until end of xml element
void CIrrMeshFileLoader::readFloatsInsideElement(io::IXMLReader* reader, f32* floats, u32 count)
{
	if (reader->isEmptyElement())
		return;

	while(reader->read())
	{
		// TODO: check for comments inside the element
		// and ignore them.

		if (reader->getNodeType() == io::EXN_TEXT)
		{
			// parse float data
			core::stringc data = reader->getNodeData();
			const c8* p = &data[0];

			for (u32 i=0; i<count; ++i)
			{
				findNextNoneWhiteSpace(&p);
				if (*p)
					floats[i] = readFloat(&p);
				else
					floats[i] = 0.0f;
			}
		}
		else
		if (reader->getNodeType() == io::EXN_ELEMENT_END)
			break; // end parsing text
	}
}
Material *
SceneParser::parseMaterial() 
{
    char token[MAX_PARSER_TOKEN_LENGTH];
    char filename[MAX_PARSER_TOKEN_LENGTH];
    filename[0] = 0;
    Vector3f diffuseColor(1,1,1), specularColor(0,0,0);
    float shininess=0;
    getToken(token); assert(!strcmp(token, "{"));
    while (true) {
        getToken(token); 
        if (strcmp(token, "diffuseColor")==0) {
            diffuseColor = readVector3f();
        }
        else if (strcmp(token, "specularColor")==0) {
            specularColor = readVector3f();
        }
        else if (strcmp(token, "shininess")==0) {
            shininess = readFloat();
        }
        else if (strcmp(token, "texture")==0) {
            getToken(filename);
        }
        else {
            assert(!strcmp(token, "}"));
            break;
        }
    }
    Material *answer = new Material(diffuseColor, specularColor, shininess);
    if(filename[0] !=0){
        answer->loadTexture(filename);
    }
    return answer;
}
Example #21
0
Material* SceneParser::parseMaterial() {
    char token[MAX_PARSER_TOKEN_LENGTH];
	char filename[MAX_PARSER_TOKEN_LENGTH];
	filename[0] = 0;
    Vector3f diffuseColor(1,1,1), specularColor(0,0,0);
	float shininess=0;
	float refractionIndex =0;
    getToken(token); assert (!strcmp(token, "{"));
	Noise *noise =0;
    while (1) {
        getToken(token); 
        if (strcmp(token, "diffuseColor")==0) {
            diffuseColor = readVector3f();
        }
		else if (strcmp(token, "specularColor")==0) {
            specularColor = readVector3f();
        }
		else if (strcmp(token, "shininess")==0) {
            shininess = readFloat();
        }else if(strcmp(token, "refractionIndex")==0){
			refractionIndex = readFloat();
		}
		else if (strcmp(token, "texture")==0) {
            getToken(filename);
        }
		///unimplemented
		else if (strcmp(token, "bump")==0) {
            getToken(token);
        }
		else if(strcmp(token,"Noise")==0){
			noise = parseNoise();
		}
		else {
            assert (!strcmp(token, "}"));
            break;
        }
    }
    Material *answer = new Material(diffuseColor, specularColor, shininess,refractionIndex);
	if(filename[0] !=0){
		answer->loadTexture(filename);
	}
	if(noise != 0){
		answer->setNoise(*noise);
		delete noise;
	}
    return answer;
}
Example #22
0
void Histogram::parse(vector<string> args) {
    assert(args.size() < 4, "-histogram takes three or fewer arguments\n");
    int buckets = 256;
    float minVal = 0.0f;
    float maxVal = 1.0f;
    if (args.size() > 0) {
        buckets = readInt(args[0]);
    }
    if (args.size() > 1) {
        minVal = readFloat(args[1]);
    }
    if (args.size() > 2) {
        maxVal = readFloat(args[2]);
    }

    push(apply(stack(0), buckets, minVal, maxVal));
}
Example #23
0
void Printf::parse(vector<string> args) {
    assert(args.size() > 0, "-printf requires at least one argument\n");
    vector<float> fargs;
    for (unsigned i = 1; i < args.size(); i++) {
        fargs.push_back(readFloat(args[args.size()-i]));
    }
    apply(stack(0), args[0], fargs);
}
Example #24
0
void Mod::parse(vector<string> args) {
    vector<float> fargs;
    for (size_t i = 0; i < args.size(); i++) {
	fargs.push_back(readFloat(args[i]));
    }
	
    apply(stack(0), fargs);
}
static void readCurve(spSkeletonBinary *self, spCurveTimeline *timeline, int frameIndex)
{
    switch (readByte(self)) {
        case CURVE_STEPPED: {
            spCurveTimeline_setStepped(timeline, frameIndex);
            break;
        }
        case CURVE_BEZIER: {
            float v1 = readFloat(self);
            float v2 = readFloat(self);
            float v3 = readFloat(self);
            float v4 = readFloat(self);
            spCurveTimeline_setCurve(timeline, frameIndex, v1, v2, v3, v4);
            break;
        }
    }
}
Example #26
0
void FPrintf::parse(vector<string> args) {
    assert(args.size() > 1, "-fprintf requires at least two arguments\n");
    vector<float> fargs;
    for (unsigned i = 2; i < args.size(); i++) {
        fargs.push_back(readFloat(args[args.size()-i+1]));
    }
    apply(stack(0), args[0], args[1], fargs);
}
Example #27
0
void BoneVertex::readFromFile(FILE *fp, float scale)
{
  char nameCurrent[512];
  float posx, posy, posz;
  float angle;
  float axisx, axisy, axisz;

  readString(fp, nameCurrent);

  posx = readFloat(fp) * scale;
  posy = readFloat(fp) * scale;
  posz = readFloat(fp) * scale;

  angle = readFloat(fp);
  axisx = readFloat(fp);
  axisy = readFloat(fp);
  axisz = readFloat(fp);

  setName(nameCurrent);
  setInitialPosition(posx, posy, posz);
  setInitialRotation(angle, axisx, axisy, axisz);

  int cpt = readInt(fp); // Number of children
  for (int i=0; i<cpt; i++) {
    BoneVertex *tmp = new BoneVertex();
    addChild(tmp);
    tmp->readFromFile(fp);
  }

  compileChildList();
}
static void readVertices(spSkeletonBinary *self, spVertexAttachment *attachment, int vertexCount)
{
    if (!readBoolean(self)) {
        attachment->vertices = readFloats(self, self->scale, vertexCount << 1);
        attachment->verticesCount = vertexCount << 1;
        attachment->bones = NULL;
        attachment->bonesCount = 0;
    } else {
        float *weights;
        int *bones;
        int weightCount = 0, boneCount = 0;
        int position = self->data->position;
        
        for (int i = 0; i < vertexCount; i++) {
            int nn = readVarint(self, true);
            boneCount++;
            for (int ii = 0; ii < nn; ii++) {
                readVarint(self, true);
                self->data->position += sizeof(float) * 3;
                weightCount += 3;
                boneCount++;
            }
        }
        
        self->data->position = position;
        
        attachment->bones = MALLOC(int, boneCount);
        attachment->bonesCount = boneCount;
        attachment->vertices = MALLOC(float, weightCount);
        attachment->verticesCount = weightCount;
        weights = attachment->vertices;
        bones = attachment->bones;
        
        for (int i = 0; i < vertexCount; i++) {
            int nn = readVarint(self, true);
            *bones++ = nn;
            for (int ii = 0; ii < nn; ii++) {
                *bones++ = readVarint(self, true);
                *weights++ = readFloat(self) * self->scale;
                *weights++ = readFloat(self) * self->scale;
                *weights++ = readFloat(self);
            }
        }
    }
}
Example #29
0
/// read from file
coTetin__defDensPoly::coTetin__defDensPoly(istream &str, int binary)
    : coTetinCommand(coTetin::DEFINE_DENSITY_POLYGON)
{
    if (binary)
    {
    }
    else
    {
        char lineBuf[4096];
        getLine(lineBuf, 4096, str);
        d_npnts = 0;
        d_size = 0.0;
        getOption(lineBuf, "npnts", d_npnts);
        getOption(lineBuf, "size", d_size);
        d_name = NULL;
        if (getOption(lineBuf, "name", d_name) == 0)
        {
            d_name = new char[1];
            d_name[0] = '\0';
        }

        // no points ...
        if (d_npnts <= 0)
        {
            d_coord = NULL;
            return;
        }

        // read the points the safe way...
        float *fPtr;
        fPtr = d_coord = new float[3 * d_npnts];
        int i;
        for (i = 0; i < d_npnts; i++)
        {
            getLine(lineBuf, 4096, str);
            char *cPtr = lineBuf;
            *fPtr = readFloat(cPtr);
            fPtr++;
            *fPtr = readFloat(cPtr);
            fPtr++;
            *fPtr = readFloat(cPtr);
            fPtr++;
        }
    }
}
int NmeaParser::nmeaReadLongitude(char *s, float &longitude)
{
   if (strlen(s) < 4) {
      DEBUG_BAD_PACKETS("Invalid llongitude length, %i characters", strlen(s));
      return 0;
   }
   longitude = (float(readNDigitsInt(s, 3) * 60) + readFloat(s+3)) * float(M_PI / (180 * 60));
   return 1;
}