Add a geometry syntax using angle and length (2D only)

Draw a line with an angle of 30 degrees and a lenght of 200:
	--drawline <x>,<y>@30+200
This commit is contained in:
Rogier 2015-12-24 23:57:32 +01:00
parent a09819285a
commit 00920947af
2 changed files with 105 additions and 0 deletions

View File

@ -570,6 +570,11 @@ Detailed Description of Options
as world-coordinates, but the dimensions will be interpreted relative as world-coordinates, but the dimensions will be interpreted relative
to the image. I.e. they won't scale with the map. to the image. I.e. they won't scale with the map.
* If the geometry is specified using an angle and length, and if the
length is specified in nodes (e.g. '20n'), the size will scale. If
the length is specified in pixels (e.g. '20p') or if no unit is
specified, then the size will not scale.
In practise this means that two identically-sized figures in a full-scale In practise this means that two identically-sized figures in a full-scale
map, may have different sizes after scaling, depending on how their map, may have different sizes after scaling, depending on how their
geometry was specified. The jury is still out as to whether this is geometry was specified. The jury is still out as to whether this is
@ -1384,6 +1389,7 @@ Geometry Syntax
* As the corners of the area * As the corners of the area
* As the lower-left corner, and the area's dimensions * As the lower-left corner, and the area's dimensions
* As the center of the are, and the area's dimensions * As the center of the are, and the area's dimensions
* As a corner and an angle and distance to the second corner
* Using legacy format (compatible with standard minetestmapper) * Using legacy format (compatible with standard minetestmapper)
**Granularity** **Granularity**
@ -1501,6 +1507,40 @@ Geometry Using Center and Dimensions
option is used with a center-style geometry, then that geometry is option is used with a center-style geometry, then that geometry is
interpreted as a corner geometry instead. interpreted as a corner geometry instead.
Geometry using Corner and Angle with Length
-------------------------------------------
A geometry using one corner (or endpoint of the line) and an
angle with a line length is specified as follows::
--drawline <xcorner>,<ycorner>@<angle>+<length>[np]
This syntax is only supported for 2-dimensional geometries
(e.g. when drawing figures on the map).
where ``xcorner,ycorner`` are the coordinates of one corner,
``angle`` is the angle, or compass direction, in degrees of the
line or second corner, and ``length`` is the length of the
line, or the distance to the second corner.
An angle of 0° is north, 90° is east, 180° is south and 270° is
west. Negative values are accepted as well: -90° is also west,
for instance.
When the map is scaled, the length may or may not need to be
scaled. Where scaling is possible, a suffix 'n' specifies
that the length is in nodes, and so it scales. A suffix 'p'
specifies a length in pixels, which do not scale.
Scaling is not possible for figures that are drawn on the map,
e.g. using '--drawmapline'. Use '--drawline' instead if
a figure must scale with the map.
Example::
--drawline 100,100@20+100p
Legacy Geometry Format Legacy Geometry Format
----------------------- -----------------------

View File

