-
-
Notifications
You must be signed in to change notification settings - Fork 3k
/
feature.h
294 lines (243 loc) · 9.78 KB
/
feature.h
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
/*
* libpal - Automated Placement of Labels Library
*
* Copyright (C) 2008 Maxence Laurent, MIS-TIC, HEIG-VD
* University of Applied Sciences, Western Switzerland
* http://www.hes-so.ch
*
* Contact:
* maxence.laurent <at> heig-vd <dot> ch
* or
* eric.taillard <at> heig-vd <dot> ch
*
* This file is part of libpal.
*
* libpal 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 3 of the License, or
* (at your option) any later version.
*
* libpal 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 libpal. If not, see <http://www.gnu.org/licenses/>.
*
*/
#ifndef _FEATURE_H
#define _FEATURE_H
#include <iostream>
#include <fstream>
#include <cmath>
#include <geos_c.h>
#include "palgeometry.h"
#include "pointset.h"
#include "util.h"
#include "labelposition.h"
namespace pal
{
/** Optional additional info about label (for curved labels) */
class CORE_EXPORT LabelInfo
{
public:
typedef struct
{
unsigned short chr;
double width;
} CharacterInfo;
LabelInfo( int num, double height, double maxinangle = 20.0, double maxoutangle = -20.0 )
{
max_char_angle_inside = maxinangle;
// outside angle should be negative
max_char_angle_outside = maxoutangle > 0 ? -maxoutangle : maxoutangle;
label_height = height;
char_num = num;
char_info = new CharacterInfo[num];
}
~LabelInfo() { delete [] char_info; }
double max_char_angle_inside;
double max_char_angle_outside;
double label_height;
int char_num;
CharacterInfo* char_info;
};
class LabelPosition;
class FeaturePart;
class CORE_EXPORT Feature
{
friend class FeaturePart;
public:
Feature( Layer* l, const char* geom_id, PalGeometry* userG, double lx, double ly );
~Feature();
void setLabelInfo( LabelInfo* info ) { labelInfo = info; }
void setDistLabel( double dist ) { distlabel = dist; }
//Set label position of the feature to fixed x/y values
void setFixedPosition( double x, double y ) { fixedPos = true; fixedPosX = x; fixedPosY = y;}
void setQuadOffset( double x, double y ) { quadOffset = true; quadOffsetX = x; quadOffsetY = y;}
void setPosOffset( double x, double y ) { offsetPos = true; offsetPosX = x; offsetPosY = y;}
bool fixedPosition() const { return fixedPos; }
//Set label rotation to fixed value
void setFixedAngle( double a ) { fixedRotation = true; fixedAngle = a; }
void setRepeatDistance( double dist ) { repeatDist = dist; }
double repeatDistance() const { return repeatDist; }
void setAlwaysShow( bool bl ) { alwaysShow = bl; }
protected:
Layer *layer;
PalGeometry *userGeom;
double label_x;
double label_y;
double distlabel;
LabelInfo* labelInfo; // optional
char *uid;
bool fixedPos; //true in case of fixed position (only 1 candidate position with cost 0)
double fixedPosX;
double fixedPosY;
bool quadOffset; // true if a quadrant offset exists
double quadOffsetX;
double quadOffsetY;
bool offsetPos; //true if position is to be offset by set amount
double offsetPosX;
double offsetPosY;
//Fixed (e.g. data defined) angle only makes sense together with fixed position
bool fixedRotation;
double fixedAngle; //fixed angle value (in rad)
double repeatDist;
bool alwaysShow; //true is label is to always be shown (but causes overlapping)
// array of parts - possibly not necessary
//int nPart;
//FeaturePart** parts;
};
/**
* \brief Main class to handle feature
*/
class CORE_EXPORT FeaturePart : public PointSet
{
public:
/**
* \brief create a new generic feature
*
* \param feat a pointer for a Feat which contains the spatial entites
* \param geom a pointer to a GEOS geometry
*/
FeaturePart( Feature *feat, const GEOSGeometry* geom );
/**
* \brief Delete the feature
*/
virtual ~FeaturePart();
/**
* \brief generate candidates for point feature
* Generate candidates for point features
* \param x x coordinates of the point
* \param y y coordinates of the point
* \param scale map scale is 1:scale
* \param lPos pointer to an array of candidates, will be filled by generated candidates
* \param delta_width delta width
* \param angle orientation of the label
* \return the number of generated cadidates
*/
int setPositionForPoint( double x, double y, double scale, LabelPosition ***lPos, double delta_width, double angle );
/**
* generate one candidate over specified point
*/
int setPositionOverPoint( double x, double y, double scale, LabelPosition ***lPos, double delta_width, double angle );
/**
* \brief generate candidates for line feature
* Generate candidates for line features
* \param scale map scale is 1:scale
* \param lPos pointer to an array of candidates, will be filled by generated candidates
* \param mapShape a pointer to the line
* \param delta_width delta width
* \return the number of generated cadidates
*/
int setPositionForLine( double scale, LabelPosition ***lPos, PointSet *mapShape, double delta_width );
LabelPosition* curvedPlacementAtOffset( PointSet* path_positions, double* path_distances,
int orientation, int index, double distance );
/**
* Generate curved candidates for line features
*/
int setPositionForLineCurved( LabelPosition ***lPos, PointSet* mapShape );
/**
* \brief generate candidates for point feature
* Generate candidates for point features
* \param scale map scale is 1:scale
* \param lPos pointer to an array of candidates, will be filled by generated candidates
* \param mapShape a pointer to the polygon
* \param delta_width delta width
* \return the number of generated cadidates
*/
int setPositionForPolygon( double scale, LabelPosition ***lPos, PointSet *mapShape, double delta_width );
/**
* \brief return the feature
* \return the feature
*/
Feature* getFeature() { return f; }
/**
* \brief return the geometry
* \return the geometry
*/
const GEOSGeometry* getGeometry() const { return the_geom; }
/**
* \brief return the layer that feature belongs to
* \return the layer of the feature
*/
Layer * getLayer();
/**
* \brief generic method to generate candidates
* This method will call either setPositionFromPoint(), setPositionFromLine or setPositionFromPolygon
* \param scale the map scale is 1:scale
* \param lPos pointer to candidates array in which candidates will be put
* \param bbox_min min values of the map extent
* \param bbox_max max values of the map extent
* \param mapShape generate candidates for this spatial entites
* \param candidates index for candidates
* \return the number of candidates in *lPos
*/
int setPosition( double scale, LabelPosition ***lPos, double bbox_min[2], double bbox_max[2], PointSet *mapShape, RTree<LabelPosition*, double, 2, double>*candidates );
/**
* \brief get the unique id of the feature
* \return the feature unique identifier
*/
const char *getUID();
/**
* \brief Print feature information
* Print feature unique id, geometry type, points, and holes on screen
*/
void print();
PalGeometry* getUserGeometry() { return f->userGeom; }
void setLabelSize( double lx, double ly ) { f->label_x = lx; f->label_y = ly; }
double getLabelWidth() const { return f->label_x; }
double getLabelHeight() const { return f->label_y; }
void setLabelDistance( double dist ) { f->distlabel = dist; }
double getLabelDistance() const { return f->distlabel; }
void setLabelInfo( LabelInfo* info ) { f->labelInfo = info; }
bool getFixedRotation() { return f->fixedRotation; }
double getLabelAngle() { return f->fixedAngle; }
bool getFixedPosition() { return f->fixedPos; }
bool getAlwaysShow() { return f->alwaysShow; }
int getNumSelfObstacles() const { return nbHoles; }
PointSet* getSelfObstacle( int i ) { return holes[i]; }
/** Check whether this part is connected with some other part */
bool isConnected( FeaturePart* p2 );
/** Merge other (connected) part with this one and save the result in this part (other is unchanged).
* Return true on success, false if the feature wasn't modified */
bool mergeWithFeaturePart( FeaturePart* other );
void addSizePenalty( int nbp, LabelPosition** lPos, double bbx[4], double bby[4] );
protected:
Feature* f;
int nbHoles;
PointSet **holes;
GEOSGeometry *the_geom;
bool ownsGeom;
/** \brief read coordinates from a GEOS geom */
void extractCoords( const GEOSGeometry* geom );
/** Find duplicate (or nearly duplicate points) and remove them.
* Probably to avoid numerical errors in geometry algorithms.
*/
void removeDuplicatePoints();
private:
LabelPosition::Quadrant quadrantFromOffset() const;
};
} // end namespace pal
#endif