rspfErrorCode rspfRpfBoundaryRectRecord::parseStream(std::istream& in, rspfByteOrder byteOrder)
{
   if(in)
   {
      clearFields();
      
      in.read((char*)&m_productDataType, 5);
      in.read((char*)&m_compressionRatio, 5);
      in.read((char*)&m_scale, 12);
      in.read((char*)&m_zone, 1);
      in.read((char*)&m_producer, 5);

      rspfString tmpScale(m_scale);
      tmpScale.trim();
      if (!tmpScale.empty())
      {
        if (tmpScale.beforePos(2) != "1:")
        {
          if (tmpScale.afterPos(tmpScale.size()-2)!="M" && 
            tmpScale.afterPos(tmpScale.size()-2)!="K")
          {
            int tmpScaleValue = tmpScale.toInt();
            if (tmpScaleValue > 0)
            {
              tmpScale = rspfString("1:" + tmpScale);
              memset(m_scale, ' ', 12);
              memcpy(m_scale, tmpScale.c_str(), 12);
            }
          }
        }
      }
      
      m_coverage.parseStream(in, byteOrder);
      
      in.read((char*)&m_numberOfFramesNorthSouth, 4);
      in.read((char*)&m_numberOfFramesEastWest, 4);

      if( rspf::byteOrder() != byteOrder )
      {
         rspfEndian anEndian;
         anEndian.swap(m_numberOfFramesNorthSouth);
         anEndian.swap(m_numberOfFramesEastWest);
      }
   }
   else
   {
      return rspfErrorCodes::RSPF_ERROR;
   }

   return rspfErrorCodes::RSPF_OK;
}
// get pivot inverse matrix only
GMatrix33 GAnimTRSNode2D::InversePivotMatrix() const {

	// build (inverse) translation factor
	GMatrix33 invTranslation;
	TranslationToMatrix(invTranslation, gPivotPosition);

	// build (inverse) rotation factor
	GMatrix33 invRotation;
	RotationToMatrix(invRotation, -gPivotRotation);
	// build (inverse) scale factor
	GMatrix33 invScale;
	GVector2 tmpScale(gPivotScale);
	if (GMath::Abs(tmpScale[G_X]) > G_EPSILON)
		tmpScale[G_X] = 1 / tmpScale[G_X];
	if (GMath::Abs(tmpScale[G_Y]) > G_EPSILON)
		tmpScale[G_Y] = 1 / tmpScale[G_Y];
	ScaleToMatrix(invScale, tmpScale);
	// return the resulting (inverse) matrix
	return (invScale * (invRotation * invTranslation));
}
Acad::ErrorStatus
ArxDbgDbAdeskLogo::dxfInFields(AcDbDxfFiler* filer)
{
    Acad::ErrorStatus es;
    if (((es = ArxDbgDbEntity::dxfInFields(filer)) != Acad::eOk) ||
        (filer->atSubclassData(this->desc()->name()) != Adesk::kTrue))
        return filer->filerStatus();

    resbuf rb;

    while ((es == Acad::eOk) && ((es = filer->readResBuf(&rb)) == Acad::eOk)) {
        if (rb.restype == kDxfLogoStyleId) {
            AcDbObjectId id;
            id.setFromOldId(rb.resval.mnLongPtr);
            setLogoStyleId(id);
        }
        else if (rb.restype == kDxfArbitraryRefId) {
            AcDbObjectId id;
            id.setFromOldId(rb.resval.mnLongPtr);
            setArbitraryReferenceId(id);
        }
        else if (rb.restype == kDxfScale) {
            AcGeScale3d tmpScale(rb.resval.rpoint[X], rb.resval.rpoint[Y], rb.resval.rpoint[Z]);
            setScale(tmpScale);
        }
        else {
            filer->pushBackItem();
            es = Acad::eEndOfFile;
        }
    }

    if (es != Acad::eEndOfFile)
        return Acad::eInvalidResBuf;

    return filer->filerStatus();
}
GMatrix33 GAnimTRSNode2D::InverseMatrix(const GTimeValue TimePos, const GSpaceSystem Space, GTimeInterval& ValidInterval) const {

	GProperty *tmpProp = Property("transform");

	// this can be the case of a curve not created through a kernel
	if (!tmpProp) {
		ValidInterval = G_FOREVER_TIMEINTERVAL;
		return GMatrix33();
	}

	GMatrix33 invTranslation;
	GMatrix33 invRotation;
	GMatrix33 invScale;
	GTimeInterval tmpValid = G_FOREVER_TIMEINTERVAL;
	GKeyValue xValue, yValue;
	GError xErr, yErr;
	GProperty *transProp = tmpProp->Property("position");
	GProperty *rotProp = tmpProp->Property("rotation");
	GProperty *scaleProp = tmpProp->Property("scale");

	G_ASSERT(transProp != NULL);
	G_ASSERT(rotProp != NULL);
	G_ASSERT(scaleProp != NULL);

	// extract translation
	GProperty *xProp = transProp->Property("x");
	GProperty *yProp = transProp->Property("y");
	G_ASSERT(xProp != NULL);
	G_ASSERT(yProp != NULL);
	// build translation factor
	xErr = xProp->Value(xValue, tmpValid, TimePos, G_ABSOLUTE_VALUE);
	yErr = yProp->Value(yValue, tmpValid, TimePos, G_ABSOLUTE_VALUE);
	if (xErr != G_NO_ERROR || yErr != G_NO_ERROR)
		return GMatrix33();
	TranslationToMatrix(invTranslation, GVector2(-xValue.RealValue(), -yValue.RealValue()));

	// build rotation factor
	xErr = rotProp->Value(xValue, tmpValid, TimePos, G_ABSOLUTE_VALUE);
	if (xErr != G_NO_ERROR)
		return GMatrix33();
	RotationToMatrix(invRotation, -xValue.RealValue());

	// extract scale
	xProp = scaleProp->Property("x");
	yProp = scaleProp->Property("y");
	G_ASSERT(xProp != NULL);
	G_ASSERT(yProp != NULL);
	// build scale factor
	xErr = xProp->Value(xValue, tmpValid, TimePos, G_ABSOLUTE_VALUE);
	yErr = yProp->Value(yValue, tmpValid, TimePos, G_ABSOLUTE_VALUE);
	if (xErr != G_NO_ERROR || yErr != G_NO_ERROR)
		return GMatrix33();
	GPoint2 tmpScale(1, 1);
	if (GMath::Abs(xValue.RealValue()) > G_EPSILON)
		tmpScale[G_X] = 1 / xValue.RealValue();
	if (GMath::Abs(yValue.RealValue()) > G_EPSILON)
		tmpScale[G_Y] = 1 / yValue.RealValue();
	ScaleToMatrix(invScale, tmpScale);

	ValidInterval = tmpValid;
	// take care of father
	GMatrix33 invLocalMatrix = (invScale * (invRotation * invTranslation));
	if (gFather && Space == G_WORLD_SPACE) {
		GMatrix33 invFatherMatrix = gFather->InverseMatrix(TimePos, G_WORLD_SPACE, tmpValid);
		ValidInterval &= tmpValid;
		return (invLocalMatrix * invFatherMatrix);
	}
	return invLocalMatrix;
}
GError GAnimTRSNode2D::SetFather(GAnimTRSNode2D *NewFather, const GBool AffectTracks) {

	GTimeInterval tmpValid;

	// if specified father is NULL, detach this node (it will become a root node)
	if (!NewFather) {
		if (AffectTracks) {
			// offset position track
			GPoint2 wPos = Position(0, G_WORLD_SPACE, tmpValid);
			GPoint2 lPos = Position(0, G_LOCAL_SPACE, tmpValid);
			OffsetPositionTrack(wPos - lPos);
			// offset rotation track
			GReal wRot = Rotation(0, G_WORLD_SPACE, tmpValid);
			GReal lRot = Rotation(0, G_LOCAL_SPACE, tmpValid);
			OffsetRotationTrack(wRot - lRot);
			// offset scale track
			GVector2 wScl = Scale(0, G_WORLD_SPACE, tmpValid);
			GVector2 lScl = Scale(0, G_LOCAL_SPACE, tmpValid);
			GVector2 tmpScale(wScl);
			if (GMath::Abs(lScl[G_X]) > G_EPSILON)
				tmpScale[G_X] /= lScl[G_X];
			if (GMath::Abs(lScl[G_Y]) > G_EPSILON)
				tmpScale[G_Y] /= lScl[G_Y];
			OffsetScaleTrack(tmpScale);
		}
		// detach me from my current father (if it exists)
		if (gFather)
			gFather->DetachChildNode(this);
	}
	else {
		if (AffectTracks) {
			// offset position track
			GPoint2 wPos = Position(0, G_WORLD_SPACE, tmpValid);
			GPoint2 lPos = Position(0, G_LOCAL_SPACE, tmpValid);
			GPoint2 fwPos = NewFather->Position(0, G_WORLD_SPACE, tmpValid);
			OffsetPositionTrack(fwPos - wPos - lPos);
			// offset rotation track
			GReal wRot = Rotation(0, G_WORLD_SPACE, tmpValid);
			GReal lRot = Rotation(0, G_LOCAL_SPACE, tmpValid);
			GReal fwRot = NewFather->Rotation(0, G_WORLD_SPACE, tmpValid);
			OffsetRotationTrack(fwRot - wRot - lRot);
			// offset scale track
			GVector2 wScl = Scale(0, G_WORLD_SPACE, tmpValid);
			GVector2 lScl = Scale(0, G_LOCAL_SPACE, tmpValid);
			GPoint2 fwScl = NewFather->Scale(0, G_WORLD_SPACE, tmpValid);
			GVector2 tmpScale(fwScl);
			GVector2 tmpDen(wScl[G_X] * lScl[G_X], wScl[G_Y] * lScl[G_Y]);
			if (GMath::Abs(tmpDen[G_X]) > G_EPSILON)
				tmpScale[G_X] /= tmpDen[G_X];
			else
				tmpScale[G_X] = 1;

			if (GMath::Abs(tmpDen[G_Y]) > G_EPSILON)
				tmpScale[G_Y] /= tmpDen[G_Y];
			else
				tmpScale[G_Y] = 1;
			OffsetScaleTrack(tmpScale);
		}
		// detach me from my current father (if it exists)
		if (gFather)
			gFather->DetachChildNode(this);
		// attach me to the new father
		NewFather->AttachChildNode(this);
	}
	return G_NO_ERROR;
}