[GRASS5] Nested vector islands, and incorrect left/right poly id's for island edges...

It appears that GRASS doesn't write correct information for
left/right adjaceny for edges of areas nested more than
one polygon deep. That is: If polygon 1, contains polygon
2, and polygon 2 contains polygon 3, the lines comprising
polygon 3 will have polygon 1 written as the adjacent area
for either left or right, when I would think it should be
polygon 2.

I was trying to work up a way to do the following:

  Given an area with N islands/holes. Create a set of
  interior boundaries such that islands/holes that
  share one or more edges are combined into a single
  boundary (with interior edges being dropped).

I tried to write a little program that iterated through
areas, and their islands, reporting the lines for all
and the reported line left/right indices. That's when
I discovered, I was getting islands where none of the
edges reported being adjacent to their immediate parent.

I guess, next I'll try using nodes instead of edges. If
anyone familiar with the guts of the vector libraries
(Radim, David ?) wants to point me in the right direction,
I'd appreciate it...

Attached: area_report.c & Gmakefile

--
Eric G. Miller <egm2@jps.net>

(attachments)

area_report.c (1.78 KB)
Gmakefile (181 Bytes)

Eric G. Miller wrote:

It appears that GRASS doesn't write correct information for
left/right adjaceny for edges of areas nested more than
one polygon deep. That is: If polygon 1, contains polygon
2, and polygon 2 contains polygon 3, the lines comprising
polygon 3 will have polygon 1 written as the adjacent area
for either left or right, when I would think it should be
polygon 2.

Yes I would have thought so.

I was trying to work up a way to do the following:

  Given an area with N islands/holes. Create a set of
  interior boundaries such that islands/holes that
  share one or more edges are combined into a single
  boundary (with interior edges being dropped).

I don't quite understand how islands can share edges. I thought in the earlier posting you meant that an edge of an island can be the same as that of an (outer) ring. If two 'islands' share a boundary, then they are actually the constituent cells of an island, not the island itself. If the build routine is creating islands within a polygon that abut, then that is a bug.

I have recently been developing a terminology that helps to create a more formal link between the intuitive notions and the topological and geometric concepts in common circulation.

Four concepts:

Holes <-------------------------> Hulls

   | |

  | |

Islands <-------------------------> Cells

Holes and hulls are defined in relation to an individual polygon. In practical terms, a polygon is the interior of a fully connected open subspace of the whole, union'd with its closure. Without going into that too deeply, it can be thought of as the boundary, but purely in terms of a limiting bound to the interior, with no conception of edges, nodes etc. Exterior boundaries (only one) consitutes the 'hull' and interior boundaries the 'holes'. You can tell if its a hole or a hull by tracknig from an arbitrary interior point to a boundary point on the subject boundary. Then track right, and follow the boundary round to its starting point (we've dropped to geometrical operations here). If the boundary is traversed clockwise it is a hull; if anti-clockwise it is a hole.

Islands and cells are defined in relation to the boundary system of a coverage, which really is a network with some constraints. You start at a node or track from an arbitrary point to a node, and continue tracking, always following the right-most link at each node, until you get back to the starting point. If you circulate clockwise, it is a cell, and if anti-clockwise, it's an island. An 'island' is the boundary set of a subspace whose interior is an 'aggregate' of cells, union'd with that interior. A 'cell' is a subspace whose interior union'd with the cell boundary co-incides with a polygon. If an island has only a single cell it is a 'simple island' (though it can have islands of its own), and is also a cell in its own right.

The first set of definitions is similar in structure to the kind of polygon coverage that is found in shapefiles for examples, while the latter is like that found in GRASS, Arc/Info etc.

This is quite detailed, as it ties in to formal topological theory, but it's useful for us as it highlights some important areas - how the different kinds of coverage that are used relate to different aspects of the topology of the coverage, polygons relate to interior sets, 'topological' coverages to boundary sets. There's also the practical trick of tracking right or left to distinguish inner and outer components.

I tried to write a little program that iterated through
areas, and their islands, reporting the lines for all
and the reported line left/right indices. That's when
I discovered, I was getting islands where none of the
edges reported being adjacent to their immediate parent.

I guess, next I'll try using nodes instead of edges. If
anyone familiar with the guts of the vector libraries
(Radim, David ?) wants to point me in the right direction,
I'd appreciate it...

