v2.10 Symbool rotatie

svn path=/Slnkdwf/trunk/; revision=12485
This commit is contained in:
Jos Groot Lipman
2008-01-21 13:34:06 +00:00
parent 6596ce32c5
commit f07aea9ec7
23 changed files with 491 additions and 89 deletions

View File

@@ -2,6 +2,10 @@
#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
@@ -61,9 +65,187 @@ BOOL CSLNKContourImpl::PointInPolygon(const CPoint pt, const CPoint *ps, int siz
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 dichts 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, Positve counterclockwise
/*static*/double CSLNKContourImpl::DWFArea(const WT_Polygon &pg)
/*static*/double CSLNKContourImpl::DWFArea(const WT_Point_Set &pg)
{
int i;
double area = 0;
@@ -121,7 +303,7 @@ WT_Logical_Point CSLNKContourImpl::LabelPosition(LABELPOS pos /*= LABEL_DEFAULT*
}
}
/*static*/WT_Logical_Point CSLNKContourImpl::Centroid(const WT_Polygon &pg)
/*static*/WT_Logical_Point CSLNKContourImpl::Centroid(const WT_Point_Set &pg)
{
double ptx = 0;
double pty = 0;
@@ -393,11 +575,14 @@ WT_Result CSLNKContourImpl::serialize(WT_File & file, BOOL solidOnly)
{
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