@ -46,6 +46,8 @@ using namespace std;
#define OPT_SILENCE_SUGGESTIONS 0x92 #define OPT_SILENCE_SUGGESTIONS 0x92
#define OPT_PRESCAN_WORLD 0x93 #define OPT_PRESCAN_WORLD 0x93
#define DRAW_ARROW_LENGTH 10
#define DRAW_ARROW_ANGLE 30
// Will be replaced with the actual name and location of the executable (if found) // Will be replaced with the actual name and location of the executable (if found)
string executableName = "minetestmapper"; string executableName = "minetestmapper";
string executablePath; // ONLY for use on windows string executablePath; // ONLY for use on windows
@ -124,6 +126,7 @@ void usage()
" --drawair\n" " --drawair\n"
" --draw[map]point \"<x>,<y> color\"\n" " --draw[map]point \"<x>,<y> color\"\n"
" --draw[map]line \"<geometry> color\"\n" " --draw[map]line \"<geometry> color\"\n"
" --draw[map]line \"<x>,<y> <angle> <length>[np] color\"\n"
" --draw[map]circle \"<geometry> color\"\n" " --draw[map]circle \"<geometry> color\"\n"
" --draw[map]ellipse \"<geometry> color\"\n" " --draw[map]ellipse \"<geometry> color\"\n"
" --draw[map]rectangle \"<geometry> color\"\n" " --draw[map]rectangle \"<geometry> color\"\n"
@ -433,6 +436,29 @@ static void convertDimensionToCornerCoordinates(NodeCoord &coord1, NodeCoord &co
} }
} }
static void convertPolarToCartesianCoordinates(NodeCoord &coord1, NodeCoord &coord2, double angle, double length)
{
angle *= M_PI / 180;
double dxf = sin(angle) * length;
int dx = (dxf < 0 ? -1 : 1) * int(fabs(dxf + (dxf < 0 ? -0.5 : 0.5)));
dx -= dx < 0 ? -1 : dx > 0 ? +1 : 0;
double dyf = cos(angle) * length;
int dy = (dyf < 0 ? -1 : 1) * int(fabs(dyf + (dyf < 0 ? -0.5 : 0.5)));
dy -= dy < 0 ? -1 : dy > 0 ? +1 : 0;
coord2.x() = coord1.x() + dx;
coord2.y() = coord1.y() + dy;
}
static void convertCartesianToPolarCoordinates(NodeCoord &coord1, NodeCoord &coord2, double &angle, double &length)
{
int lx = coord2.x() - coord1.x();
lx += lx < 0 ? -1 : lx > 0 ? 1 : 0;
int ly = coord2.y() - coord1.y();
ly += ly < 0 ? -1 : ly > 0 ? 1 : 0;
length = sqrt(lx*lx + ly*ly);
angle = atan2(lx, ly) / M_PI * 180;
}
static void orderCoordinateDimensions(NodeCoord &coord1, NodeCoord &coord2, int n) static void orderCoordinateDimensions(NodeCoord &coord1, NodeCoord &coord2, int n)
{ {
for (int i = 0; i < n; i++) for (int i = 0; i < n; i++)
@ -454,6 +480,7 @@ static void orderCoordinateDimensions(NodeCoord &coord1, NodeCoord &coord2, int
// (center of the area, and dimensions) // (center of the area, and dimensions)
// <x>[,:]<y>+<w>+<h> // <x>[,:]<y>+<w>+<h>
// (corner of the area, and dimensions) // (corner of the area, and dimensions)
// <x>,<y>@<angle>+<length>
static bool parseGeometry(istream &is, NodeCoord &coord1, NodeCoord &coord2, NodeCoord &dimensions, bool &legacy, bool &centered, int n, FuzzyBool expectDimensions, int wildcard = 0) static bool parseGeometry(istream &is, NodeCoord &coord1, NodeCoord &coord2, NodeCoord &dimensions, bool &legacy, bool &centered, int n, FuzzyBool expectDimensions, int wildcard = 0)
{ {
int pos; int pos;
@ -526,6 +553,44 @@ static bool parseGeometry(istream &is, NodeCoord &coord1, NodeCoord &coord2, Nod
return false; return false;
} }
} }
else if (safePeekStream(is) == '@') {
// <x>,<y>@<angle>+<length>[np]
if (n != 2)
return false;
centered = false;
is.ignore(1);
double angle;
double length;
bool world_relative = false;
is >> angle;
if (safePeekStream(is) != '+' && safePeekStream(is) != '-')
return false;
if (safePeekStream(is) == '+')
is.ignore(1);
is >> length;
if (!validStreamAtEof(is)) {
switch (safePeekStream(is)) {
case 'n' :
is.ignore(1);
world_relative = true;
break;
case 'p' :
is.ignore(1);
world_relative = false;
break;
}
}
if (!validStreamAtWsOrEof(is))
return false;
convertPolarToCartesianCoordinates(coord1, coord2, angle, length);
if (!world_relative) {
convertCornerToDimensionCoordinates(coord1, coord2, dimensions, n);
coord2.x() = NodeCoord::Invalid;
coord2.y() = NodeCoord::Invalid;
}
return true;
}
else { else {
// <x>,<y>+<w>+<h> // <x>,<y>+<w>+<h>
centered = false; centered = false;