[postgis-users] How to generalize or simplify a Polygon

oscar.gomez at telvent.abengoa.com oscar.gomez at telvent.abengoa.com
Thu Aug 28 09:31:54 PDT 2003


Matt,

There is no way to run the Avenue routine outside ArcView GIS, and I 
wouldn't recommend it's use on server-side.

I just wanted to show an implementation of Douglas-Peucker algorithm which 
effectively generalizes a feature mantaining it's main shape.

If I were you, I would search for a library or component that would let 
you open and edit shapefiles, such as JShape. There are plenty of them, as 
long as shapefile format is public. Using this library you can build a 
generalization routine based on Douglas - Peucker algorithm, editing each 
feature's vertices. Then run shp2psql.

Hope this helps.

Best Regards,



--------------------------------------------------------------------
Óscar Gómez                        oscar.gomez at telvent.abengoa.com
Analista/Consultor GIS             Centralita: +34 - 954 92 09 92
Telvent                            Tfno. directo: +34 - 954 32 18 19
Tamarguillo, 29                    Fax: +34 - 954 92 64 24
41006 Sevilla (España)             URL: http://www.telvent.com
--------------------------------------------------------------------







"Matt Lynch" <matt at terraEngine.com>


"Matt Lynch" <matt at terraEngine.com>
Enviado por: postgis-users-bounces at postgis.refractions.net
28/08/2003 18:20
Por favor, responda a PostGIS Users Discussion

 
        Para:   "'PostGIS Users Discussion'" 
<postgis-users at postgis.refractions.net>
        cc: 
        Asunto: RE: [postgis-users] How to generalize or simplify a 
Polygon


Hi Oscar,

Thanks for the code! 

I am not sure I can use it, however.  I haven't been totally clear on
how I plan to use the generalization routine.
My goal is to have the shapefile submitted via a webservice, generalized
by the webservice, and then imported into postgis. 

This means I need one of the following:

1) a postgis operation
2) a commandline utility (DOS executable)
3) VB,C#,C++, or C code

That is unless there is a runtime engine for Avenue.  I am not very
familiar with Avenue, and I did do a search on the ESRI site for an
Avenue runtime, but did not find one.   If you could point me to one,
your solution would be perfect.

Regards,

Matt

-----Original Message-----
From: postgis-users-bounces at postgis.refractions.net
[mailto:postgis-users-bounces at postgis.refractions.net] On Behalf Of
oscar.gomez at telvent.abengoa.com
Sent: Thursday, August 28, 2003 9:49 AM
To: PostGIS Users Discussion
Subject: Re: [postgis-users] How to generalize or simplify a Polygon


This is an ArcView-Avenue implementation of the Douglas - Peucker 
algorithm to generalize a polyline or polygon feature's vertices.

Good luck,

Oscar Gomez
IT Consultant
Telvent


theView = av.GetActiveDoc
thePrj = theView.GetProjection
if (thePrj.IsNull) then
  hasPrj = false
else
  hasPrj = true
  thePrj = theView.GetProjection
end

' Get active themes

theThemes = theView.GetActiveThemes

