Revision 31705
branches/v2_0_0_prep/extensions/org.gvsig.symbology/src/main/java/org/gvsig/symbology/fmap/mapcontext/rendering/symbol/style/Line2DOffset.java | ||
---|---|---|
49 | 49 |
import java.util.List; |
50 | 50 |
import java.util.Map; |
51 | 51 |
|
52 |
import org.gvsig.fmap.geom.Geometry; |
|
52 | 53 |
import org.gvsig.fmap.geom.primitive.GeneralPathX; |
53 | 54 |
import org.slf4j.Logger; |
54 | 55 |
import org.slf4j.LoggerFactory; |
... | ... | |
85 | 86 |
|
86 | 87 |
switch (type) { |
87 | 88 |
case PathIterator.SEG_MOVETO: |
88 |
from = new Coordinate(dataCoords[0], dataCoords[1]); |
|
89 |
first = from; |
|
90 |
break; |
|
89 |
if(from == null){ |
|
90 |
from = new Coordinate(dataCoords[0], dataCoords[1]); |
|
91 |
first = from; |
|
92 |
break; |
|
93 |
} else { |
|
94 |
/* Puede significar un agujero en un pol?gono o un salto en una linea. |
|
95 |
* Entonces, consumimos los segmentos que llevamos |
|
96 |
* y empezamos un nuevo pol?gono o una nueva linea. |
|
97 |
*/ |
|
98 |
try { |
|
99 |
if(((Geometry)p).getType() == Geometry.TYPES.SURFACE){ |
|
100 |
offsetSegments.append(offsetAndConsumeClosedSegments(offset, segments).getPathIterator(null), |
|
101 |
false); |
|
102 |
} else { |
|
103 |
offsetSegments.append(offsetAndConsumeSegments(offset, segments).getPathIterator(null), |
|
104 |
false); |
|
105 |
} |
|
106 |
} catch (NotEnoughSegmentsToClosePathException e) { |
|
107 |
logger.error( |
|
108 |
e.getMessage(), e); |
|
109 |
} |
|
110 |
segments.clear(); |
|
111 |
from = new Coordinate(dataCoords[0], dataCoords[1]); |
|
112 |
first = from; |
|
113 |
break; |
|
114 |
} |
|
91 | 115 |
|
92 | 116 |
case PathIterator.SEG_LINETO: |
93 | 117 |
|
... | ... | |
102 | 126 |
case PathIterator.SEG_CLOSE: |
103 | 127 |
line = new LineSegment(from, first); |
104 | 128 |
segments.add(line); |
105 |
from = first; |
|
129 |
// from = first;
|
|
106 | 130 |
try { |
107 | 131 |
offsetSegments.append(offsetAndConsumeClosedSegments( |
108 | 132 |
offset, segments).getPathIterator(null), false); |
... | ... | |
110 | 134 |
logger.error( |
111 | 135 |
e.getMessage(), e); |
112 | 136 |
} |
137 |
segments.clear(); |
|
138 |
first =null; |
|
139 |
from = null; |
|
140 |
|
|
113 | 141 |
break; |
114 | 142 |
|
115 | 143 |
} // end switch |
... | ... | |
117 | 145 |
pi.next(); |
118 | 146 |
} |
119 | 147 |
offsetSegments.append(offsetAndConsumeSegments(offset, segments) |
120 |
.getPathIterator(null), true);
|
|
148 |
.getPathIterator(null), false);
|
|
121 | 149 |
|
122 | 150 |
return offsetSegments; |
123 | 151 |
} catch (ParallelLinesCannotBeResolvedException e) { |
... | ... | |
130 | 158 |
List<LineSegment> segments) |
131 | 159 |
throws ParallelLinesCannotBeResolvedException { |
132 | 160 |
Map<LineSegment, LineEquation> offsetLines = |
133 |
new HashMap<LineSegment, LineEquation>();
|
|
161 |
new HashMap<LineSegment, LineEquation>(); |
|
134 | 162 |
int segmentCount = segments.size(); |
135 | 163 |
// first calculate offset lines with the starting point |
136 | 164 |
for (int i = 0; i < segmentCount; i++) { |
137 | 165 |
LineSegment segment = (LineSegment)segments.get(i); |
138 | 166 |
double theta = segment.angle(); |
139 | 167 |
//FIXME: ?Esto para qu? es? |
140 |
// if (Math.abs(theta) % (Math.PI*0.5) < 0.00001){ |
|
141 |
// theta=theta+0.00000000000001; |
|
142 |
// } |
|
168 |
// if (Math.abs(theta) % (Math.PI*0.5) < 0.00001){
|
|
169 |
// theta=theta+0.00000000000001;
|
|
170 |
// }
|
|
143 | 171 |
|
144 | 172 |
double xOffset = offset * Math.sin(theta); |
145 | 173 |
double yOffset = offset * Math.cos(theta); |
... | ... | |
180 | 208 |
} catch (ParallelLinesCannotBeResolvedException e) { //Las lineas son paralelas y NO son la misma. |
181 | 209 |
pEnd = new Point2D.Double(eq.xEnd, eq.yEnd); |
182 | 210 |
gpx.append(new Line2D.Double(pIni, pEnd) |
183 |
.getPathIterator(null), true); // a?adimos una linea
|
|
184 |
// hasta el final
|
|
185 |
// del primer
|
|
186 |
// segmento
|
|
187 |
// y asignamos como punto final el principio del siguiente segmento |
|
188 |
// para que en la siguiente iteraci?n lo tome como punto inicial. |
|
211 |
.getPathIterator(null), true); // a?adimos una linea |
|
212 |
// hasta el final |
|
213 |
// del primer |
|
214 |
// segmento |
|
215 |
// y asignamos como punto final el principio del siguiente segmento
|
|
216 |
// para que en la siguiente iteraci?n lo tome como punto inicial.
|
|
189 | 217 |
pIni = pEnd; |
190 | 218 |
pEnd = new Point2D.Double(eq1.x, eq1.y); |
191 | 219 |
segments.remove(0); |
... | ... | |
203 | 231 |
|
204 | 232 |
private static GeneralPathX offsetAndConsumeClosedSegments(double offset, |
205 | 233 |
List<LineSegment> segments) |
206 |
throws ParallelLinesCannotBeResolvedException, |
|
207 |
NotEnoughSegmentsToClosePathException { |
|
234 |
throws ParallelLinesCannotBeResolvedException, NotEnoughSegmentsToClosePathException { |
|
208 | 235 |
int segmentCount = segments.size(); |
209 | 236 |
if (segmentCount > 1) { |
210 |
GeneralPathX openPath = offsetAndConsumeSegments(offset, segments); |
|
211 |
openPath.closePath(); |
|
212 |
return openPath; |
|
237 |
Map<LineSegment, LineEquation> offsetLines = new HashMap<LineSegment, LineEquation>(); |
|
238 |
// first calculate offset lines with the starting point |
|
239 |
for (int i = 0; i < segmentCount; i++) { |
|
240 |
LineSegment segment = (LineSegment)segments.get(i); |
|
241 |
double theta = segment.angle(); |
|
242 |
//FIXME: ?Esto para qu? es? |
|
243 |
// if (Math.abs(theta) % (Math.PI*0.5) < 0.00001){ |
|
244 |
// theta=theta+0.00000000000001; |
|
245 |
// } |
|
246 |
|
|
247 |
double xOffset = offset * Math.sin(theta); |
|
248 |
double yOffset = offset * Math.cos(theta); |
|
249 |
|
|
250 |
Coordinate p0 = segment.p0; |
|
251 |
double x0 = p0.x + xOffset; |
|
252 |
double y0 = p0.y - yOffset; |
|
253 |
|
|
254 |
Coordinate p1 = segment.p1; |
|
255 |
double x1 = p1.x + xOffset; |
|
256 |
double y1 = p1.y - yOffset; |
|
257 |
|
|
258 |
LineEquation offsetLine = new LineEquation(theta, x0, y0, x1, y1); |
|
259 |
offsetLines.put(segment, offsetLine); |
|
260 |
} |
|
261 |
|
|
262 |
/* |
|
263 |
* let's now calculate the end point of each segment with the point |
|
264 |
* where each line crosses the next one. this point will be the end |
|
265 |
* point of the first line, and the start point of its next one. |
|
266 |
*/ |
|
267 |
Point2D pIni = null; |
|
268 |
Point2D pEnd = null; |
|
269 |
Point2D firstP = null; |
|
270 |
GeneralPathX gpx = new GeneralPathX(); |
|
271 |
for (int i = 0; i < segmentCount; i++) { |
|
272 |
LineSegment segment = (LineSegment)segments.get(0); |
|
273 |
LineEquation eq = offsetLines.get(segment); |
|
274 |
if (i == 0) { //Calculo de la intersecci?n entre el primer segmento y el ?ltimo |
|
275 |
LineEquation eq0 = offsetLines.get((LineSegment)segments.get(segmentCount-1)); |
|
276 |
try{ |
|
277 |
pIni = eq0.resolve(eq); |
|
278 |
} catch (ParallelLinesCannotBeResolvedException e) { //Las lineas son paralelas y NO son la misma. |
|
279 |
// pIni = new Point2D.Double(eq0.xEnd, eq0.yEnd); |
|
280 |
pIni = new Point2D.Double(eq.x, eq.y); |
|
281 |
} |
|
282 |
firstP = pIni; |
|
283 |
} else { |
|
284 |
pIni = pEnd; |
|
285 |
} |
|
286 |
|
|
287 |
if (i < segmentCount - 1) { |
|
288 |
LineEquation eq1 = offsetLines.get((LineSegment)segments.get(1)); |
|
289 |
try{ |
|
290 |
pEnd = eq.resolve(eq1); |
|
291 |
} catch (ParallelLinesCannotBeResolvedException e) { //Las lineas son paralelas y NO son la misma. |
|
292 |
pEnd = new Point2D.Double(eq.xEnd, eq.yEnd); |
|
293 |
gpx.append(new Line2D.Double(pIni, pEnd).getPathIterator(null), true); // a?adimos una linea hasta el final del primer segmento |
|
294 |
// y asignamos como punto final el principio del siguiente segmento |
|
295 |
// para que en la siguiente iteraci?n lo tome como punto inicial. |
|
296 |
pIni = pEnd; |
|
297 |
pEnd = new Point2D.Double(eq1.x, eq1.y); |
|
298 |
segments.remove(0); |
|
299 |
continue; |
|
300 |
} |
|
301 |
} else { |
|
302 |
// pEnd = new Point2D.Double(eq.xEnd, eq.yEnd); |
|
303 |
pEnd = new Point2D.Double(firstP.getX(), firstP.getY()); |
|
304 |
} |
|
305 |
|
|
306 |
gpx.append(new Line2D.Double(pIni, pEnd).getPathIterator(null), true); |
|
307 |
segments.remove(0); |
|
308 |
} |
|
309 |
return gpx; |
|
213 | 310 |
} |
214 | 311 |
throw new NotEnoughSegmentsToClosePathException(segments); |
312 |
|
|
215 | 313 |
} |
314 |
|
|
315 |
// private static GeneralPathX offsetAndConsumeClosedSegments(double offset, |
|
316 |
// List<LineSegment> segments) |
|
317 |
// throws ParallelLinesCannotBeResolvedException, |
|
318 |
// NotEnoughSegmentsToClosePathException { |
|
319 |
// int segmentCount = segments.size(); |
|
320 |
// if (segmentCount > 1) { |
|
321 |
// GeneralPathX openPath = offsetAndConsumeSegments(offset, segments); |
|
322 |
// openPath.closePath(); |
|
323 |
// return openPath; |
|
324 |
// } |
|
325 |
// throw new NotEnoughSegmentsToClosePathException(segments); |
|
326 |
// } |
|
216 | 327 |
} |
217 | 328 |
|
218 | 329 |
class LineEquation { |
... | ... | |
222 | 333 |
|
223 | 334 |
public LineEquation(double theta, double x, double y, double xEnd, |
224 | 335 |
double yEnd) { |
225 |
// this.theta = Math.tan(theta); //Esto es un error, no podemos confundir el angulo de la recta con su pendiente |
|
336 |
// this.theta = Math.tan(theta); //Esto es un error, no podemos confundir el angulo de la recta con su pendiente
|
|
226 | 337 |
this.theta = theta; |
227 | 338 |
this.m = Math.tan(theta); |
228 | 339 |
this.x = x; |
... | ... | |
241 | 352 |
double X; |
242 | 353 |
double Y; |
243 | 354 |
if(Math.abs(this.x - this.xEnd)<0.00001) { //Esta linea es vertical |
244 |
// System.out.println("1 VERTICAL"); |
|
355 |
// System.out.println("1 VERTICAL");
|
|
245 | 356 |
X = this.xEnd; |
246 | 357 |
if (Math.abs(otherLine.x - otherLine.xEnd)<0.00001){//La otra linea es vertical |
247 |
// System.out.println(" 2 PERPENDICULAR"); |
|
358 |
// System.out.println(" 2 PERPENDICULAR");
|
|
248 | 359 |
if(Math.abs(this.x - otherLine.x)<0.00001){ //Son la misma linea, devolvemos el primer punto de la otra linea. |
249 |
// System.out.println(" MISMA LINEA"); |
|
360 |
// System.out.println(" MISMA LINEA");
|
|
250 | 361 |
Y = otherLine.y; |
251 | 362 |
} else { //No son la misma linea, entonces son paralelas, excepcion. |
252 |
// System.out.println(" CASCO POR 1"); |
|
363 |
// System.out.println(" CASCO POR 1");
|
|
253 | 364 |
throw new ParallelLinesCannotBeResolvedException(this, otherLine); |
254 | 365 |
} |
255 | 366 |
} else if (Math.abs(otherLine.y - otherLine.yEnd)<0.00001) { //La otra linea es horizontal |
256 |
// System.out.println(" 2 HORIZONTAL"); |
|
367 |
// System.out.println(" 2 HORIZONTAL");
|
|
257 | 368 |
Y = otherLine.y; |
258 | 369 |
} else { //Si no |
259 |
// System.out.println(" 2 CUALQUIERA"); |
|
370 |
// System.out.println(" 2 CUALQUIERA");
|
|
260 | 371 |
Y = otherLine.m*(X - otherLine.x)+otherLine.y; |
261 | 372 |
} |
262 | 373 |
|
263 | 374 |
} else if (Math.abs(this.y - this.yEnd)<0.00001) { //Esta linea es horizontal |
264 |
// System.out.println("1 HORIZONTAL"); |
|
375 |
// System.out.println("1 HORIZONTAL");
|
|
265 | 376 |
Y = this.yEnd; |
266 | 377 |
if (Math.abs(otherLine.y - otherLine.yEnd)<0.00001) { //La otra linea es horizontal |
267 |
// System.out.println(" 2 HORIZONTAL"); |
|
378 |
// System.out.println(" 2 HORIZONTAL");
|
|
268 | 379 |
if(Math.abs(this.y - otherLine.y)<0.00001){ //Son la misma linea, devolvemos el primer punto de la otra linea. |
269 |
// System.out.println(" MISMA LINEA"); |
|
380 |
// System.out.println(" MISMA LINEA");
|
|
270 | 381 |
X = otherLine.x; |
271 | 382 |
} else { //No son la misma linea, entonces son paralelas, excepcion. |
272 |
// System.out.println(" CASCO POR 2"); |
|
383 |
// System.out.println(" CASCO POR 2");
|
|
273 | 384 |
throw new ParallelLinesCannotBeResolvedException(this, otherLine); |
274 | 385 |
} |
275 | 386 |
} else if (Math.abs(otherLine.x - otherLine.xEnd)<0.00001){//La otra linea es vertical |
276 |
// System.out.println(" 2 VERTICAL"); |
|
387 |
// System.out.println(" 2 VERTICAL");
|
|
277 | 388 |
X = otherLine.x; |
278 | 389 |
} else { //Si no |
279 |
// System.out.println(" 2 CUALQUIERA"); |
|
390 |
// System.out.println(" 2 CUALQUIERA");
|
|
280 | 391 |
X = (Y - otherLine.y)/otherLine.m +otherLine.x; |
281 | 392 |
} |
282 | 393 |
} else { //Esta linea no es ni vertical ni horizontal |
283 |
// System.out.println("1 CUALQUIERA"); |
|
394 |
// System.out.println("1 CUALQUIERA");
|
|
284 | 395 |
if (Math.abs(otherLine.y - otherLine.yEnd)<0.00001) { //La otra linea es horizontal |
285 |
// System.out.println(" 2 HORIZONTAL"); |
|
396 |
// System.out.println(" 2 HORIZONTAL");
|
|
286 | 397 |
Y = otherLine.y; |
287 | 398 |
X = (Y - this.y)/this.m +this.x; |
288 | 399 |
} else if (Math.abs(otherLine.x - otherLine.xEnd)<0.00001){//La otra linea es vertical |
289 |
// System.out.println(" 2 VERTICAL"); |
|
400 |
// System.out.println(" 2 VERTICAL");
|
|
290 | 401 |
X = otherLine.x; |
291 | 402 |
Y = this.m*(X - this.x)+this.y; |
292 | 403 |
} else if ((Math.abs(otherLine.m - this.m)<0.00001)) { //Tienen la misma pendiente |
293 |
// System.out.println(" MISMA PENDIENTE"); |
|
404 |
// System.out.println(" MISMA PENDIENTE");
|
|
294 | 405 |
Y = otherLine.m*(this.x - otherLine.x)+otherLine.y; |
295 | 406 |
if (Math.abs(this.y - Y)<0.00001){ //Las lineas son la misma |
296 |
// System.out.println(" MISMA LINEA"); |
|
407 |
// System.out.println(" MISMA LINEA");
|
|
297 | 408 |
X = otherLine.x; |
298 | 409 |
Y = otherLine.y; |
299 | 410 |
} else { |
300 |
// System.out.println(" CASCO POR 3"); |
|
411 |
// System.out.println(" CASCO POR 3");
|
|
301 | 412 |
throw new ParallelLinesCannotBeResolvedException(this, otherLine); |
302 | 413 |
} |
303 | 414 |
} else { |
304 |
// System.out.println(" AMBAS CUALESQUIERA"); |
|
415 |
// System.out.println(" AMBAS CUALESQUIERA");
|
|
305 | 416 |
double mTimesX = this.m * this.x; |
306 | 417 |
X = (mTimesX - this.y - otherLine.m * otherLine.x + otherLine.y) / (this.m - otherLine.m); |
307 | 418 |
Y = this.m * X - mTimesX + this.y; |
308 | 419 |
} |
309 | 420 |
} |
310 | 421 |
|
311 |
// System.out.println("DEVOLVEMOS X = "+X+" Y = "+Y); |
|
422 |
// System.out.println("DEVOLVEMOS X = "+X+" Y = "+Y);
|
|
312 | 423 |
return new Point2D.Double(X, Y); |
313 | 424 |
|
314 | 425 |
} |
Also available in: Unified diff