/src/org/mt4j/util/ShapeBuilder.java
Java | 259 lines | 165 code | 46 blank | 48 comment | 12 complexity | 9f8943f8c54bf35a6641e1792d7fbbfd MD5 | raw file
1/*********************************************************************** 2 * mt4j Copyright (c) 2008 - 2010 Christopher Ruff, Fraunhofer-Gesellschaft All rights reserved. 3 * 4 * This program is free software: you can redistribute it and/or modify 5 * it under the terms of the GNU General Public License as published by 6 * the Free Software Foundation, either version 3 of the License, or 7 * (at your option) any later version. 8 * 9 * This program is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 * GNU General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program. If not, see <http://www.gnu.org/licenses/>. 16 * 17 ***********************************************************************/ 18package org.mt4j.util; 19 20import java.util.ArrayList; 21import java.util.List; 22 23 24import org.mt4j.components.TransformSpace; 25import org.mt4j.components.bounds.BoundsZPlaneRectangle; 26import org.mt4j.components.bounds.IBoundingShape; 27import org.mt4j.components.visibleComponents.shapes.AbstractShape; 28import org.mt4j.components.visibleComponents.shapes.MTComplexPolygon; 29import org.mt4j.components.visibleComponents.shapes.MTPolygon; 30import org.mt4j.util.math.ConvexityUtil; 31import org.mt4j.util.math.ToolsGeometry; 32import org.mt4j.util.math.Vertex; 33import org.mt4j.util.xml.svg.CustomPathHandler; 34 35import processing.core.PApplet; 36 37public class ShapeBuilder { 38 private CustomPathHandler pathHandler; 39 private PApplet app; 40 41 public ShapeBuilder(PApplet app){ 42 this.app = app; 43 this.pathHandler = new CustomPathHandler(); 44 45 } 46 47// public void startPath() throws ParseException { 48// this.pathHandler.startPath(); 49// } 50 51 public void reset(){ 52 this.pathHandler = new CustomPathHandler(); 53 } 54 55 /** 56 * Starts a new path at the specified absolute coordinate. 57 * 58 * @param x the x 59 * @param y the y 60 */ 61 public void movetoAbs(float x, float y){ 62 this.pathHandler.movetoAbs(x, y); 63 } 64 65 /** 66 * Starts a new path at the specified coordinate relative to the last coordinate. 67 * 68 * @param x the x 69 * @param y the y 70 */ 71 public void movetoRel(float x, float y){ 72 this.pathHandler.movetoRel(x, y); 73 } 74 75 public void arcAbs(float rx, float ry, float phi, boolean largeArc, boolean sweep, float x, float y) { 76 this.pathHandler.arcAbs(rx, ry, phi, largeArc, sweep, x, y); 77 } 78 79 public void arcRel(float rx, float ry, float phi, boolean largeArc,boolean sweep, float x, float y) { 80 this.pathHandler.arcRel(rx, ry, phi, largeArc, sweep, x, y); 81 } 82 83 84 public void curvetoCubicAbs(float x1, float y1, float x2, float y2,float x, float y){ 85 this.pathHandler.curvetoCubicAbs(x1, y1, x2, y2, x, y); 86 } 87 88 public void curvetoCubicRel(float x1, float y1, float x2, float y2,float x, float y) { 89 this.pathHandler.curvetoCubicRel(x1, y1, x2, y2, x, y); 90 } 91 92 public void curvetoCubicSmoothAbs(float x2, float y2, float x, float y){ 93 this.pathHandler.curvetoCubicSmoothAbs(x2, y2, x, y); 94 } 95 96 public void curvetoCubicSmoothRel(float x2, float y2, float x, float y){ 97 this.pathHandler.curvetoCubicSmoothRel(x2, y2, x, y); 98 } 99 100 public void curvetoQuadraticAbs(float x1, float y1, float x, float y) { 101 this.pathHandler.curvetoQuadraticAbs(x1, y1, x, y); 102 } 103 104 public void curvetoQuadraticRel(float x1, float y1, float x, float y){ 105 this.pathHandler.curvetoQuadraticRel(x1, y1, x, y); 106 } 107 108 public void curvetoQuadraticSmoothAbs(float x, float y){ 109 this.pathHandler.curvetoQuadraticSmoothAbs(x, y); 110 } 111 112 public void curvetoQuadraticSmoothRel(float x, float y) { 113 this.pathHandler.curvetoQuadraticSmoothRel(x, y); 114 } 115 116 public void linetoAbs(float x, float y){ 117 this.pathHandler.linetoAbs(x, y); 118 } 119 120 public void linetoHorizontalAbs(float x){ 121 this.pathHandler.linetoHorizontalAbs(x); 122 } 123 124 public void linetoHorizontalRel(float x){ 125 this.pathHandler.linetoHorizontalRel(x); 126 } 127 128 public void linetoRel(float x, float y){ 129 this.pathHandler.linetoRel(x, y); 130 } 131 132 public void linetoVerticalAbs(float y){ 133 this.pathHandler.linetoVerticalAbs(y); 134 } 135 136 public void linetoVerticalRel(float y){ 137 this.pathHandler.linetoVerticalRel(y); 138 } 139 140 public void setVerbose(boolean verbose) { 141 this.pathHandler.setVerbose(verbose); 142 } 143 144 /** 145 * Closed the current path by adding the start point again. 146 */ 147 public void closePath(){ 148 this.pathHandler.closePath(); 149 } 150 151 private void endPath(){ 152 this.pathHandler.endPath(); 153 } 154 155 156 public AbstractShape getShape(){ 157 this.endPath(); 158 159 ArrayList<Vertex[]> contours = this.pathHandler.getContours(); 160 Vertex[] allPoints = this.pathHandler.getPathPointsArray(); 161 AbstractShape returnComponent = null; 162 //Check for convexity 163 int convexity = ConvexityUtil.classifyPolygon2(allPoints.length, allPoints); 164 switch (convexity) { 165 case ConvexityUtil.NotConvexDegenerate: 166// logger.debug("not Convex Degenerate"); 167 case ConvexityUtil.NotConvex: 168// logger.debug("not convex"); 169 returnComponent = createComplexPoly(contours, MTComplexPolygon.WINDING_RULE_ODD); 170 break; 171 case ConvexityUtil.ConvexDegenerate: 172// logger.debug("convex degenerate"); 173 case ConvexityUtil.ConvexCW: 174// logger.debug("convex clockwise"); 175 case ConvexityUtil.ConvexCCW: 176// logger.debug("convex counterclockwise"); 177 returnComponent = createPoly(allPoints); 178 break; 179 default: 180 break; 181 } 182 183 //Create some default texture coords 184 if (returnComponent != null && returnComponent.hasBounds() && returnComponent.getBounds() instanceof BoundsZPlaneRectangle){ 185 BoundsZPlaneRectangle bounds = (BoundsZPlaneRectangle) returnComponent.getBounds(); 186 float width = bounds.getWidthXY(TransformSpace.LOCAL); 187 float height = bounds.getHeightXY(TransformSpace.LOCAL); 188 float upperLeftX = bounds.getVectorsLocal()[0].x; 189 float upperLeftY = bounds.getVectorsLocal()[0].y; 190 Vertex[] verts = returnComponent.getVerticesLocal(); 191 for (Vertex vertex : verts) { 192 vertex.setTexCoordU((vertex.x - upperLeftX) / width); 193 vertex.setTexCoordV((vertex.y - upperLeftY) / height); 194 //System.out.println("TexU:" + vertex.getTexCoordU() + " TexV:" + vertex.getTexCoordV()); 195 } 196 returnComponent.getGeometryInfo().updateTextureBuffer(returnComponent.isUseVBOs()); 197 } 198 return returnComponent; 199 } 200 201 private AbstractShape createPoly(Vertex[] verts) { 202 int segments = 15; 203 if (ToolsGeometry.containsBezierVertices(verts)) 204 verts = ToolsGeometry.createVertexArrFromBezierArr(verts, segments); 205 206 //Blow up vertex array, that will be used for picking etc 207 //to at least be of size == 3 for generating normals 208 if (verts.length <3){ 209 Vertex[] newVerts = new Vertex[3]; 210 if (verts.length == 2){ 211 newVerts[0] = verts[0]; 212 newVerts[1] = verts[1]; 213 newVerts[2] = (Vertex)verts[1].getCopy(); 214 verts = newVerts; 215 }else if (verts.length == 1){ 216 newVerts[0] = verts[0]; 217 newVerts[1] = (Vertex)verts[0].getCopy(); 218 newVerts[2] = (Vertex)verts[0].getCopy(); 219 verts = newVerts; 220 }else{ 221 //ERROR 222 } 223 } 224 return new MTPolygon2D(verts, app); 225 } 226 227 228 private AbstractShape createComplexPoly(ArrayList<Vertex[]> contours, int windingRuleOdd) { 229 int segments = 15; 230 List<Vertex[]> bezierContours = ToolsGeometry.createVertexArrFromBezierVertexArrays(contours, segments); 231 return new MTComplexPolygon2D(app, bezierContours); 232 } 233 234 235 private class MTComplexPolygon2D extends MTComplexPolygon{ 236 public MTComplexPolygon2D(PApplet app, List<Vertex[]> contours) { 237 super(app, contours); 238 239 } 240 @Override 241 protected IBoundingShape computeDefaultBounds() { 242 //Use z plane bounding rect instead default boundingsphere since always 2D! 243 return new BoundsZPlaneRectangle(this); 244 } 245 } 246 247 private class MTPolygon2D extends MTPolygon{ 248 public MTPolygon2D(Vertex[] vertices, PApplet applet) { 249 super(applet, vertices); 250 } 251 252 protected IBoundingShape computeDefaultBounds() { 253 //Use z plane bounding rect instead default boundingsphere since always 2D! 254 return new BoundsZPlaneRectangle(this); 255 } 256 } 257 258 259}