if (theThemes.Count < 1) then
  MsgBox.Error("Please make a polyline or polygon theme active","***
Error 
***")
  exit
end

' Process each active theme

for each t in theThemes

  ' Check that the theme is of the correct type

  if (t.Is( FTHEME).Not) then
    MsgBox.Error (t.GetName++"is not a polyline or polygon theme","*** 
Error ***")
    continue
  end

  theClassName = t.GetFTab.GetShapeClass.GetClassName
  if ((theClassName = "Polygon").Not and (theClassName =
"Polyline").Not) 
then
    MsgBox.Error (t.GetName++"is not a polyline or polygon theme","*** 
Error ***")
    continue
  end

  ' Get a tolerance in (distance units) to be used (must be > 0)

  theTol = 0
  theMUnits = theView.GetDisplay.GetUnits
  theDUnits = theView.GetDisplay.GetDistanceUnits
  theUStr = Units.GetFullUnitString(theDUnits).LCase
  while ((theTol <= 0) or (theTol.AsString.IsNumber).Not)
    theTol = MsgBox.Input("Positive tolerance value (in "+theUStr+
         ") for theme"++t.GetName,"Tolerance",theTol.AsString)
    if (theTol = NIL) then exit end

    if (theTol.IsNumber) then
      theTol = theTol.AsNumber
    end
  end
  theTol = Units.Convert(theTol,theDUnits,theMUnits)

  ' Get the name for a new theme, from View.Export script

  def = av.GetProject.MakeFileName("theme", "shp")
  def = FileDialog.Put(def, "*.shp", "New file for simplified "+ 
t.getName)

  if (def = NIL) then return nil end

  ' Create a new shapefile theme, from View.Export script

  tbl = t.GetFtab
  shpfld = (tbl.FindField("Shape"))
  if (shpfld.IsVisible.Not) then
    shpfld.SetVisible(shpfld.IsVisible.Not)
    WasNotVisible = TRUE
  else
    WasNotVisible =FALSE
  end

  ' This will only export the selected shapes, if any have been selected

  av.ShowMsg("Creating new shape file from"++ t.GetName)
  anFTab = tbl.Export(def, Shape, tbl.GetSelection.Count > 0)
  anFTab.SetEditable(true)

  if (WasNotVisible) then
    shpfld.SetVisible(FALSE)
  end

  ' Find the shape field

  theSField = anFTab.FindField("Shape")

  ' Set up status bar

  av.ShowMsg("Generalizing new shapes from theme"++ t.GetName)
  theSize = anFTab.GetNumRecords

  ' Initialize counters for reporting

  count = 0
  oldCount = 0
  newCount = 0

  ' Process each shape

  for each r in anFTab

    av.SetStatus(100*count/theSize)

    ' Retrieve shape

    if (theClassName = "Polygon") then
      theOShape = Polygon.MakeNull
    else
      theOShape = Polyline.MakeNull
    end
    anFTab.QueryShape(r,theView.GetProjection,theOShape)

    ' Make a list for collecting the new set of point lists

    theNShape = List.Make

    ' Process each list in the ListofListofPoints

    for each p in theOShape.AsList

      ' Make a list for collecting the vertices to keep

      theNList = List.Make

      oldCount = oldCount + p.Count

      ' Set up stack for holding a set of lists of form {index,point}

      theStack = Stack.Make

      ' Add first point to the list being assembled, and make it the 
anchor

      theAnchor = p.Get(0)
      if (hasPrj) then
        theNList.Add(theAnchor.ReturnUnProjected(thePrj))
      else
        theNList.Add(theAnchor)
      end
      aIndex = 0

      ' Add last point to stack

      fIndex = p.Count - 1
      theStack.Push({fIndex,p.Get(fIndex)})

      ' Process the points with the Douglas - Peucker approach

       while (theStack.IsEmpty.Not)

        ' Process from Anchor (beginning) to Floater (top of stack)

        fIndex = theStack.Top.Get(0)

        ' Create graphic shape for comparing distances

        theVect = Line.Make(theAnchor,theStack.Top.Get(1))

        ' Initialize values for comparison

        theMax = theTol
        mxIndex = 0

        ' Find distance

        for each i in (aIndex + 1) .. (fIndex - 1) ' process middle
points

          dist = theVect.Distance(p.Get(i))

          ' Check against previous maximum

          if (dist >= theMax) then  ' this point is out of the tolerance
            theMax = dist
            mxIndex = i
          end

        end

        ' If a vertex is found outside the current tolerance corridor,
        ' push it onto the stack

        if (mxIndex > 0) then 'a new floater has been found
          theStack.Push({mxIndex,p.Get(mxIndex)})
        else  ' add floater to the list for the new shape and move
forward
          if (hasPrj) then
            theNList.Add(theStack.Top.Get(1).ReturnUnProjected(thePrj))
          else
            theNList.Add(theStack.Top.Get(1))
          end

          ' Make the floater the new anchor

          theAnchor = theStack.Pop.Get(1)
          aIndex = fIndex

        end

      end

      ' Check for collapsed polygons

      if ((theNList.Count < 4) and (theClassName = "Polygon")) then
         ' Revert to original polygon
        if (hasPrj) then
          theNList = List.Make
          for each pt in p
            theNList.Add(pt.ReturnUnProjected(thePrj))
          end
        else
          theNList = p
        end

      end

      ' Finish up individual lists

      newCount = newCount + theNList.Count
      theNShape.Add(theNList)

    end

    ' Finish up the shape

    if (theClassName = "Polygon") then
      theNShape = Polygon.Make(theNShape)
    else
      theNShape = Polyline.Make(theNShape)
    end
    anFTab.SetValue(theSField, r, theNShape)
    count = count + 1

  end

  ' Clear status message

  av.ClearMsg
  av.ClearStatus

  ' Report on counts of old and new theme

  MsgBox.Info("The old theme with"++ oldCount.AsString ++
      "vertices has been generalized to"++
        newCount.AsString++"vertices","Results")

  ' Create a theme and add it to the View

  anFTab.SetEditable(false)
  fthm = FTheme.Make(anFTab)
  theView.AddTheme(fthm)

end

' Bring the View to the front

theView.GetWin.Activate




"Matt Lynch" <matt at terraEngine.com>


"Matt Lynch" <matt at terraEngine.com>
Enviado por: postgis-users-bounces at postgis.refractions.net
28/08/2003 17:45
Por favor, responda a PostGIS Users Discussion

 
        Para:   <postgis-users at postgis.refractions.net>
        cc: 
        Asunto: [postgis-users] How to generalize or simplify a Polygon


Hi,

I have an application where I will be accepting a shape file (polygon)
to define a region of permitted access for a user which will be imported
to postgis.  That shape file has the potential to have many points if
the region defined has a border like a river or lake.  Are there any
functions or tools available that would take a polygon shape and reduce
or generalize the number of points in the polygon?  The resulting
polygon must cover at least as much area as the original.

Thanks,

Matt

---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.507 / Virus Database: 304 - Release Date: 8/4/2003
 



_______________________________________________
postgis-users mailing list postgis-users at postgis.refractions.net
http://postgis.refractions.net/mailman/listinfo/postgis-users




_______________________________________________
postgis-users mailing list postgis-users at postgis.refractions.net
http://postgis.refractions.net/mailman/listinfo/postgis-users

---
Incoming mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.507 / Virus Database: 304 - Release Date: 8/4/2003
 

---
Outgoing mail is certified Virus Free.
Checked by AVG anti-virus system (http://www.grisoft.com).
Version: 6.0.507 / Virus Database: 304 - Release Date: 8/4/2003
 



_______________________________________________
postgis-users mailing list
postgis-users at postgis.refractions.net
http://postgis.refractions.net/mailman/listinfo/postgis-users






More information about the postgis-users mailing list