--- In ogdidev@egroups.com, Frank Warmerdam <warmerda@h...> wrote:
Folks,
I have been doing a little work with the OGDI 3.0 Beta VRF driver (as
found on the III web site) working with VITD datasets. My work revolved
around support to aggregate the primitives forming a line feature into a
single OGDI object before return based on join tables. However, while I
did this work I ran into a number of other problems with the VRF driver that
I think could affect other products and may be useful even without my
feature aggregation "improvements".
While I am hoping to role these changes into the OGDI core someday, there isn't
currently any methodology to accomplish this. In the meantime I am offering
the changes to the OGDI community to consider and apply to local VRF drivers
if it seems appropriate.
I would be interested in any feedback on whether the code changes help, hinder
or seem inappropriate for some reason. Needless to say the code comes with
no guarantees.
If you don't want the feature aggregation just skip to the end of the README
and checkout the "other bugs fixed" section.
The full source can be found at:
ftp://gdal.velocet.ca/pub/outgoing/vrf_src.zip
Finally, I would like to credit Mercator Systems who funded my work on
the VRF driver.
Best regards,
This VRF driver source was updated by Frank Warmerdam (warmerda@h...)
circa August 11th, 1999 to support merging of VRF line features based
on the relationship implied by the join table (relating a set of
primitive geometries with one feature).
This merging operation can be enabled and disabled via the VRF_LINE_JOIN_HACK
macro in vrf.h; however, even with this macro disabled modified code will be
used though I believe it does the same thing as the old code. The macro
is primarily used to set the mergeFeatures flag in the layer private
information structure ... alternative logic could be applied to the
setting of this flag in vrf.c.
Assumptions
-----------
o It is assumed that all primitives forming a single feature will appear
contiguously in the join table.
o It is assumed that an exact floating point comparison will succeed
when comparing end points of primitives that are intended to be
coincident.
o Any primitives that can't be successfully assembled into the aggregate
feature geometry are silently discarded.
o There are no joining affects for points, text or areas at this time.
These feature types have not been tested to ensure they still work
properly.
Code / Algorithm Specifics
--------------------------
Code changes for this work were restricted to vrf.h, vrf.c, feature.c
and object.c.
When features are being merged on the basis of a join table the nbfeature
element of the layer structure is set to the number of features, rather than
the number of rows in the table (primitives) as it was previously. Changes
in _getNextObjectLine() have been incorporated to assemble a list of
primitives for a given feature, and to operate on this whole list when
computing the min bound rectangle, and when fetching the feature geometry.
The collection of related primitives currently assumes that all primitives
for a given feature will appear contiguously in the join feature table. If
this proves not to be true problems will occur ... at the very least
features being split into multiple objects. The attributes attached to the
merged feature are based on the feature attribute table. In the past
these attributes were propagated to each of the primitive features.
Code in feature.c takes care of fetching all the primitive geometries, and
assembling them into a contiguous single polyline. This operation is based
on processing the primitive list, adding new primitives to a growing line
based on co-incident end points. The assembly starts with the first
primitive encountered, and primitives are added to this. The assembly
currently does an exact floating point comparison of end points. If there
is a possibility of round off differences in coordinate vertices within the
VPF files this assembly will fail ... in this case some tolerance test
would need to be applied. The "direction" of the final feature will be
based on the direction of the first primitive.
The _getObjectLine(), and _getObjectIdLine() functions have also been
updated to be "correct" for merged features.
$TOPDIR/ogdi/drivers/vrf/vrf.c
------------------------------
There is code in dyn_SelectLayer() which checks whether a join table
has a TILE_ID field before using it for features. This doesn't work for VITD
datasets which don't have a TILE_ID in the join tables. I have modified the
code as follows:
Old:
/*
Check if Tile_ID is defined in the join table, if not, it's an
attribute join
*/
#ifdef TESTOPENTABLE
printf("close lpriv->joinTable:%s\n");
#endif
if (table_pos("TILE_ID",lpriv->joinTable) == -1) {
vpf_close_table(&(lpriv->joinTable));
free(lpriv->joinTableName);
lpriv->joinTableName = NULL;
}
New:
/*
Check if Tile_ID is defined in the join table for tiled datasets, if
not, it's an attribute join.
There is no apparent way of identifying whether this is an
attribute join or not for non-tiled datasets such as VITD which don't
have TILE_ID, but do have feature joins so we assume in this case that
it is a feature join.
*/
#ifdef TESTOPENTABLE
printf("close lpriv->joinTable:%s\n");
#endif
/*
*/
if (table_pos("TILE_ID",lpriv->joinTable) == -1
&& lpriv->isTiled ) {
vpf_close_table(&(lpriv->joinTable));
free(lpriv->joinTableName);
lpriv->joinTableName = NULL;
}
$TOPDIR/ogdi/drivers/vrf/object.c
---------------------------------
In the _getTileAndPrimId() function the TILE_ID was again required
even
though previous code was initializing *tile_id to 1 for untiled
datasets.
I modified to skip check for TILE_ID if tile_id is already set.
Old:
if ((lpriv->joinTableName != NULL) &&
(table_pos("TILE_ID",lpriv->joinTable) != -1) &&
(table_pos(lpriv->featureTablePrimIdName,lpriv->joinTable) != -1)) {
join_row = get_row(object_id+1, lpriv->joinTable);
New:
if (lpriv->index[object_id].prim_id == -1) {
if ((lpriv->joinTableName != NULL) &&
(*tile_id != -1 || (table_pos("TILE_ID",lpriv->joinTable) != -1)) &&
(table_pos(lpriv->featureTablePrimIdName,lpriv->joinTable) != -1)) {
join_row = get_row(object_id+1, lpriv->joinTable);
$TOPDIR/vpflib/vpfprim.c
------------------------
There is a case in the create_edge_rec() function where the right_face
variable was passed in a call where the left_face attribute should have been
passed. This resulted in the right face id being substituted into the
edge structure in place of the left face id. This resulted in problems
reassembling areas, and in some cases the hang condition we say at
CubeWerx. I have included a fixed vpfprim.c in the vrf distribution
for now, but the fix can just be applied back against vpflib.
Old:
} else if (edge_table.header[left_face].type=='I') {
get_table_element( right_face, row, edge_table,
&(edge.left_face),
&count );
New:
} else if (edge_table.header[left_face].type=='I') {
get_table_element( left_face, row, edge_table,
&(edge.left_face),
&count ); /* NFW: This used to pass right_face! */
--- End forwarded message ---
Logged In: YES
user_id=17655
Patches applied to current CVS source.
Logged In: NO
There are several array bounds reads that eventually end up
resulting in an access violation.
Not sure if they are directly related to this, but
commenting out VRF_LINE_JOIN_HACK in vrf.h causes these
array bounds read errors to go away.