5203d61969
* NEW: ImageEditor: The image size is displayed wen the mouse cursor is outside of the view. Many bug fixes. The magic wand has been implemented. JIT compiler is used to speed-up the routine. [GB.CLIPPER] * NEW: Clipper.OffsetPolygons has been renamed as Clipper.Offset. * NEW: Clipper.Simplify and Clipper.Clean methods have been implemented. [GB.DESKTOP] * NEW: DesktopFile.Run() method now returns the created process object. [GB.IMAGE] * NEW: Color.Distance() is a new method that returns the RGBA distance between two colours as a floating point value between 0.0 and 1.0. git-svn-id: svn://localhost/gambas/trunk@5792 867c0c6c-44f3-4631-809d-bfa615b0a4ec
208 lines
5.3 KiB
C++
208 lines
5.3 KiB
C++
/***************************************************************************
|
|
|
|
c_clipper.cpp
|
|
|
|
(c) 2000-2013 Benoît Minisini <gambas@users.sourceforge.net>
|
|
|
|
This program is free software; you can redistribute it and/or modify
|
|
it under the terms of the GNU General Public License as published by
|
|
the Free Software Foundation; either version 2, or (at your option)
|
|
any later version.
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
GNU General Public License for more details.
|
|
|
|
You should have received a copy of the GNU General Public License
|
|
along with this program; if not, write to the Free Software
|
|
Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
|
MA 02110-1301, USA.
|
|
|
|
***************************************************************************/
|
|
|
|
#define __C_CLIPPER_CPP
|
|
|
|
#include "main.h"
|
|
#include "gb.geom.h"
|
|
#include "c_clipper.h"
|
|
#include "clipper.hpp"
|
|
|
|
using namespace ClipperLib;
|
|
|
|
#define SCALE 1000000.0
|
|
|
|
static IntPoint to_point(GEOM_POINTF *point)
|
|
{
|
|
return IntPoint(point->x * SCALE + 0.5, point->y * SCALE + 0.5);
|
|
}
|
|
|
|
static GEOM_POINTF *from_point(IntPoint p)
|
|
{
|
|
return GEOM.CreatePointF((double)p.X / SCALE, (double)p.Y / SCALE);
|
|
}
|
|
|
|
/*static bool is_closed(GB_ARRAY p)
|
|
{
|
|
if (!p)
|
|
return false;
|
|
|
|
int count = GB.Array.Count(p);
|
|
if (count <= 1)
|
|
return false;
|
|
|
|
GEOM_POINTF **ap = (GEOM_POINTF **)GB.Array.Get(p, 0);
|
|
return ap[0]->x == ap[count - 1]->x && ap[0]->y == ap[count - 1]->y;
|
|
}*/
|
|
|
|
static bool to_polygons(Polygons &polygons, GB_ARRAY array)
|
|
{
|
|
int count;
|
|
GB_ARRAY a;
|
|
int i, j;
|
|
GEOM_POINTF **ap;
|
|
GEOM_POINTF *pp;
|
|
|
|
if (GB.CheckObject(array))
|
|
return true;
|
|
|
|
count = GB.Array.Count(array);
|
|
if (count == 0)
|
|
return false;
|
|
|
|
polygons.resize(count);
|
|
|
|
for(i = 0; i < count; i++)
|
|
{
|
|
a = *(GB_ARRAY *)GB.Array.Get(array, i);
|
|
if (!a)
|
|
continue;
|
|
ap = (GEOM_POINTF **)GB.Array.Get(a, 0);
|
|
|
|
for (j = 0; j < GB.Array.Count(a); j++)
|
|
{
|
|
pp = ap[j];
|
|
if (!pp)
|
|
continue;
|
|
//fprintf(stderr, "<< %d %d: %g %g\n", i, j, pp->x, pp->y);
|
|
polygons[i].push_back(to_point(pp));
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
static GB_ARRAY from_polygons(Polygons &polygons, GB_ARRAY array)
|
|
{
|
|
GB_ARRAY a;
|
|
GB_ARRAY p;
|
|
uint i, j, n;
|
|
GEOM_POINTF *pp;
|
|
|
|
GB.Array.New(&a, GB.FindClass("PointF[]"), polygons.size());
|
|
for (i = 0; i < polygons.size(); i++)
|
|
{
|
|
n = polygons[i].size();
|
|
if (n == 0)
|
|
continue;
|
|
|
|
GB.Array.New(&p, GB.FindClass("PointF"), n);
|
|
|
|
for (j = 0; j < n; j++)
|
|
{
|
|
pp = from_point(polygons[i][j]);
|
|
//fprintf(stderr, ">> %d %d: %g %g\n", i, j, pp->x, pp->y);
|
|
*(GEOM_POINTF **)GB.Array.Get(p, j) = pp;
|
|
GB.Ref(pp);
|
|
}
|
|
|
|
// Close polygon
|
|
pp = from_point(polygons[i][0]);
|
|
//fprintf(stderr, ">> %d %d: %g %g\n", i, j, pp->x, pp->y);
|
|
*(GEOM_POINTF **)GB.Array.Add(p) = pp;
|
|
GB.Ref(pp);
|
|
|
|
*(GB_ARRAY *)GB.Array.Get(a, i) = p;
|
|
GB.Ref(p);
|
|
}
|
|
|
|
return a;
|
|
}
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
BEGIN_METHOD(Clipper_Offset, GB_OBJECT polygons; GB_FLOAT delta; GB_INTEGER join; GB_FLOAT limit; GB_BOOLEAN do_not_fix)
|
|
|
|
Polygons polygons;
|
|
Polygons result;
|
|
|
|
if (to_polygons(polygons, VARG(polygons)))
|
|
return;
|
|
|
|
SimplifyPolygons(polygons, result, pftNonZero);
|
|
polygons = result;
|
|
OffsetPolygons(polygons, result, VARG(delta) * SCALE, (JoinType)VARGOPT(join, jtSquare), VARGOPT(limit, 0.0), !VARGOPT(do_not_fix, false));
|
|
|
|
GB.ReturnObject(from_polygons(result, VARG(polygons)));
|
|
|
|
END_METHOD
|
|
|
|
|
|
BEGIN_METHOD(Clipper_Simplify, GB_OBJECT polygons; GB_INTEGER fill)
|
|
|
|
Polygons polygons;
|
|
Polygons result;
|
|
|
|
if (to_polygons(polygons, VARG(polygons)))
|
|
return;
|
|
|
|
SimplifyPolygons(polygons, result, (PolyFillType)VARGOPT(fill, pftNonZero));
|
|
|
|
GB.ReturnObject(from_polygons(result, VARG(polygons)));
|
|
|
|
END_METHOD
|
|
|
|
BEGIN_METHOD(Clipper_Clean, GB_OBJECT polygons; GB_FLOAT distance)
|
|
|
|
Polygons polygons;
|
|
Polygons result;
|
|
|
|
if (to_polygons(polygons, VARG(polygons)))
|
|
return;
|
|
|
|
result.resize(polygons.size());
|
|
|
|
CleanPolygons(polygons, result, VARGOPT(distance, 1.415));
|
|
|
|
GB.ReturnObject(from_polygons(result, VARG(polygons)));
|
|
|
|
END_METHOD
|
|
|
|
//---------------------------------------------------------------------------
|
|
|
|
GB_DESC ClipperDesc[] =
|
|
{
|
|
GB_DECLARE_VIRTUAL("Clipper"),
|
|
|
|
//void OffsetPolygons(const Polygons &in_polys, Polygons &out_polys, double delta, JoinType jointype = jtSquare, double limit = 0.0, bool autoFix = true);
|
|
//void SimplifyPolygons(const Polygons &in_polys, Polygons &out_polys, PolyFillType fillType = pftEvenOdd);
|
|
//void CleanPolygons(Polygons &in_polys, Polygon &out_polys, double distance = 1.415);
|
|
|
|
GB_CONSTANT("JoinMiter", "i", jtMiter),
|
|
GB_CONSTANT("JoinSquare", "i", jtSquare),
|
|
GB_CONSTANT("JoinRound", "i", jtRound),
|
|
|
|
GB_CONSTANT("FillEvenOdd", "i", pftEvenOdd),
|
|
GB_CONSTANT("FillWinding", "i", pftNonZero),
|
|
GB_CONSTANT("FillNonZero", "i", pftNonZero),
|
|
GB_CONSTANT("FillPositive", "i", pftPositive),
|
|
GB_CONSTANT("FillNegative", "i", pftNegative),
|
|
|
|
GB_STATIC_METHOD("Offset", "PointF[][]", Clipper_Offset, "(Polygons)PointF[][];(Delta)f[(Join)i(Limit)f(DoNotFix)b]"),
|
|
GB_STATIC_METHOD("Simplify", "PointF[][]", Clipper_Simplify, "(Polygons)PointF[][];[(Fill)i]"),
|
|
GB_STATIC_METHOD("Clean", "PointF[][]", Clipper_Clean, "(Polygons)PointF[][];[(Distance)f]"),
|
|
|
|
GB_END_DECLARE
|
|
};
|
|
|
|
|