?? mitab_tabview.cpp
字號:
*/
poFieldDefn = poMainDefn->GetFieldDefn(nIndex);
m_poDefn->AddFieldDefn(poFieldDefn);
m_panMainTableFieldMap[nIndex] = m_poDefn->GetFieldCount()-1;
}
else if (poRelDefn &&
(nIndex=poRelDefn->GetFieldIndex(papszSelectedFields[i]))>=0)
{
/* Field from the related table
*/
poFieldDefn = poRelDefn->GetFieldDefn(nIndex);
m_poDefn->AddFieldDefn(poFieldDefn);
m_panRelTableFieldMap[nIndex] = m_poDefn->GetFieldCount()-1;
}
else
{
// Hummm... field does not exist... likely an unsupported feature!
// At least send a warning and ignore the field.
CPLError(CE_Warning, CPLE_IllegalArg,
"Selected Field %s not found in source tables %s and %s",
papszSelectedFields[i],
poMainDefn->GetName(), poRelDefn->GetName());
}
}
return 0;
}
/**********************************************************************
* TABRelation::CreateRelFields()
*
* For write access, create the integer fields in each table that will
* link them, and setup everything to be ready to write the first feature.
*
* This function should be called just before writing the first feature.
*
* Returns 0 on success, or -1 or error.
**********************************************************************/
int TABRelation::CreateRelFields()
{
int i;
/*-----------------------------------------------------------------
* Create the field in each table.
* The default name is "MI_refnum" but if a field with the same name
* already exists then we'll try to generate a unique name.
*----------------------------------------------------------------*/
m_pszMainFieldName = CPLStrdup("MI_Refnum ");
strcpy(m_pszMainFieldName, "MI_Refnum");
i = 1;
while(m_poDefn->GetFieldIndex(m_pszMainFieldName) >= 0)
{
sprintf(m_pszMainFieldName, "MI_Refnum_%d", i++);
}
m_pszRelFieldName = CPLStrdup(m_pszMainFieldName);
m_nMainFieldNo = m_nRelFieldNo = -1;
if (m_poMainTable->AddFieldNative(m_pszMainFieldName,
TABFInteger, 0, 0) == 0)
m_nMainFieldNo = m_poMainTable->GetLayerDefn()->GetFieldCount()-1;
if (m_poRelTable->AddFieldNative(m_pszRelFieldName,
TABFInteger, 0, 0) == 0)
m_nRelFieldNo = m_poRelTable->GetLayerDefn()->GetFieldCount()-1;
if (m_nMainFieldNo == -1 || m_nRelFieldNo == -1)
return -1;
if (m_poMainTable->SetFieldIndexed(m_nMainFieldNo) == -1)
return -1;
if ((m_nRelFieldIndexNo=m_poRelTable->SetFieldIndexed(m_nRelFieldNo)) ==-1)
return -1;
m_poRelINDFileRef = m_poRelTable->GetINDFileRef();
/*-----------------------------------------------------------------
* Update field maps
*----------------------------------------------------------------*/
OGRFeatureDefn *poMainDefn, *poRelDefn;
poMainDefn = m_poMainTable->GetLayerDefn();
poRelDefn = m_poRelTable->GetLayerDefn();
m_panMainTableFieldMap = (int*)CPLRealloc(m_panMainTableFieldMap,
poMainDefn->GetFieldCount()*sizeof(int));
m_panMainTableFieldMap[poMainDefn->GetFieldCount()-1] = -1;
m_panRelTableFieldMap = (int*)CPLRealloc(m_panRelTableFieldMap,
poRelDefn->GetFieldCount()*sizeof(int));
m_panRelTableFieldMap[poRelDefn->GetFieldCount()-1] = -1;
/*-----------------------------------------------------------------
* Make sure the first unique field (in poRelTable) is indexed since
* it is the one against which we will try to match records.
*----------------------------------------------------------------*/
if ( m_poRelTable->SetFieldIndexed(0) == -1)
return -1;
return 0;
}
/**********************************************************************
* TABRelation::GetFeature()
*
* Fill and return a TABFeature object for the specified feature id.
*
* The retuned pointer is a new TABFeature that will have to be freed
* by the caller.
*
* Returns NULL if the specified feature id does not exist of if an
* error happened. In any case, CPLError() will have been called to
* report the reason of the failure.
*
* __TODO__ The current implementation fetches the features from each table
* and creates a 3rd feature to merge them. There would be room for
* optimization, at least by avoiding the duplication of the geometry
* which can be big sometimes... but this would imply changes at the
* lower-level in the lib. and we won't go there yet.
**********************************************************************/
TABFeature *TABRelation::GetFeature(int nFeatureId)
{
TABFeature *poMainFeature;
TABFeature *poCurFeature;
/*-----------------------------------------------------------------
* Make sure init() has been called
*----------------------------------------------------------------*/
if (m_poMainTable == NULL || m_poRelTable == NULL)
{
CPLError(CE_Failure, CPLE_IllegalArg,
"GetFeatureRef() failed: object not initialized yet!");
return NULL;
}
/*-----------------------------------------------------------------
* Read main feature and create a new one of the right type
*----------------------------------------------------------------*/
if ((poMainFeature = m_poMainTable->GetFeatureRef(nFeatureId)) == NULL)
{
// Feature cannot be read from main table...
// an error has already been reported.
return NULL;
}
poCurFeature = poMainFeature->CloneTABFeature(m_poDefn);
/*-----------------------------------------------------------------
* Keep track of FID and copy the geometry
*----------------------------------------------------------------*/
poCurFeature->SetFID(nFeatureId);
if (poCurFeature->GetFeatureClass() != TABFCNoGeomFeature)
{
OGRGeometry *poGeom;
poGeom = poMainFeature->GetGeometryRef();
poCurFeature->SetGeometry(poGeom);
}
/*-----------------------------------------------------------------
* Fetch feature from related table
*
* __TODO__ Right now we support only many-to-1 relationships, but
* it might be possible to have several related entries
* for a single key, and in this case we should return
* one new feature for each of them.
*----------------------------------------------------------------*/
TABFeature *poRelFeature=NULL;
GByte *pKey = BuildFieldKey(poMainFeature, m_nMainFieldNo,
m_poMainTable->GetNativeFieldType(m_nMainFieldNo),
m_nRelFieldIndexNo);
int i;
int nRelFeatureId = m_poRelINDFileRef->FindFirst(m_nRelFieldIndexNo, pKey);
if (nRelFeatureId > 0)
poRelFeature = m_poRelTable->GetFeatureRef(nRelFeatureId);
/*-----------------------------------------------------------------
* Copy fields from poMainFeature
*----------------------------------------------------------------*/
for(i=0; i<poMainFeature->GetFieldCount(); i++)
{
if (m_panMainTableFieldMap[i] != -1)
{
poCurFeature->SetField(m_panMainTableFieldMap[i],
poMainFeature->GetRawFieldRef(i));
}
}
/*-----------------------------------------------------------------
* Copy fields from poRelFeature...
*
* NOTE: For now, if no corresponding feature is found in RelTable
* then we will just leave the corresponding fields unset.
*----------------------------------------------------------------*/
for(i=0; poRelFeature && i<poRelFeature->GetFieldCount(); i++)
{
if (m_panRelTableFieldMap[i] != -1)
{
poCurFeature->SetField(m_panRelTableFieldMap[i],
poRelFeature->GetRawFieldRef(i));
}
}
return poCurFeature;
}
/**********************************************************************
* TABRelation::BuildFieldKey()
*
* Return the index key for the specified field in poFeature.
* Simply maps the call to the proper method in the TABINDFile class.
*
* Returns a reference to a TABINDFile internal buffer that should not
* be freed by the caller.
**********************************************************************/
GByte *TABRelation::BuildFieldKey(TABFeature *poFeature, int nFieldNo,
TABFieldType eType, int nIndexNo)
{
GByte *pKey = NULL;
switch(eType)
{
case TABFChar:
pKey = m_poRelINDFileRef->BuildKey(nIndexNo,
poFeature->GetFieldAsString(nFieldNo));
break;
case TABFDecimal:
case TABFFloat:
pKey = m_poRelINDFileRef->BuildKey(nIndexNo,
poFeature->GetFieldAsDouble(nFieldNo));
break;
// __TODO__ DateTime fields are 8 bytes long, not supported yet by
// the indexing code (see bug #1844).
case TABFDateTime:
CPLError(CE_Failure, CPLE_NotSupported,
"TABRelation on field of type DateTime not supported yet.");
break;
case TABFInteger:
case TABFSmallInt:
case TABFDate:
case TABFTime:
case TABFLogical:
default:
pKey = m_poRelINDFileRef->BuildKey(nIndexNo,
poFeature->GetFieldAsInteger(nFieldNo));
break;
}
return pKey;
}
/**********************************************************************
* TABRelation::GetNativeFieldType()
*
* Returns the native MapInfo field type for the specified field.
*
* Returns TABFUnknown if file is not opened, or if specified field index is
* invalid.
*
* Note that field ids are positive and start at 0.
**********************************************************************/
TABFieldType TABRelation::GetNativeFieldType(int nFieldId)
{
int i, numFields;
if (m_poMainTable==NULL || m_poRelTable==NULL ||
m_panMainTableFieldMap==NULL || m_panRelTableFieldMap==NULL)
return TABFUnknown;
/*-----------------------------------------------------------------
* Look for nFieldId in the field maps and call the corresponding
* TAB file's GetNativeFieldType()
*----------------------------------------------------------------*/
numFields = m_poMainTable->GetLayerDefn()->GetFieldCount();
for(i=0; i<numFields; i++)
{
if (m_panMainTableFieldMap[i] == nFieldId)
{
return m_poMainTable->GetNativeFieldType(i);
}
}
numFields = m_poRelTable->GetLayerDefn()->GetFieldCount();
for(i=0; i<numFields; i++)
{
if (m_panRelTableFieldMap[i] == nFieldId)
{
return m_poRelTable->GetNativeFieldType(i);
}
}
return TABFUnknown;
}
/**********************************************************************
* TABRelation::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().
*
* Returns 0 on success, -1 on error.
**********************************************************************/
int TABRelation::AddFieldNative(const char *pszName, TABFieldType eMapInfoType,
int nWidth /*=0*/, int nPrecision /*=0*/,
GBool bIndexed /*=FALSE*/, GBool bUnique/*=FALSE*/)
{
if (m_poMainTable==NULL || m_poRelTable==NULL ||
m_panMainTableFieldMap==NULL || m_panRelTableFieldMap==NULL)
return -1;
if (!bUnique)
{
/*-------------------------------------------------------------
* Add field to poMainTable and to m_poDefn
*------------------------------------------------------------*/
if (m_poMainTable->AddFieldNative(pszName, eMapInfoType,
nWidth, nPrecision,
bIndexed) != 0)
return -1;
OGRFeatureDefn *poMainDefn = m_poMainTable->GetLayerDefn();
m_panMainTableFieldMap = (int*)CPLRealloc(m_panMainTableFieldMap,
poMainDefn->GetFieldCount()*sizeof(int));
m_poDefn->AddFieldDefn(poMainDefn->GetFieldDefn(poMainDefn->
GetFieldCount()-1));
m_panMainTableFieldMap[poMainDefn->GetFieldCount()-1] =
m_poDefn->GetFieldCount()-1;
}
else
{
/*-------------------------------------------------------------
* Add field to poRelTable and to m_poDefn
*------------------------------------------------------------*/
if (m_poRelTable->AddFieldNative(pszName, eMapInfoType,
nWidth, nPrecision,
bIndexed) != 0)
return -1;
OGRFeatureDefn *poRelDefn = m_poRelTable->GetLayerDefn();
m_panRelTableFieldMap = (int*)CPLRealloc(m_panRelTableFieldMap,
poRelDefn->GetFieldCount()*sizeof(int));
m_poDefn->AddFiel
?? 快捷鍵說明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -