svn-gvsig-desktop / trunk / org.gvsig.desktop / org.gvsig.desktop.plugin / org.gvsig.labeling.app / org.gvsig.labeling.app.mainplugin / src / main / java / org / gvsig / labeling / placements / PolygonPlacementParallel.java @ 43510
History | View | Annotate | Download (5.6 KB)
1 | 43510 | jjdelcerro | /**
|
---|---|---|---|
2 | * gvSIG. Desktop Geographic Information System.
|
||
3 | 40911 | jldominguez | *
|
4 | 43510 | jjdelcerro | * Copyright (C) 2007-2013 gvSIG Association.
|
5 | 40911 | jldominguez | *
|
6 | * This program is free software; you can redistribute it and/or
|
||
7 | * modify it under the terms of the GNU General Public License
|
||
8 | 43510 | jjdelcerro | * as published by the Free Software Foundation; either version 3
|
9 | 40911 | jldominguez | * of the License, or (at your option) any later version.
|
10 | *
|
||
11 | * This program is distributed in the hope that it will be useful,
|
||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||
14 | * GNU General Public License for more details.
|
||
15 | *
|
||
16 | * You should have received a copy of the GNU General Public License
|
||
17 | * along with this program; if not, write to the Free Software
|
||
18 | 43510 | jjdelcerro | * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
|
19 | * MA 02110-1301, USA.
|
||
20 | 40911 | jldominguez | *
|
21 | 43510 | jjdelcerro | * For any additional information, do not hesitate to contact us
|
22 | * at info AT gvsig.com, or visit our website www.gvsig.com.
|
||
23 | 40911 | jldominguez | */
|
24 | package org.gvsig.labeling.placements; |
||
25 | |||
26 | import java.awt.Rectangle; |
||
27 | import java.awt.geom.PathIterator; |
||
28 | import java.awt.geom.Point2D; |
||
29 | import java.util.ArrayList; |
||
30 | import java.util.Vector; |
||
31 | |||
32 | import org.gvsig.fmap.geom.Geometry; |
||
33 | import org.gvsig.fmap.geom.Geometry.SUBTYPES; |
||
34 | import org.gvsig.fmap.geom.Geometry.TYPES; |
||
35 | import org.gvsig.fmap.geom.GeometryLocator; |
||
36 | 43510 | jjdelcerro | import org.gvsig.fmap.geom.GeometryManager; |
37 | 40911 | jldominguez | import org.gvsig.fmap.geom.primitive.Point; |
38 | import org.gvsig.fmap.mapcontext.ViewPort; |
||
39 | import org.gvsig.fmap.mapcontext.rendering.legend.styling.ILabelClass; |
||
40 | import org.gvsig.fmap.mapcontext.rendering.legend.styling.IPlacementConstraints; |
||
41 | import org.gvsig.symbology.fmap.mapcontext.rendering.legend.styling.LabelLocationMetrics; |
||
42 | import org.gvsig.tools.task.Cancellable; |
||
43 | import org.slf4j.Logger; |
||
44 | import org.slf4j.LoggerFactory; |
||
45 | |||
46 | public class PolygonPlacementParallel implements ILabelPlacement{ |
||
47 | |||
48 | private static final Logger logger = LoggerFactory.getLogger( |
||
49 | PolygonPlacementParallel.class); |
||
50 | |||
51 | 43510 | jjdelcerro | @Override
|
52 | 40911 | jldominguez | public ArrayList<LabelLocationMetrics> guess( |
53 | ILabelClass lc, Geometry geom, |
||
54 | IPlacementConstraints placementConstraints, |
||
55 | double cartographicSymbolSize, Cancellable cancel, ViewPort vp) {
|
||
56 | |||
57 | 43510 | jjdelcerro | if (cancel.isCanceled()) {
|
58 | return CannotPlaceLabel.NO_PLACES;
|
||
59 | } |
||
60 | 40911 | jldominguez | |
61 | double theta = 0; |
||
62 | Point start_po = null; |
||
63 | |||
64 | try {
|
||
65 | if(placementConstraints.isFitInsidePolygon()){
|
||
66 | start_po = geom.getInteriorPoint(); |
||
67 | } else {
|
||
68 | start_po = geom.centroid(); |
||
69 | } |
||
70 | } catch (Exception exc) { |
||
71 | 43510 | jjdelcerro | logger.warn("While getting centroid/interior point.", exc);
|
72 | 40911 | jldominguez | } |
73 | |||
74 | Point2D startingPoint = new Point2D.Double(start_po.getX(), start_po.getY()); |
||
75 | |||
76 | // calculated with the Linear Regression technique
|
||
77 | PathIterator pi = geom.getPathIterator(null); |
||
78 | Rectangle geomBounds = geom.getBounds();
|
||
79 | double sumx = 0, sumy = 0, sumxx = 0, sumyy = 0, sumxy = 0; |
||
80 | double Sxx, Sxy, b, a;
|
||
81 | double[] coords = new double[6]; |
||
82 | int count = 0; |
||
83 | |||
84 | // add points to the regression process
|
||
85 | Vector<Point2D> v = new Vector<Point2D>(); |
||
86 | while (!pi.isDone()) {
|
||
87 | pi.currentSegment(coords); |
||
88 | Point2D p;
|
||
89 | if (geomBounds.width > geomBounds.height)
|
||
90 | p = new Point2D.Double(coords[0], coords[1]); |
||
91 | else
|
||
92 | p = new Point2D.Double(coords[1], coords[0]); |
||
93 | v.addElement(p); |
||
94 | count++; |
||
95 | sumx += p.getX(); |
||
96 | sumy += p.getY(); |
||
97 | sumxx += p.getX()*p.getX(); |
||
98 | sumyy += p.getY()*p.getY(); |
||
99 | sumxy += p.getX()*p.getY(); |
||
100 | pi.next(); |
||
101 | } |
||
102 | |||
103 | // start regression
|
||
104 | double n = (double) count; |
||
105 | Sxx = sumxx-sumx*sumx/n; |
||
106 | Sxy = sumxy-sumx*sumy/n; |
||
107 | b = Sxy/Sxx; |
||
108 | a = (sumy-b*sumx)/n; |
||
109 | |||
110 | boolean isVertical = false; |
||
111 | if (geomBounds.width < geomBounds.height) {
|
||
112 | if (b == 0) { |
||
113 | // force vertical (to avoid divide by zero)
|
||
114 | isVertical = true;
|
||
115 | |||
116 | } else {
|
||
117 | // swap axes
|
||
118 | double bAux = 1/b; |
||
119 | a = - a / b; |
||
120 | b = bAux; |
||
121 | } |
||
122 | } |
||
123 | |||
124 | if (isVertical){
|
||
125 | theta = AbstractLinePlacement.HALF_PI; |
||
126 | } else {
|
||
127 | double p1x = 0; |
||
128 | double p1y =geomBounds.height-a;
|
||
129 | double p2x = geomBounds.width;
|
||
130 | double p2y = geomBounds.height-
|
||
131 | (a+geomBounds.width*b); |
||
132 | |||
133 | theta = -Math.atan(((p2y - p1y) / (p2x - p1x)) );
|
||
134 | } |
||
135 | |||
136 | ArrayList<LabelLocationMetrics> guessed = new ArrayList<LabelLocationMetrics>(); |
||
137 | Rectangle labelBounds = lc.getBounds();
|
||
138 | double cosTheta = Math.cos(theta); |
||
139 | double sinTheta = Math.sin(theta); |
||
140 | double halfHeight = labelBounds.getHeight()*0.5; |
||
141 | double halfWidth= labelBounds.getWidth()*0.5; |
||
142 | double offsetX = halfHeight * sinTheta + halfWidth*cosTheta;
|
||
143 | double offsetY = -halfHeight * cosTheta + halfWidth*sinTheta;
|
||
144 | double offsetRX=vp.toMapDistance((int)offsetX); |
||
145 | double offsetRY=vp.toMapDistance((int)offsetY); |
||
146 | startingPoint.setLocation(startingPoint.getX() - offsetRX, |
||
147 | startingPoint.getY() - offsetRY); |
||
148 | |||
149 | Point auxp = null; |
||
150 | |||
151 | try {
|
||
152 | auxp = GeometryLocator.getGeometryManager().createPoint( |
||
153 | startingPoint.getX(),startingPoint.getY(), SUBTYPES.GEOM2D); |
||
154 | } catch (Exception e) { |
||
155 | 43510 | jjdelcerro | logger.warn("While creating point.", e);
|
156 | 40911 | jldominguez | } |
157 | |||
158 | auxp.transform(vp.getAffineTransform()); |
||
159 | guessed.add(new LabelLocationMetrics(
|
||
160 | new Point2D.Double(auxp.getX(),auxp.getY()), -theta, true)); |
||
161 | return guessed;
|
||
162 | } |
||
163 | 43510 | jjdelcerro | |
164 | @Override
|
||
165 | 40911 | jldominguez | public boolean isSuitableFor(IPlacementConstraints placementConstraints, |
166 | int shapeType) {
|
||
167 | |||
168 | 43510 | jjdelcerro | GeometryManager geomManager = GeometryLocator.getGeometryManager(); |
169 | if( geomManager.isSubtype(TYPES.SURFACE, shapeType) ||
|
||
170 | geomManager.isSubtype(TYPES.MULTISURFACE, shapeType) ) { |
||
171 | return placementConstraints != null && placementConstraints.isParallel(); |
||
172 | 40911 | jldominguez | } |
173 | return false; |
||
174 | } |
||
175 | |||
176 | } |