Files
Slnkdwf/SlnkDWFImpl/SLNKContourImpl.cpp
Jos Groot Lipman fc01e8cdc5 DefineSymbol levert voortaan zijn bounding contour als resultaat
Op contouren kun je via PountCount en PointItem de punten opvragen (in DWG coordinate)
Daarmee kun je uiteindelijk de bounding contour van een symbool aanpassen (fijnslijpen)

svn path=/Slnkdwf/trunk/; revision=18381
2013-07-07 15:36:05 +00:00

756 lines
24 KiB
C++
Raw Blame History

#include "StdAfx.h"
#include "slnkcontourImpl.h"
#include <math.h>
#ifndef PI
#define PI 3.14159265358979323846
#endif
#define PALETTE_RED 1 // Color in the default colormap is red.
/*static*/ WT_Integer32 CSLNKContourImpl::m_next_node_num = 0; // Eigenlijk initialiseren op laatste van planfile
// Constructor voor symboldef's en symbolen
// Hier weten we vaak de contour polygon nog niet (of kunnen die pas later bepalen/
// invullen met transformatie)
CSLNKContourImpl::CSLNKContourImpl(void)
: m_DWGArea(-1), m_outlineColor(WT_RGBA32(128,128,128,255))
{
m_Color = WT_RGBA32(0,0,0,0); // alpha==0, onzichtbaar
m_Lineweight = 10.0; // 10mm default
m_Fontheight = 200.0;
m_Labelpos = LABEL_DEFAULT;
m_isDynamic = false;
}
// Constructor voor gescande contouren
CSLNKContourImpl::CSLNKContourImpl(
int count, /**< The number of points in the array. */
WT_Logical_Point const * points, /**< Pointer to the array of points. */
WT_Boolean copy, /**< Whether the points should be copied or if their addresses should be used directly from the array. */
WT_Units units
)
: WT_Polygon(count, points, copy), m_outlineColor(128,128,128,255),
m_fromSymbol(false), m_onTop(false)
{
m_DWGArea = -1;
m_Color = WT_RGBA32(0,0,0,0); // alpha==0, 100% transparant
m_Lineweight = 10.0; // 10 mm default
m_Fontheight = 200.0;
m_Labelpos = LABEL_DEFAULT;
m_Units = units;
m_isDynamic = false;
}
CSLNKContourImpl::~CSLNKContourImpl(void)
{
}
// Algoritm: search google for Randolph Franklin polygon
BOOL CSLNKContourImpl::PointInPolygon(const WT_Logical_Point pt, const WT_Point_Set &ps)
{
double ptx = pt.m_x;
double pty = pt.m_y;
int i, j, c = 0;
for (i = 0, j = ps.count()-1; i < ps.count(); j = i++) {
WT_Logical_Point pti = ps.points()[i];
if (pti.m_x==ptx&&pti.m_y==pty) // Op een hoekpunt is altijd goed!
{
return TRUE;
}
WT_Logical_Point ptj = ps.points()[j];
if ((((pti.m_y <= pty) && (pty < ptj.m_y)) ||
((ptj.m_y <= pty) && (pty < pti.m_y))) &&
(ptx < (ptj.m_x - pti.m_x) * (pty - pti.m_y) / (ptj.m_y - pti.m_y) + pti.m_x))
c = !c;
}
return c;
}
BOOL CSLNKContourImpl::PointInPolygon(const CPoint pt, const CPoint *ps, int size)
{
double ptx = pt.x;
double pty = pt.y;
int i, j, c = 0;
for (i = 0, j = size-1; i < size; j = i++) {
CPoint pti = ps[i];
if (pti.x==ptx&&pti.y==pty) // Op een hoekpunt is altijd goed!
{
return TRUE;
}
CPoint ptj = ps[j];
if ((((pti.y <= pty) && (pty < ptj.y)) ||
((ptj.y <= pty) && (pty < pti.y))) &&
(ptx < (ptj.x - pti.x) * (pty - pti.y) / (ptj.y - pti.y) + pti.x))
c = !c;
}
return c;
}
// http://www.codeguru.com/forum/printthread.php?t=194400
void DistanceFromLine(double cx, double cy, double ax, double ay ,
double bx, double by, double &distanceSegment,
double &distanceLine)
{
//
// find the distance from the point (cx,cy) to the line
// determined by the points (ax,ay) and (bx,by)
//
// distanceSegment = distance from the point to the line segment
// distanceLine = distance from the point to the line (assuming
// infinite extent in both directions
//
/*
Subject 1.02: How do I find the distance from a point to a line?
Let the point be C (Cx,Cy) and the line be AB (Ax,Ay) to (Bx,By).
Let P be the point of perpendicular projection of C on AB. The parameter
r, which indicates P's position along AB, is computed by the dot product
of AC and AB divided by the square of the length of AB:
(1) AC dot AB
r = ---------
||AB||^2
r has the following meaning:
r=0 P = A
r=1 P = B
r<0 P is on the backward extension of AB
r>1 P is on the forward extension of AB
0<r<1 P is interior to AB
The length of a line segment in d dimensions, AB is computed by:
L = sqrt( (Bx-Ax)^2 + (By-Ay)^2 + ... + (Bd-Ad)^2)
so in 2D:
L = sqrt( (Bx-Ax)^2 + (By-Ay)^2 )
and the dot product of two vectors in d dimensions, U dot V is computed:
D = (Ux * Vx) + (Uy * Vy) + ... + (Ud * Vd)
so in 2D:
D = (Ux * Vx) + (Uy * Vy)
So (1) expands to:
(Cx-Ax)(Bx-Ax) + (Cy-Ay)(By-Ay)
r = -------------------------------
L^2
The point P can then be found:
Px = Ax + r(Bx-Ax)
Py = Ay + r(By-Ay)
And the distance from A to P = r*L.
Use another parameter s to indicate the location along PC, with the
following meaning:
s<0 C is left of AB
s>0 C is right of AB
s=0 C is on AB
Compute s as follows:
(Ay-Cy)(Bx-Ax)-(Ax-Cx)(By-Ay)
s = -----------------------------
L^2
Then the distance from C to P = |s|*L.
*/
double r_numerator = (cx-ax)*(bx-ax) + (cy-ay)*(by-ay);
double r_denomenator = (bx-ax)*(bx-ax) + (by-ay)*(by-ay);
double r = r_numerator / r_denomenator;
//
double px = ax + r*(bx-ax);
double py = ay + r*(by-ay);
//
double s = ((ay-cy)*(bx-ax)-(ax-cx)*(by-ay) ) / r_denomenator;
distanceLine = fabs(s)*sqrt(r_denomenator);
//
// (xx,yy) is the point on the lineSegment closest to (cx,cy)
//
double xx = px;
double yy = py;
if ( (r >= 0) && (r <= 1) )
{
distanceSegment = distanceLine;
}
else
{
double dist1 = (cx-ax)*(cx-ax) + (cy-ay)*(cy-ay);
double dist2 = (cx-bx)*(cx-bx) + (cy-by)*(cy-by);
if (dist1 < dist2)
{
xx = ax;
yy = ay;
distanceSegment = sqrt(dist1);
}
else
{
xx = bx ;
yy = by;
distanceSegment = sqrt(dist2);
}
}
return;
}
// Vind de hoek van de edge van ps die het dichtst bij pt ligt
// (het maakt ons niet uit of pt er binnen of buiten ligt)
// A = P2Y - P1Y
// B = P1X - P2X
// C = P2X * P1Y - P2Y * P1X
// DistToLine = Abs((A * PX + B * PY + C) / Sqr(A * A + B * B))
/*static*/ void CSLNKContourImpl::EdgeAngle(const WT_Logical_Point pt, const WT_Point_Set &ps, double &EdgeAngle, double &EdgeDistance)
{
double ptx = pt.m_x;
double pty = pt.m_y;
int i, j, c = 0;
double minDistSeg = 0x7FFFFFFF; // Max WT_Integer32
double minDistLine;
double angle = 0.0;
myTRACE("\npt = %d,%d", pt.m_x, pt.m_y);
for (i = 0, j = ps.count()-1; i < ps.count(); j = i++) {
WT_Logical_Point pt1 = ps.points()[i];
WT_Logical_Point pt2 = ps.points()[j];
double DistSeg, DistLine;
DistanceFromLine(pt.m_x, pt.m_y,
pt1.m_x, pt1.m_y,
pt2.m_x, pt2.m_y,
DistSeg, DistLine);
// Bij een 'ingedeukte' ruimte kan DistSeg == minDistSeg zijn. Dan wil
// je juist een zo'n groot mogelijke afstand tot de virtuele projectie
if (DistSeg < minDistSeg || (DistSeg == minDistSeg && DistLine > minDistLine))
{
long dy = pt2.m_y - pt1.m_y;
long dx = pt2.m_x - pt1.m_x;
//ASSERT(!(dx == 0 && dy == 0));
angle = atan2((double)dy, (double)dx) * (180 / PI); // Tussen -180 en +180
if (dy==0) if (dx<0) angle=-180; else angle=0;
myTRACE("\nDist %.1f angle set to: %.3f", DistSeg, angle);
minDistSeg = DistSeg;
minDistLine = DistLine;
}
}
if (DWFArea(ps) < 0)
EdgeAngle = angle;
else
EdgeAngle = 180+angle;
if (EdgeAngle < 0) EdgeAngle += 360;
EdgeDistance = minDistLine; //We rekenen met Seg maar projecteren uiteindelijk op Line
}
// Signed Area needed for centroid!
// Negative is clockwise, Positive counterclockwise
/*static*/double CSLNKContourImpl::DWFArea(const WT_Point_Set &pg)
{
int i;
double area = 0;
for (i=0;i<pg.count();i++) {
const WT_Logical_Point &dwfPtA = pg.points()[i];
const WT_Logical_Point &dwfPtB = pg.points()[(i + 1) % pg.count()];
area += (double)dwfPtA.m_x * dwfPtB.m_y;
area -= (double)dwfPtA.m_y * dwfPtB.m_x;
}
area /= 2;
return area;
}
/* Bepaal label positie
Default is natuurlijk de plaats waar hij oorspronkelijk gevonden
Alternatief 1 is de Centroide (gewogen gemiddelde van de coordinaten)
Let wel: deze kan er buiten vallen. Aanroeper moet maar bepalen
of hij dat acceptabel vind
Alternatief 2 is 'linksbovenin'
Alternatief 3 is 'rechts aan de buitenkant' (handig voor symbolen)
Alternatief 4 is 'onder aan de buitenkant' (handig voor symbolen)
*/
WT_Logical_Point CSLNKContourImpl::LabelPosition(LABELPOS pos /*= LABEL_DEFAULT*/)
{
switch (pos)
{
case LABEL_DEFAULT:
return WT_Logical_Point(m_ptLabel.m_x, m_ptLabel.m_y);
case LABEL_CENTROID:
return Centroid(*this);
case LABEL_TOPLEFT:
{ // Zoek het meest 'linksboven' hoekpunt
WT_Logical_Point pt = points()[0]; // Eerste gok
for (int i = 1; i < count(); i++) {
if (points()[i].m_y - pt.m_y > points()[i].m_x - pt.m_x)
pt = points()[i];
}
return pt;
}
case LABEL_OUTSIDERIGHT:
{
WT_Logical_Box bx = bounds();
return WT_Logical_Point(bx.maxpt().m_x, bx.minpt().m_y/2+bx.maxpt().m_y/2); // Pas op voor overflow
}
case LABEL_OUTSIDEBOTTOM:
{
WT_Logical_Box bx = bounds();
return WT_Logical_Point(bx.minpt().m_x/2+bx.maxpt().m_x/2, bx.minpt().m_y); // Pas op voor overflow
}
default:
return WT_Logical_Point(m_ptLabel.m_x, m_ptLabel.m_y);
}
}
/*static*/WT_Logical_Point CSLNKContourImpl::Centroid(const WT_Point_Set &pg)
{
double ptx = 0;
double pty = 0;
int i, j;
for (i = 0; i < pg.count(); i++) {
j = (i + 1) % pg.count();
double Xi=pg.points()[i].m_x, // Alles naar double anders krijgen wel overflows
Yi=pg.points()[i].m_y,
Xj=pg.points()[j].m_x,
Yj=pg.points()[j].m_y;
double dArea = Xi*Yj - Xj*Yi;
ptx += (Xi+Xj) * dArea;
pty += (Yi+Yj) * dArea;
}
double dDWFArea6 = 6*DWFArea(pg);
return WT_Logical_Point((WT_Integer32)(ptx / dDWFArea6), (WT_Integer32)(pty / dDWFArea6));
}
void CSLNKContourImpl::SerializeLabel(WT_File &my_file,
double scale,
HDC myDC)
{
if (m_Color.rgba().m_rgb.a==255)
{ // Volle achtergrond kleur
COLORREF DCclr = RGB(m_Color.rgba().m_rgb.r,
m_Color.rgba().m_rgb.g,
m_Color.rgba().m_rgb.b);
// Net niet 100% kleuren om te zorgen dat bij achtergrond
// zwart/wit toggle deze kleuren niet mee togglen
if (isDarkRGB(DCclr))
my_file.desired_rendition().color() = WT_Color(254,254,254,0);
else
my_file.desired_rendition().color() = WT_Color(1,1,1,0);
}
else
my_file.desired_rendition().color() = WT_Color(255,255,255,0); //Teksten wit
CString tok(m_ShowLabel); // strtok seems to modify
tok.Replace("~", "\n"); // We ondersteunen ook ~ als newline
tok.Replace("[br]", "\n"); // We ondersteunen ook [br] als newline
tok.Replace("[BR]", "\n"); // We ondersteunen ook [BR] als newline
WT_Logical_Point ptTxt = LabelPosition(m_Labelpos);
int l_fontheight = myRound(m_Fontheight * scale);
// De wiskundige label-positie is bepaald. Nu iets corrigeren om
// (afhankelijk van het font) mooier te zijn
// Ook eventueel hori/vert centreren
int width = -1; // Voor UBB code [c] van centreren
switch (m_Labelpos)
{
case CSLNKContourImpl::LABEL_DEFAULT:
break;
case CSLNKContourImpl::LABEL_TOPLEFT: // Iets naar rechtstonder moven
ptTxt.m_x += l_fontheight/4;
ptTxt.m_y -= l_fontheight;
break;
case CSLNKContourImpl::LABEL_OUTSIDERIGHT: // Iets naar rechts en verticaal centreren
{
// Eerst een keer simuleren om grootte te bepalen
ATLASSERT(myDC!=NULL);
WT_Logical_Point ptBR = DrawOneLabel(my_file, ptTxt, tok, l_fontheight, scale, myDC);
width = (ptBR.m_x - ptTxt.m_x);
ptTxt.m_y -= (ptBR.m_y - ptTxt.m_y)/2 + l_fontheight*9/10;
ptTxt.m_x += l_fontheight/4;
break;
}
case CSLNKContourImpl::LABEL_OUTSIDEBOTTOM: // Iets naar beneden en horizontaal centreren
{
// Eerst een keer simuleren om grootte te bepalen
ATLASSERT(myDC!=NULL);
WT_Logical_Point ptBR = DrawOneLabel(my_file, ptTxt, tok, l_fontheight, scale, myDC);
width = (ptBR.m_x - ptTxt.m_x);
ptTxt.m_y -= l_fontheight;
ptTxt.m_x -= (ptBR.m_x - ptTxt.m_x)/2;
break;
}
case CSLNKContourImpl::LABEL_CENTROID:
{ ATLASSERT(myDC!=NULL);
// Als niet binnen contour dan terugvallen op DEFAULT
if (!CSLNKContourImpl::PointInPolygon(ptTxt, *this))
ptTxt = LabelPosition(CSLNKContourImpl::LABEL_DEFAULT);
// Eerst een keer simuleren om grootte te bepalen
WT_Logical_Point ptBR = DrawOneLabel(my_file, ptTxt, tok, l_fontheight, scale, myDC);
width = (ptBR.m_x - ptTxt.m_x);
ptTxt.m_x -= (ptBR.m_x - ptTxt.m_x)/2;
ptTxt.m_y -= (ptBR.m_y - ptTxt.m_y)/2 + l_fontheight*9/10;
// Nooit verder naar links/boven dan TOPLEFT zou doen
// JGL: jul 2007: Waarom niet? Bij heel kleine ruimtes mag bij centreren de boel er best wel iets buiten
// WT_Logical_Point ptTL = LabelPosition(CSLNKContourImpl::LABEL_TOPLEFT);
//ptTxt.m_x = max(ptTxt.m_x, ptTL.m_x + l_fontheight/4);
//ptTxt.m_y = min(ptTxt.m_y, ptTL.m_y - l_fontheight);
#ifdef _DEBUG
WT_Polymarker pm(1, &ptTxt, true);
pm.serialize(my_file);
#endif
}
}
// Nu echt tekenen met width<>-2
DrawOneLabel(my_file, ptTxt, tok, l_fontheight, scale, myDC, width);
}
// Draw one (possibly multline) label
// When width==-2 the drawing is simulated and the result
// is the calculated bottomright of the full text
// Als width==-1 is centreren niet mogelijk/nodig
// Als width>0 is centreren mogelijk via [c]
WT_Logical_Point CSLNKContourImpl::DrawOneLabel(WT_File &my_file,
WT_Logical_Point ptTxt,
CString tok,
int l_fontheight,
double scale,
HDC myDC,
int width/*=-2*/)// Voor centreren. Moet aanroeper al een keer bepaald hebben
{
long max_width=0; // Bepaal hiermee 'rechtsonder' van de tekst als myDC
my_file.desired_rendition().font().height() = l_fontheight;
//TODO: UBB sluitcodes ondersteunen
int curpos = 0;
CString token = tok.Tokenize("\n", curpos);
int line = 0;
bool centering=false;
while( token != "" )
{
// invariant (ook bij binnenkomst): ptTxt.m_y bevat het linksonderpunt van de huidige regel
// uitgaande van l_fontheight. Bij [s] gebruik moeten we dus corrigeren
//CString f(token);
int skipextra = 0; // Extra skip bij underline
long size=100;
int thisLineHeight = l_fontheight; // mooie default
// Supported UBB-like codes:
// [[This is literal text in square brackets]
// [i]This text is italic
// [b]This text is bold
// [u]This text is underline
// [cFF00FF]This text is colored
// [s50]This text is 50% sized van standaard labelfont
// [S800]This text is 800 height sized
// Bovenstaand alleen voor de huidige regel
// [c] Centreer alle(!) volgende regels binnen bounding box (anders links gealigned)
while (token[0] == '[')
{
token.Delete(0);
if (token[0]=='[') break; // [[ALF-TB] to escape parsing
switch (tolower(token[0]))
{
case 'i': // Italic
if (width != -2)
my_file.desired_rendition().font().style().set_italic(true);
token.Delete(0);
break;
case 'b': // Bold
if (width != -2)
my_file.desired_rendition().font().style().set_bold(true);
token.Delete(0);
break;
case 'u': // Underline
if (width != -2)
my_file.desired_rendition().font().style().set_underlined(true);
token.Delete(0);
skipextra = l_fontheight / 5;
break;
case 'c': // Color or Center
{
int end = token.Find(']');
if (end==1)
{
token.Delete(0);
centering = true;
break;
}
if (end >= 0)
{
long clr;
if (sscanf(token, "c%lx]", &clr))
{
WT_Color x(clr>>16,(clr&0xff00)>>8,clr&0xff);
if (width != -2)
my_file.desired_rendition().color() = x;
}
token.Delete(0, end);
}
break;
}
case 's': // Size
{
BOOL bigS = (token[0]=='S');
int end = token.Find(']');
if (end >= 0)
{
token.Delete(0);
if (sscanf(token, "%d]", &size))
{
if (bigS)
thisLineHeight = myRound(size * scale);
else
thisLineHeight = myRound(double(size)*l_fontheight/100);
ptTxt.m_y -= (thisLineHeight - l_fontheight); // Correctie op de invariant voor huidige regel
if (width != -2)
my_file.desired_rendition().font().height() = thisLineHeight;
}
token.Delete(0, end);
}
break;
}
}
if (token[0]==']') token.Delete(0); // Skip closing ]
}
if (width != -2) // Echt tekenen (lees: wegschrijven naar DWF)
{
int horoffset=0;
if (centering)
{
RECT rc = { 0, 0, 0, 0};
DrawText(myDC, token, token.GetLength(), &rc, DT_CALCRECT); // Grootte bepalen
// Tekst horizontaal centreren
horoffset = width/2 - MulDiv(rc.right,thisLineHeight,FONT_SIZER)/2;
}
WT_String txt;
if (WT_String::is_ascii(token.GetLength(), token))
// txt.set(f.GetLength(), f);
txt.set(token.GetLength(), token);
else
{ // Use UNICODE for example for Micha<68>l
CStringW s(token);
txt.set(s.GetLength(), s);
}
WT_Text my_text(WT_Logical_Point(ptTxt.m_x+horoffset, ptTxt.m_y), txt);
my_text.serialize(my_file);
// Altijd terug voor volgende regel
my_file.desired_rendition().font().style().set_italic(false);
my_file.desired_rendition().font().style().set_bold(false);
my_file.desired_rendition().font().style().set_underlined(false);
my_file.desired_rendition().color() = WT_Color(255,255,255,0); //Teksten wit TODO: (contrasteren met background)
my_file.desired_rendition().font().height() = l_fontheight;
}
else
{
// We willen de breedte en hoogte weten van de volledige tekst
RECT rc = { 0, 0, 0, 0};
// Volgens de documentatie werkt DT_CALCRECT niet voor de breedte bij
// multiline teksten maar in de praktijk wel?
// ==>JGL: Onze token is toch maar <20><>n regel
DrawText(myDC, token, token.GetLength(), &rc, DT_CALCRECT); // Grootte bepalen
// Tekst horizontaal en verticaal centreren
// ptRes.m_y += rc.bottom; halen we wel uit ptY
max_width = max(max_width, MulDiv(rc.right,thisLineHeight,l_fontheight));
}
line ++;
/* Get next token: */
token = tok.Tokenize("\n", curpos);
ptTxt.m_y -= l_fontheight + skipextra;
}
return WT_Logical_Point(ptTxt.m_x+MulDiv(max_width,l_fontheight,FONT_SIZER), ptTxt.m_y);
}
/****************************************************************************
Serialize een contour.
Varianten:
- (!fromSymbol)Gesloten polyline op contourlaag
Hiermee komen we twee keer langs, met en zonder solidOnly
- waar uiteindelijk geen label in gevonden (m_contLabel is leeg)
- waar uiteindelijk wel label in gevonden (m_Key zal waarschijnlijk contourlabel zijn maar kan zijn veranderd)
- Geen kleur gezet
- Met solid kleur gezet
- Met transparante kleur gezet
- (m_fromSymbol) Symbool (al dan niet met m_Key gedefinieerd)
- Ingebouwd (star)
- Gedefinieerd (bounding octagon)
Als solidOnly dan alleen als alpha==255 en een label (wel herkend)
****************************************************************************/
WT_Result CSLNKContourImpl::serialize(WT_File & file, BOOL solidOnly, BOOL forFind, double scale)
{
if (!m_fromSymbol && m_contLabel == "" && !solidOnly) // Alleen bij tweede slag
{ // May very well be a textobject itself, just emit it
#ifdef _DEBUG
// niet meer in release-mode
file.desired_rendition().color() =
WT_Color(PALETTE_RED, file.desired_rendition().color_map());
file.desired_rendition().line_weight() = 0;
WT_Polyline my_line( count(), points(), WD_False);
my_line.serialize(file);
#endif
}
else
{ // We have got a proper label/contour
if (m_fromSymbol ||
(m_Color.rgba().m_rgb.a==255 && solidOnly) ||
(m_Color.rgba().m_rgb.a<255 && !solidOnly))
{
// Start a node for 'everything'. Dit is wat we concreet teruggeven bij klikken in de tekening
WT_Object_Node my_node(file,m_next_node_num++,m_Key);
file.desired_rendition().object_node() = my_node;
//char s[256];
//sprintf(s, "Ruimte %s (%.2fm2)", m_Label.ascii(), m_DWGArea/1e6);
// Van de URL gebruiken we met name de friendlyName voor de poly2Map
if (m_Url.index() !=0 )
{
file.desired_rendition().url().add_url_optimized(m_Url, file);
}
//
// Add the filled polygon for the room
//
// Ook als geheel doorzichtig
// - poly2Map heeft namelijk een poly nodig
// - voor als we ruimte willen aanwijzen want de point-in werkt later op polygons
file.desired_rendition().color() = m_Color; // Set the color for the polygon
WT_Polygon my_poly( count(), points(), WD_False);
my_poly.serialize(file);
#if 0
WT_RGBA32 rgba[3];
WT_RGBA32 clr(this.m_Color.rgba());
rgba[0] = clr;
rgba[1] = WT_RGBA32 (clr.m_rgb.r+64>255?255:clr.m_rgb.r+64,
clr.m_rgb.g+64>255?255:clr.m_rgb.g+64,
clr.m_rgb.b+64>255?255:clr.m_rgb.b+64, clr.m_rgb.a);
rgba[1] = WT_RGBA32 (clr.m_rgb.r-64<0?0:clr.m_rgb.r-64,
clr.m_rgb.g-64<0?0:clr.m_rgb.g-64,
clr.m_rgb.b-64<0?0:clr.m_rgb.b-64, clr.m_rgb.a);
rgba[2] = rgba[1];
WT_Logical_Point vP[3];
vP[0] = this.LabelPosition(CSLNKContourImpl::LABEL_CENTROID);
if (!CSLNKContourImpl::PointInPolygon(vP[0], *contour))
vP[0] = this.LabelPosition(CSLNKContourImpl::LABEL_DEFAULT);
for (int i = 0; i < count()-1; i++)
{
vP[1] = points()[i];
vP[2] = points()[i+1];
WT_Gouraud_Polytriangle gpt (3, vP, rgba, WD_True);
gpt.serialize (my_file);
}
#endif
if (m_Pattern.pattern_id() != WT_Fill_Pattern::Solid)
{ // Nog een keer gearceerd
WT_Fill_Pattern pOld = file.desired_rendition().fill_pattern();
file.desired_rendition().fill_pattern() = m_Pattern;
WT_RGBA32 clr(m_Color.rgba());
//WT_Color xor((128+clr.m_rgb.r)%256, (128+clr.m_rgb.g)%256,(128+clr.m_rgb.b)%256);
WT_Color xor(255, (128+clr.m_rgb.g)%256,(128+clr.m_rgb.b)%256);
file.desired_rendition().color() = xor; // Inverse
WT_Polygon my_poly2( count(), points(), WD_False);
my_poly2.serialize(file);
file.desired_rendition().fill_pattern() = pOld;
}
file.desired_rendition().url().clear();
}
//
// Nu nogmaals om de zichtbare rand van de ruimte te tekenen
//
if (!solidOnly // Randje altijd alleen in de tweede slag zodat bij voorkeur bovenop
&& m_outlineColor.rgba().m_rgb.a>0) // Voor symbolen niet nodig
{
file.desired_rendition().color() = m_outlineColor; // Set the color for the polyline
file.desired_rendition().line_weight() = myRound(m_Lineweight * scale);
// Fraaier bij lijndikte aan begin/eind
file.desired_rendition().line_style().line_end_cap() = WT_Line_Style::Round_Cap;
// Als eerste punt ongelijk aan laatste punt dan points() eentje uitbreiden
// De polygon sluit vanzelf wel maar deze polyline niet
if (count() > 2 && (points()[0].m_x != points()[count()-1].m_x || points()[0].m_y != points()[count()-1].m_y))
{
m_isDynamic = true; // Voorkom reset
AddPoint(points()[0]);
}
WT_Polyline my_line( count(), points(), WD_False);
my_line.serialize(file);
}
}
return WT_Result::Success;
};
void CSLNKContourImpl::AddPoint(double pValX, double pValY)
{
AddPoint(m_Units.transform(WT_Point3D(pValX, pValY)));
}
void CSLNKContourImpl::AddPoint(WT_Logical_Point pt)
{
WT_Logical_Point *pts = new WT_Logical_Point[m_isDynamic?count()+1:1];
if (!pts)
throw WT_Result::Out_Of_Memory_Error;
int i = 0;
if (m_isDynamic) // Dan hebben we al zinvolle punten
{
for (i = 0; i < count(); i++)
{
pts[i] = points()[i];
}
}
// Het nieuwe punt
pts[i] = pt;
set(m_isDynamic?(count() + 1):1, pts, true);
// Na elk punt voor de zekerheid area opnieuw?
if (!m_isDynamic)
m_ptLabel = points()[0];
delete[] pts;
m_isDynamic = true; // Zodat geen reset bij volgende punten toevoegen
}