I haven't tried this yet - I'll look now and see if I can confirm this bug. We have to sort that out priority A1 if there is, and then I think that should solve the problem.

David

Attached: area_report.c & Gmakefile

------------------------------------------------------------------------

#include <stdio.h>
#include <stdlib.h>
#include "gis.h"
#include "Vect.h"

int main (int argc, char **argv)
{
  struct Option *opt_map;
  struct Map_info map;
  char *mapset;
  int i, j, k, att;
  int isle_area;
  P_AREA *area;
  P_LINE *line;
  P_ISLE *isle;
  
  opt_map = G_define_option();
  opt_map->key = "map";
  opt_map->required = YES;
  opt_map->gisprompt = "dig,old,vector";

  G_gisinit(argv[0]);

  if (G_parser (argc, argv))
    exit (EXIT_FAILURE);

  if (NULL == (mapset = G_find_file2 ("dig", opt_map->answer, "")))
    G_fatal_error ("Vector map [%s] not found!", opt_map->answer);

  if (V2_open_old (&map, opt_map->answer, mapset))
    G_fatal_error ("Couldn't open vector map at level 2!");

  for (i = 1; i <= map.n_areas; i++)
  {
    fprintf (stdout, "Area %d {\n", i);
    att = V2_area_att (&map, i);
    fprintf (stdout, " dig_att = %d\n", att);
    
    V2_get_area (&map, i, &area);

    fprintf (stdout, " lines {\n");
    for (j = 0; j < area->n_lines; j++) {
      line = &(map.Line[abs(area->lines[j])]);
      fprintf (stdout, " line %d, left %d, right %d\n",
          area->lines[j],
          line->left, line->right);
    }
    fprintf (stdout, " }\n");

    for (j = 0; j < area->n_isles; j++)
    {
      fprintf (stdout, " Island %d {\n", area->isles[j]);
      isle = &(map.Isle[area->isles[j]]);
      fprintf (stdout, " Lines {\n");
      for (k = 0; k < isle->n_lines; k++)
      {
        line = &(map.Line[abs(isle->lines[k])]);
        fprintf (stdout, " Line %d, LeftArea %d, RightArea %d\n",
            isle->lines[k],
            line->left,
            line->right);
      }
      if (i == abs(line->left)) isle_area = abs(line->right);
      else if (i == abs(line->right))
        isle_area = abs(line->left);
      else isle_area = -1;
      
      fprintf (stdout, " } = Area %d\n }\n", isle_area );
    }
    
    fprintf (stdout, "}\n");
  }
      
  return 0;
}

Eric G. Miller wrote:

[...]
I tried to write a little program that iterated through
areas, and their islands, reporting the lines for all
and the reported line left/right indices. That's when
I discovered, I was getting islands where none of the
edges reported being adjacent to their immediate parent.

I guess, next I'll try using nodes instead of edges. If
anyone familiar with the guts of the vector libraries
(Radim, David ?) wants to point me in the right direction,
I'd appreciate it...

Attached: area_report.c & Gmakefile

Eric

I've now run your script on some files. I can't confirm that there are any cases of islands being incorrectly built. they all appear as I (and Radim) described earlier, ie. with no internal boundaries separating different cells, of course you may have found some.

The matter with area assignments to islands' lines is different. I couldn't repeat the problem you reported, but found something else equally bizarre:

I tested a small map with three chinese eggs, each of two segments, and the ouput is as follows: [going inwards]

Area 1 {
   dig_att = 0
   lines {
     line 1, left -1, right 1
     line 2, left -1, right 1
   }
   Island 2 {
     Lines {
       Line -3, LeftArea -2, RightArea 2
       Line 4, LeftArea 2, RightArea -2
     } = Area -1
   }
}
Area 2 {
   dig_att = 0
   lines {
     line 3, left -2, right 2
     line -4, left 2, right -2
   }
   Island 3 {
     Lines {
       Line 5, LeftArea 3, RightArea -3
       Line -6, LeftArea -3, RightArea 3
     } = Area -1
   }
}
Area 3 {
   dig_att = 0
   lines {
     line -5, left 3, right -3
     line 6, left -3, right 3
   }
}

All the lines here appear to have the same area on each side. So the assignment of left/right area seems to be getting mangled. Could this be giving the errors with internal boundaries, or apparent boundaries?

