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:
parent
a09819285a
commit
00920947af
@ -570,6 +570,11 @@ Detailed Description of Options
|
||||
as world-coordinates, but the dimensions will be interpreted relative
|
||||
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
|
||||
map, may have different sizes after scaling, depending on how their
|
||||
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 lower-left corner, 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)
|
||||
|
||||
**Granularity**
|
||||
@ -1501,6 +1507,40 @@ Geometry Using Center and Dimensions
|
||||
option is used with a center-style geometry, then that geometry is
|
||||
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
|
||||
-----------------------
|
||||
|
||||
|
65
mapper.cpp
65
mapper.cpp
@ -46,6 +46,8 @@ using namespace std;
|
||||
#define OPT_SILENCE_SUGGESTIONS 0x92
|
||||
#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)
|
||||
string executableName = "minetestmapper";
|
||||
string executablePath; // ONLY for use on windows
|
||||
@ -124,6 +126,7 @@ void usage()
|
||||
" --drawair\n"
|
||||
" --draw[map]point \"<x>,<y> 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]ellipse \"<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)
|
||||
{
|
||||
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)
|
||||
// <x>[,:]<y>+<w>+<h>
|
||||
// (corner of the area, and dimensions)
|
||||
// <x>,<y>@<angle>+<length>
|
||||
static bool parseGeometry(istream &is, NodeCoord &coord1, NodeCoord &coord2, NodeCoord &dimensions, bool &legacy, bool ¢ered, int n, FuzzyBool expectDimensions, int wildcard = 0)
|
||||
{
|
||||
int pos;
|
||||
@ -526,6 +553,44 @@ static bool parseGeometry(istream &is, NodeCoord &coord1, NodeCoord &coord2, Nod
|
||||
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 {
|
||||
// <x>,<y>+<w>+<h>
|
||||
centered = false;
|
||||
|
Loading…
x
Reference in New Issue
Block a user