Statistics
| Revision:

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
/**
2
 * gvSIG. Desktop Geographic Information System.
3
 *
4
 * Copyright (C) 2007-2013 gvSIG Association.
5
 *
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
 * as published by the Free Software Foundation; either version 3
9
 * 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
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
19
 * MA  02110-1301, USA.
20
 *
21
 * For any additional information, do not hesitate to contact us
22
 * at info AT gvsig.com, or visit our website www.gvsig.com.
23
 */
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
import org.gvsig.fmap.geom.GeometryManager;
37
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
    @Override
52
        public ArrayList<LabelLocationMetrics> guess(
53
                        ILabelClass lc, Geometry geom,
54
                        IPlacementConstraints placementConstraints,
55
                        double cartographicSymbolSize, Cancellable cancel, ViewPort vp) {
56

    
57
                if (cancel.isCanceled()) {
58
            return CannotPlaceLabel.NO_PLACES;
59
        }
60
                
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
                        logger.warn("While getting centroid/interior point.", exc);
72
                }
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
                        logger.warn("While creating point.", e);
156
                }
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
    
164
    @Override
165
        public boolean isSuitableFor(IPlacementConstraints placementConstraints,
166
                        int shapeType) {
167
                
168
        GeometryManager geomManager = GeometryLocator.getGeometryManager();
169
        if( geomManager.isSubtype(TYPES.SURFACE, shapeType) ||
170
            geomManager.isSubtype(TYPES.MULTISURFACE, shapeType) ) {
171
                        return placementConstraints != null && placementConstraints.isParallel();
172
                }
173
                return false;
174
        }
175

    
176
}