Anyway this definately needs looking into. It's getting late here, so it will have to wait till tomorrow evening now, but I'll get back if I find anything.

David

On Tue, 22 Jan 2002 20:19:42 +0000, David D Gray <ddgray@armadce.demon.co.uk> wrote:

Eric G. Miller wrote:

> It appears that GRASS doesn't write correct information for
> left/right adjaceny for edges of areas nested more than
> one polygon deep. That is: If polygon 1, contains polygon
> 2, and polygon 2 contains polygon 3, the lines comprising
> polygon 3 will have polygon 1 written as the adjacent area
> for either left or right, when I would think it should be
> polygon 2.
>

Yes I would have thought so.

> I was trying to work up a way to do the following:
>
> Given an area with N islands/holes. Create a set of
> interior boundaries such that islands/holes that
> share one or more edges are combined into a single
> boundary (with interior edges being dropped).
>

I don't quite understand how islands can share edges. I thought in the
earlier posting you meant that an edge of an island can be the same as
that of an (outer) ring. If two 'islands' share a boundary, then they
are actually the constituent cells of an island, not the island itself.
If the build routine is creating islands within a polygon that abut,
then that is a bug.

I'm perhaps not being clear. Area A, contains areas B, C and D.
Areas B and C share a common edge. Therefore, the interior boundaries
of A are formed from the exterior boundaries of D and the minimal
boundary enclosing B and C. However, when I iterate through the
islands in GRASS (Vect_get_isles_points), each boundary of each
interior area (B, C, and D) is returned, and therefore I get
duplicate linework for the common boundary of B and C.

At least, that seems to be what is going on. So, now I'm looking at
eliminating those common edges, but apparently I can't rely on the
line -> area adjacency information, so I'll have to use a "seen list"
instead. But at this point, I think I'm wasting my time on the
simplified, scanline, polygon simplification algorithm I've been using,
and I might as well just try implementing a generic scan line rasterizer.
The overhead of the "simplified" solution seems to be getting to high,
where it won't yield much (if any) performance benefit.

--
Eric G. Miller <egm2@jps.net>

On Wed, 23 Jan 2002 01:02:48 +0000, David D Gray <ddgray@armadce.demon.co.uk> wrote:

Eric

I've now run your script on some files. I can't confirm that there are
any cases of islands being incorrectly built. they all appear as I (and
Radim) described earlier, ie. with no internal boundaries separating
different cells, of course you may have found some.

Okay. I'll double check my code on the colinearity test. I found some
other bugs, so maybe this was a red herring.

The matter with area assignments to islands' lines is different. I
couldn't repeat the problem you reported, but found something else
equally bizarre:

I tested a small map with three chinese eggs, each of two segments, and
the ouput is as follows: [going inwards]

Area 1 {
   dig_att = 0
   lines {
     line 1, left -1, right 1
     line 2, left -1, right 1
   }
   Island 2 {
     Lines {
       Line -3, LeftArea -2, RightArea 2
       Line 4, LeftArea 2, RightArea -2
     } = Area -1
   }
}
Area 2 {
   dig_att = 0
   lines {
     line 3, left -2, right 2
     line -4, left 2, right -2
   }
   Island 3 {
     Lines {
       Line 5, LeftArea 3, RightArea -3
       Line -6, LeftArea -3, RightArea 3
     } = Area -1
   }
}
Area 3 {
   dig_att = 0
   lines {
     line -5, left 3, right -3
     line 6, left -3, right 3
   }
}

All the lines here appear to have the same area on each side. So the
assignment of left/right area seems to be getting mangled. Could this be
giving the errors with internal boundaries, or apparent boundaries?

I will hypothesize there is a confusion about Island id's and Area id's.
On the one's where I saw problems, for Island edges, one of the adjacency
id's always matched the Island id. Except for the last area, the id's
may be referring to different types of things (one area, one island).

I'm not real familiar with the vector library, so you might double check
that I'm not somehow abusing the Map_info structure. I basically
hacked that little script together on what I could glean from a couple
library routines (and how they used the struct).

--
Eric G. Miller <egm2@jps.net>

On Tuesday 22 January 2002 08:32, Eric G. Miller wrote:

