📄 mitab_tabfile.cpp
字号:
// "GetFeatureRef() failed: invalid feature id %d",
// nFeatureId);
return NULL;
}
/*-----------------------------------------------------------------
* Flush current feature object
* __TODO__ try to reuse if it is already of the right type
*----------------------------------------------------------------*/
if (m_poCurFeature)
{
delete m_poCurFeature;
m_poCurFeature = NULL;
}
/*-----------------------------------------------------------------
* Create new feature object of the right type
* Unsupported object types are returned as raw TABFeature (i.e. NONE
* geometry)
*----------------------------------------------------------------*/
m_poCurFeature = TABFeature::CreateFromMapInfoType(m_poMAPFile->GetCurObjType(),
m_poDefn);
/*-----------------------------------------------------------------
* Read fields from the .DAT file
* GetRecordBlock() has already been called above...
*----------------------------------------------------------------*/
if (m_poCurFeature->ReadRecordFromDATFile(m_poDATFile) != 0)
{
delete m_poCurFeature;
m_poCurFeature = NULL;
return NULL;
}
/*-----------------------------------------------------------------
* Read geometry from the .MAP file
* MoveToObjId() has already been called above...
*----------------------------------------------------------------*/
TABMAPObjHdr *poObjHdr =
TABMAPObjHdr::NewObj(m_poMAPFile->GetCurObjType(),
m_poMAPFile->GetCurObjId());
// Note that poObjHdr==NULL is a valid case if geometry type is NONE
if ((poObjHdr && poObjHdr->ReadObj(m_poMAPFile->GetCurObjBlock()) != 0) ||
m_poCurFeature->ReadGeometryFromMAPFile(m_poMAPFile, poObjHdr) != 0)
{
delete m_poCurFeature;
m_poCurFeature = NULL;
if (poObjHdr)
delete poObjHdr;
return NULL;
}
if (poObjHdr) // May be NULL if feature geometry type is NONE
delete poObjHdr;
m_nCurFeatureId = nFeatureId;
m_poCurFeature->SetFID(m_nCurFeatureId);
m_poCurFeature->SetRecordDeleted(m_poDATFile->IsCurrentRecordDeleted());
return m_poCurFeature;
}
/**********************************************************************
* TABFile::SetFeature()
*
* Write a feature to this dataset.
*
* For now only sequential writes are supported (i.e. with nFeatureId=-1)
* but eventually we should be able to do random access by specifying
* a value through nFeatureId.
*
* Returns the new featureId (> 0) on success, or -1 if an
* error happened in which case, CPLError() will have been called to
* report the reason of the failure.
**********************************************************************/
int TABFile::SetFeature(TABFeature *poFeature, int nFeatureId /*=-1*/)
{
if (m_eAccessMode != TABWrite)
{
CPLError(CE_Failure, CPLE_NotSupported,
"SetFeature() can be used only with Write access.");
return -1;
}
if (nFeatureId != -1)
{
CPLError(CE_Failure, CPLE_NotSupported,
"SetFeature(): random access not implemented yet.");
return -1;
}
/*-----------------------------------------------------------------
* Make sure file is opened and establish new feature id.
*----------------------------------------------------------------*/
if (m_poMAPFile == NULL)
{
CPLError(CE_Failure, CPLE_IllegalArg,
"SetFeature() failed: file is not opened!");
return -1;
}
if (m_nLastFeatureId < 1)
{
/*-------------------------------------------------------------
* OK, this is the first feature in the dataset... make sure the
* .DAT schema has been initialized.
*------------------------------------------------------------*/
if (m_poDefn == NULL)
SetFeatureDefn(poFeature->GetDefnRef(), NULL);
/*-------------------------------------------------------------
* Special hack to write out at least one field if none are in
* OGRFeatureDefn.
*------------------------------------------------------------*/
if( m_poDATFile->GetNumFields() == 0 )
{
CPLError(CE_Warning, CPLE_IllegalArg,
"MapInfo tables must contain at least 1 column, adding dummy FID column.");
m_poDATFile->AddField("FID", TABFInteger, 10, 0 );
}
nFeatureId = m_nLastFeatureId = 1;
}
else
{
nFeatureId = ++ m_nLastFeatureId;
}
/*-----------------------------------------------------------------
* Write fields to the .DAT file and update .IND if necessary
*----------------------------------------------------------------*/
if (m_poDATFile == NULL ||
m_poDATFile->GetRecordBlock(nFeatureId) == NULL ||
poFeature->WriteRecordToDATFile(m_poDATFile, m_poINDFile,
m_panIndexNo) != 0 )
{
CPLError(CE_Failure, CPLE_FileIO,
"Failed writing attributes for feature id %d in %s",
nFeatureId, m_pszFname);
return -1;
}
/*-----------------------------------------------------------------
* Write geometry to the .MAP file
* The call to PrepareNewObj() takes care of the .ID file.
*----------------------------------------------------------------*/
TABMAPObjHdr *poObjHdr =
TABMAPObjHdr::NewObj(poFeature->ValidateMapInfoType(m_poMAPFile),
nFeatureId);
/*-----------------------------------------------------------------
* ValidateMapInfoType() may have returned TAB_GEOM_NONE if feature
* contained an invalid geometry for its class. Need to catch that
* case and return the error.
*----------------------------------------------------------------*/
if (poObjHdr->m_nType == TAB_GEOM_NONE &&
poFeature->GetFeatureClass() != TABFCNoGeomFeature )
{
CPLError(CE_Failure, CPLE_FileIO,
"Invalid geometry for feature id %d in %s",
nFeatureId, m_pszFname);
return -1;
}
/*-----------------------------------------------------------------
* The ValidateMapInfoType() call above has forced calculation of the
* feature's IntMBR. Store that value in the ObjHdr for use by
* PrepareNewObj() to search the best node to insert the feature.
*----------------------------------------------------------------*/
if ( poObjHdr && poObjHdr->m_nType != TAB_GEOM_NONE)
{
poFeature->GetIntMBR(poObjHdr->m_nMinX, poObjHdr->m_nMinY,
poObjHdr->m_nMaxX, poObjHdr->m_nMaxY);
}
if ( poObjHdr == NULL || m_poMAPFile == NULL ||
m_poMAPFile->PrepareNewObj(poObjHdr) != 0 ||
poFeature->WriteGeometryToMAPFile(m_poMAPFile, poObjHdr) != 0 ||
m_poMAPFile->CommitNewObj(poObjHdr) != 0 )
{
CPLError(CE_Failure, CPLE_FileIO,
"Failed writing geometry for feature id %d in %s",
nFeatureId, m_pszFname);
if (poObjHdr)
delete poObjHdr;
return -1;
}
delete poObjHdr;
return nFeatureId;
}
/**********************************************************************
* TABFile::GetLayerDefn()
*
* Returns a reference to the OGRFeatureDefn that will be used to create
* features in this dataset.
*
* Returns a reference to an object that is maintained by this TABFile
* object (and thus should not be modified or freed by the caller) or
* NULL if the OGRFeatureDefn has not been initialized yet (i.e. no file
* opened yet)
**********************************************************************/
OGRFeatureDefn *TABFile::GetLayerDefn()
{
return m_poDefn;
}
/**********************************************************************
* TABFile::SetFeatureDefn()
*
* Pass a reference to the OGRFeatureDefn that will be used to create
* features in this dataset. This function should be called after
* creating a new dataset, but before writing the first feature.
* All features that will be written to this dataset must share this same
* OGRFeatureDefn.
*
* A reference to the OGRFeatureDefn will be kept and will be used to
* build the .DAT file, etc.
*
* Returns 0 on success, -1 on error.
**********************************************************************/
int TABFile::SetFeatureDefn(OGRFeatureDefn *poFeatureDefn,
TABFieldType *paeMapInfoNativeFieldTypes /* =NULL */)
{
int iField, numFields;
OGRFieldDefn *poFieldDefn;
TABFieldType eMapInfoType = TABFUnknown;
int nStatus = 0;
if (m_eAccessMode != TABWrite)
{
CPLError(CE_Failure, CPLE_NotSupported,
"SetFeatureDefn() can be used only with Write access.");
return -1;
}
/*-----------------------------------------------------------------
* Keep a reference to the OGRFeatureDefn... we'll have to take the
* reference count into account when we are done with it.
*----------------------------------------------------------------*/
if (m_poDefn && m_poDefn->Dereference() == 0)
delete m_poDefn;
m_poDefn = poFeatureDefn;
m_poDefn->Reference();
/*-----------------------------------------------------------------
* Pass field information to the .DAT file, after making sure that
* it has been created and that it does not contain any field
* definition yet.
*----------------------------------------------------------------*/
if (m_poDATFile== NULL || m_poDATFile->GetNumFields() > 0 )
{
CPLError(CE_Failure, CPLE_AssertionFailed,
"SetFeatureDefn() can be called only once in a newly "
"created dataset.");
return -1;
}
numFields = poFeatureDefn->GetFieldCount();
for(iField=0; nStatus==0 && iField < numFields; iField++)
{
poFieldDefn = m_poDefn->GetFieldDefn(iField);
/*-------------------------------------------------------------
* Make sure field name is valid... check for special chars, etc.
*------------------------------------------------------------*/
char *pszCleanName = TABCleanFieldName(poFieldDefn->GetNameRef());
if (!EQUAL(pszCleanName, poFieldDefn->GetNameRef()))
poFieldDefn->SetName(pszCleanName);
CPLFree(pszCleanName);
pszCleanName = NULL;
if (paeMapInfoNativeFieldTypes)
{
eMapInfoType = paeMapInfoNativeFieldTypes[iField];
}
else
{
/*---------------------------------------------------------
* Map OGRFieldTypes to MapInfo native types
*--------------------------------------------------------*/
switch(poFieldDefn->GetType())
{
case OFTInteger:
eMapInfoType = TABFInteger;
break;
case OFTReal:
eMapInfoType = TABFFloat;
break;
case OFTString:
default:
eMapInfoType = TABFChar;
}
}
nStatus = m_poDATFile->AddField(poFieldDefn->GetNameRef(),
eMapInfoType,
poFieldDefn->GetWidth(),
poFieldDefn->GetPrecision());
}
/*-----------------------------------------------------------------
* Alloc the array to keep track of indexed fields (default=NOT indexed)
*----------------------------------------------------------------*/
m_panIndexNo = (int *)CPLCalloc(numFields, sizeof(int));
return nStatus;
}
/**********************************************************************
* TABFile::AddFieldNative()
*
* Create a new field using a native mapinfo data type... this is an
* alternative to defining fields through the OGR interface.
* This function should be called after creating a new dataset, but before
* writing the first feature.
*
* This function will build/update the OGRFeatureDefn that will have to be
* used when writing features to this dataset.
*
* A reference to the OGRFeatureDefn can be obtained using GetLayerDefn().
*
* Note: The bUnique flag has no effect on TABFiles. See the TABView class.
*
* Returns 0 on success, -1 on error.
**********************************************************************/
int TABFile::AddFieldNative(const char *pszName, TABFiel
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -