A
download polygonalyzation.pas
Language: Delphi
License: MPL11
Copyright: (c) 2003 Simdesign (www.simdesign.nl)
LOC: 169
Project Info
Filters
Server: SourceForge
Type: cvs
...ilters\Filters1\Src\Delphi\
   ...ractfilterNeighbor3.pas
   Chronometer.pas
   divers.pas
   filter.pas
   filterAdjust.pas
   filterArithmeticAdd.pas
   ...ithmeticConstantAdd.pas
   ...ArithmeticSubstract.pas
   filterBlobBalance.pas
   filterBlobExplorer.pas
   filterBlobGrouping.pas
   ...erBlobRepositioning.pas
   ...rBlobRepositioning2.pas
   filterBlur.pas
   filterCanny.pas
   filterContour.pas
   filterContrastExplorer.pas
   filterConvolution.pas
   filterCoocurenceMatrix.pas
   filterCopy.pas
   filterCorrelation.pas
   filterCutter.pas
   filterDistancesMap.pas
   filterExplorer.pas
   ...nisotropicDiffusion.pas
   ...GranularityExplorer.pas
   filterHistogram.pas
   ...erHistogramContrast.pas
   filterImageCreator.pas
   filterImageLoader.pas
   filterImageSaver.pas
   filterIntegration.pas
   filterInvert.pas
   filterLocalDeviation.pas
   filterLogPolar.pas
   filterMedian.pas
   filterMorphology.pas
   ...onMaximaSuppression.pas
   filterNormalize.pas
   filterOnOffCell.pas
   filterProjectionLine.pas
   filterPyramid.pas
   filterRescaleIntensity.pas
   filterResize.pas
   filterRotation.pas
   filterSigmoid.pas
   filterSmoothBilateral.pas
   filterSobel.pas
   filterSPV.pas
   filterStackProcessor.pas
   filterStackSmasher.pas
   ...erStandardDeviation.pas
   filterSUSAN.pas
   filterThresholdBinary.pas
   filterVectorHistogram.pas
   filterWavelets.pas
   filterWaves.pas
   fmask.pas
   fparameters.pas
   image.pas
   imageIO.pas
   imageIOVideo.pas
   lacModel.pas
   polygonalyzation.pas
   wrapper_itk.pas
   wrapper_opencv.pas

unit polygonalyzation;

interface
uses
  image;

type
  TApproximationMethod = (amDouglasPeucker,amSklanskyGonzalez);

function polygonalization_SklanskyGonzalez( const segmentList : TSegmentList; const apprimationAccuracy:Single; const imageMonitoring : PBitmap32) : TSegmentList;
function polygonalization_DouglasPeucker( const segmentList : TSegmentList; const apprimationAccuracy:Single; const imageMonitoring : PBitmap32) : TSegmentList;


implementation
uses
  Math;

{******************************************************************************}
{polygonalization method from Sklansky and Gonzalez (1980)}
function polygonalization_SklanskyGonzalez( const segmentList : TSegmentList; const apprimationAccuracy:Single; const imageMonitoring : PBitmap32) : TSegmentList;
var
  i : Integer;
  lastCriticalPoint : TFPoint;
  wedge, lastWedge : TWedge;
  vectorWidth : Single;
  vectorWidthCount : Integer;
  segment : TSegment;
  appoximatedSegmentList : TSegmentList;
begin
  SetLength(appoximatedSegmentList,0);
  if Length(segmentList)>0 then begin
    // approximation
    vectorWidth:=0;
    vectorWidthCount:=0;
    lastCriticalPoint:=segmentList[0].p1;
    lastWedge.line1.a:=math.MaxSingle;
    // for each segment
    for i:=0 to Length(segmentList)-1 do begin
      segment:=segmentList[i];
      vectorWidth:=vectorWidth+segment.width;
      Inc(vectorWidthCount);
      // for the first segment, we only calculate the first wedge
      if i>0 then begin
        // for next segment, check if the new point is inside the last wedge
        if isPointInWedge(segment.p2,lastWedge)=true then begin
          // if the point is inside, then it isn't critical
        end else begin
          // if the point is outside, then the last point is critical
          vectorWidth:=vectorWidth / vectorWidthCount;
          addSegment(appoximatedSegmentList,lastCriticalPoint,segment.p1,vectorWidth);
          vectorWidth:=segment.width;
          vectorWidthCount:=1;
          lastCriticalPoint:=segment.p1;
        end;
      end;
      // calculate the wedge at this new point
      wedge:=getWedge(lastCriticalPoint,segment.p2,lastWedge,apprimationAccuracy,imageMonitoring);
      lastWedge:=wedge;
    end;
    // the last point is critical in all case
    vectorWidth:=vectorWidth / vectorWidthCount;
    addSegment(appoximatedSegmentList,lastCriticalPoint,segment.p2,vectorWidth);
  end;
  Result:=appoximatedSegmentList;
end;

{******************************************************************************}
{polygonalization method from Douglas-Peucker polyline simplification algorithm}
{adaptation of the implementation of "http://www.simdesign.nl/Components/DouglasPeucker.html"
 here their licence :
  Implementation of the famous Douglas-Peucker polyline simplification
  algorithm.

  This file contains a 3D floating point implementation, for spatial
  polylines, as well as a 2D integer implementation for use with
  Windows GDI.

  Loosely based on C code from SoftSurfer (www.softsurfer.com)
  http://geometryalgorithms.com/Archive/algorithm_0205/algorithm_0205.htm

  References:
  David Douglas & Thomas Peucker, "Algorithms for the reduction of the number of
  points required to represent a digitized line or its caricature", The Canadian
  Cartographer 10(2), 112-122  (1973)

  Delphi code by Nils Haeck (c) 2003 Simdesign (www.simdesign.nl)
  http://www.simdesign.nl/components/douglaspeucker.html

  ****************************************************************
  The contents of this file are subject to the Mozilla Public
  License Version 1.1 (the "License"); you may not use this file
  except in compliance with the License. You may obtain a copy of
  the License at:
  http://www.mozilla.org/MPL/

  Software distributed under the License is distributed on an
  "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  implied. See the License for the specific language governing
  rights and limitations under the License.
}
function VecMinFloat3D(const A, B: TFPoint): TFPoint;
// Result = A - B
begin
  Result.X := A.X - B.X;
  Result.Y := A.Y - B.Y;
end;

function DotProdFloat3D(const A, B: TFPoint): double;
// Dotproduct = A * B
begin
  Result := A.X * B.X + A.Y * B.Y;
end;

function NormSquaredFloat3D(const A: TFPoint): double;
// Square of the norm |A|
begin
  Result := A.X * A.X + A.Y * A.Y;
end;

function DistSquaredFloat3D(const A, B: TFPoint): double;
// Square of the distance from A to B
begin
  Result := NormSquaredFloat3D(VecMinFloat3D(A, B));
end;

procedure SimplifyFloat3D(var Tol2: double;
  const Orig: array of TFPoint;
  var Marker: array of boolean; j, k: integer);
// Simplify polyline in OrigList between j and k. Marker[] will be set to True
// for each point that must be included
var
  i, MaxI: integer; // Index at maximum value
  MaxD2: double;    // Maximum value squared
  CU, CW, B: double;
  DV2: double;
  P0, P1, PB, U, W: TFPoint;
begin
  // Is there anything to simplify?
  if k <= j + 1 then exit;

  P0 := Orig[j];
  P1 := Orig[k];
  U  := VecMinFloat3D(P1, P0); // Segment vector
  CU := DotProdFloat3d(U, U); // Segment length squared
  MaxD2 := 0;
  MaxI  := 0;

  // Loop through points and detect the one furthest away
  for i := j + 1 to k - 1 do begin
    W  := VecMinFloat3D(Orig[i], P0);
    CW := DotProdFloat3D(W, U);

    // Distance of point Orig[i] from segment
    if CW <= 0 then begin
      // Before segment
      DV2 := DistSquaredFloat3D(Orig[i], P0)
    end else begin
      if CW > CU then begin
        // Past segment
        DV2 := DistSquaredFloat3D(Orig[i], P1);
      end else begin
        // Fraction of the segment
        try
          B := CW / CU;
        except
          B := 0; // in case CU = 0
        end;
        PB.X := P0.X + B * U.X;
        PB.Y := P0.Y + B * U.Y;
        DV2 := DistSquaredFloat3D(Orig[i], PB);
      end;
    end;

    // test with current max distance squared
    if DV2 > MaxD2 then begin
      // Orig[i] is a new max vertex
      MaxI  := i;
      MaxD2 := DV2;
    end;
  end;

  // If the furthest point is outside tolerance we must split
  if MaxD2 > Tol2 then begin // error is worse than the tolerance

    // split the polyline at the farthest vertex from S
    Marker[MaxI] := True;  // mark Orig[maxi] for the simplified polyline

    // recursively simplify the two subpolylines at Orig[maxi]
    SimplifyFloat3D(Tol2, Orig, Marker, j, MaxI); // polyline Orig[j] to Orig[maxi]
    SimplifyFloat3D(Tol2, Orig, Marker, MaxI, k); // polyline Orig[maxi] to Orig[k]
  end;
end;

function PolySimplifyFloat3D(Tol: double;
    const Orig: array of TFPoint;
    var Simple: array of TFPoint): integer;
var
  i, N: integer;
  Marker: array of boolean;
  Tol2: double;
begin
  Result := 0;
  if length(Orig) < 2 then exit;
  Tol2 := sqr(Tol);

  // Create a marker array
  N := Length(Orig);
  SetLength(Marker, N);
  // Include first and last point
  Marker[0]     := True;
  Marker[N - 1] := True;
  // Exclude intermediate for now
  for i := 1 to N - 2 do
    Marker[i] := False;

  // Simplify
  SimplifyFloat3D(Tol2, Orig, Marker, 0, N - 1);

  // Copy to resulting list
  for i := 0 to N - 1 do begin
    if Marker[i] then begin
      Simple[Result] := Orig[i];
      inc(Result);
    end;
  end;
end;

function polygonalization_DouglasPeucker( const segmentList : TSegmentList; const apprimationAccuracy:Single; const imageMonitoring : PBitmap32) : TSegmentList;
var
  originalPointArray, simplifiedPointArray : array of TFPoint;
  s, p : integer;
  simplifiedPointArrayLength : integer;
  segmentListLength : integer;
begin
  segmentListLength:=Length(segmentList);
  if segmentListLength>0 then begin
    // convert a list of segment to a list of point
    SetLength(originalPointArray,segmentListLength+1);
    p:=0;
    for s:=0 to segmentListLength-1 do begin
      originalPointArray[p]:=segmentList[s].p1;
      Inc(p);
    end;
    originalPointArray[p]:=segmentList[segmentListLength-1].p2;
    // call implementation of Douglas-Peucker algorithm
    SetLength(simplifiedPointArray, Length(originalPointArray));
    simplifiedPointArrayLength:=PolySimplifyFloat3D(apprimationAccuracy,originalPointArray,simplifiedPointArray);
    SetLength(simplifiedPointArray,simplifiedPointArrayLength);
    // convert a list of point to a list of segment
    SetLength(Result,simplifiedPointArrayLength-1);
    s:=0;
    for p:=0 to simplifiedPointArrayLength-2 do begin
      Result[s].p1:=simplifiedPointArray[p];
      Result[s].p2:=simplifiedPointArray[p+1];
      Inc(s);
    end;
    SetLength(originalPointArray,0);
    SetLength(simplifiedPointArray,0);
  end;
end;

{******************************************************************************}

end.

About Koders | Resources | Downloads | Support | Black Duck | Terms of Service | DMCA | Privacy Policy | Contact Us