It appears that GRASS doesn't write correct information for
left/right adjaceny for edges of areas nested more than
one polygon deep. That is: If polygon 1, contains polygon
2, and polygon 2 contains polygon 3, the lines comprising
polygon 3 will have polygon 1 written as the adjacent area
for either left or right, when I would think it should be
polygon 2.

We have to distinguish areas and isles.
Are you sure that polygon1 is area1 and is not island1?

I was trying to work up a way to do the following:

  Given an area with N islands/holes. Create a set of
  interior boundaries such that islands/holes that
  share one or more edges are combined into a single
  boundary (with interior edges being dropped).

I tried to write a little program that iterated through
areas, and their islands, reporting the lines for all
and the reported line left/right indices. That's when
I discovered, I was getting islands where none of the
edges reported being adjacent to their immediate parent.

For boundary inside other area (-island) is saved instead of (+area) for
outside area side. Sorry, you probably know that all.

I guess, next I'll try using nodes instead of edges. If
anyone familiar with the guts of the vector libraries
(Radim, David ?) wants to point me in the right direction,
I'd appreciate it...

Attached: area_report.c & Gmakefile

You may be interested in grass51. I have v.build option=dump
( Vect_dump() ) and d.vect display=topo,dir (topo - topology
numbers, dir - direction of lines - arrow). I hope to commit
this week.

Radim

On Wed, 23 Jan 2002 06:03:56 +0100, Radim Blazek <radim.blazek@wo.cz> wrote:

On Tuesday 22 January 2002 08:32, Eric G. Miller wrote:
> It appears that GRASS doesn't write correct information for
> left/right adjaceny for edges of areas nested more than
> one polygon deep. That is: If polygon 1, contains polygon
> 2, and polygon 2 contains polygon 3, the lines comprising
> polygon 3 will have polygon 1 written as the adjacent area
> for either left or right, when I would think it should be
> polygon 2.

We have to distinguish areas and isles.
Are you sure that polygon1 is area1 and is not island1?

No, I'm not sure?? I am sure, that each of the three polygons
are labelled areas with 3 inside 2, and 2 inside 1. Therefore, to
draw 1, I want to eliminate 2 from 1. And, to draw 2, I
want to eliminate 3 from 2. Drawing 3 is straight forward.

>
> I was trying to work up a way to do the following:
>
> Given an area with N islands/holes. Create a set of
> interior boundaries such that islands/holes that
> share one or more edges are combined into a single
> boundary (with interior edges being dropped).
>
> I tried to write a little program that iterated through
> areas, and their islands, reporting the lines for all
> and the reported line left/right indices. That's when
> I discovered, I was getting islands where none of the
> edges reported being adjacent to their immediate parent.

For boundary inside other area (-island) is saved instead of (+area) for
outside area side. Sorry, you probably know that all.

Yes, but if I get the interior boundary, Island, then look at
it's edges, shouldn't those edges have either the left or
right adjacency as the area number for the exterior. I find,
that is the case when there is only one level of nesting.
But in subsequent levels, the interior edges say they are
adjacent not to the immediate exterior area, but to the
area outside. That is, from the example above, the
edges of 3 say they are bounded by 1, rather than 2,
even though 2 is the closest containing area.

> I guess, next I'll try using nodes instead of edges. If
> anyone familiar with the guts of the vector libraries
> (Radim, David ?) wants to point me in the right direction,
> I'd appreciate it...
>
> Attached: area_report.c & Gmakefile

You may be interested in grass51. I have v.build option=dump
( Vect_dump() ) and d.vect display=topo,dir (topo - topology
numbers, dir - direction of lines - arrow). I hope to commit
this week.

Yes, to look at it might help me understand GRASS's idea of
topology.

--
Eric G. Miller <egm2@jps.net>

On Tue, 22 Jan 2002 18:15:45 -0800, "Eric G. Miller" <egm2@jps.net> wrote:

On Wed, 23 Jan 2002 01:02:48 +0000, David D Gray <ddgray@armadce.demon.co.uk> wrote:

> Eric
>
> I've now run your script on some files. I can't confirm that there are
> any cases of islands being incorrectly built. they all appear as I (and
> Radim) described earlier, ie. with no internal boundaries separating
> different cells, of course you may have found some.

Okay. I'll double check my code on the colinearity test. I found some
other bugs, so maybe this was a red herring.

I found the bug in my code. Oops! The other issue still puzzles me
though...

--
Eric G. Miller <egm2@jps.net>