001/* 002 * To change this template, choose Tools | Templates 003 * and open the template in the editor. 004 */ 005package armyc2.c5isr.graphics2d; 006import java.util.ArrayList; 007import armyc2.c5isr.JavaLineArray.POINT2; 008import armyc2.c5isr.JavaLineArray.ref; 009import armyc2.c5isr.JavaLineArray.arraysupport; 010import armyc2.c5isr.JavaLineArray.lineutility; 011import armyc2.c5isr.JavaLineArray.TacticalLines; 012 013/** 014 * 015* 016 */ 017public class BasicStroke implements Stroke { 018 019 /** 020 * Joins path segments by extending their outside edges until they meet. 021 */ 022 public final static int JOIN_MITER = 0; 023 /** 024 * Joins path segments by rounding off the corner at a radius of half the 025 * line width. 026 */ 027 public final static int JOIN_ROUND = 1; 028 /** 029 * Joins path segments by connecting the outer corners of their wide 030 * outlines with a straight segment. 031 */ 032 public final static int JOIN_BEVEL = 2; 033 /** 034 * Ends unclosed subpaths and dash segments with no added decoration. 035 */ 036 public final static int CAP_BUTT = 0; 037 /** 038 * Ends unclosed subpaths and dash segments with a round decoration that has 039 * a radius equal to half of the width of the pen. 040 */ 041 public final static int CAP_ROUND = 1; 042 /** 043 * Ends unclosed subpaths and dash segments with a square projection that 044 * extends beyond the end of the segment to a distance equal to half of the 045 * line width. 046 */ 047 public final static int CAP_SQUARE = 2; 048 float width; 049 int join; 050 int cap; 051 float miterlimit; 052 float dash[]; 053 float dash_phase; 054 055 public BasicStroke(float width, int cap, int join, float miterlimit, 056 float dash[], float dash_phase) { 057 if (width < 0.0f) { 058 throw new IllegalArgumentException("negative width"); 059 } 060 if (cap != CAP_BUTT && cap != CAP_ROUND && cap != CAP_SQUARE) { 061 throw new IllegalArgumentException("illegal end cap value"); 062 } 063 if (join == JOIN_MITER) { 064 if (miterlimit < 1.0f) { 065 throw new IllegalArgumentException("miter limit < 1"); 066 } 067 } else if (join != JOIN_ROUND && join != JOIN_BEVEL) { 068 throw new IllegalArgumentException("illegal line join value"); 069 } 070 if (dash != null) { 071 if (dash_phase < 0.0f) { 072 throw new IllegalArgumentException("negative dash phase"); 073 } 074 boolean allzero = true; 075 int n=dash.length; 076 //for (int i = 0; i < dash.length; i++) 077 for (int i = 0; i < n; i++) 078 { 079 float d = dash[i]; 080 if (d > 0.0) { 081 allzero = false; 082 } else if (d < 0.0) { 083 throw new IllegalArgumentException("negative dash length"); 084 } 085 } 086 if (allzero) { 087 throw new IllegalArgumentException("dash lengths all zero"); 088 } 089 } 090 this.width = width; 091 this.cap = cap; 092 this.join = join; 093 this.miterlimit = miterlimit; 094 if (dash != null) { 095 this.dash = (float[]) dash.clone(); 096 } 097 this.dash_phase = dash_phase; 098 } 099 100 public BasicStroke(float width, int cap, int join, float miterlimit) { 101 this(width, cap, join, miterlimit, null, 0.0f); 102 } 103 104 public BasicStroke(float width, int cap, int join) { 105 this(width, cap, join, 10.0f, null, 0.0f); 106 } 107 108 /** 109 * Constructs a solid <code>BasicStroke</code> with the specified line width 110 * and with default values for the cap and join styles. 111 * 112 * @param width 113 * the width of the <code>BasicStroke</code> 114 * @throws IllegalArgumentException 115 * if <code>width</code> is negative 116 */ 117 public BasicStroke(float width) { 118 this(width, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f); 119 } 120 121 /** 122 * Constructs a new <code>BasicStroke</code> with defaults for all 123 * attributes. The default attributes are a solid line of width 1.0, 124 * CAP_SQUARE, JOIN_MITER, a miter limit of 10.0. 125 */ 126 public BasicStroke() { 127 this(1.0f, CAP_SQUARE, JOIN_MITER, 10.0f, null, 0.0f); 128 } 129 130 /** 131 * Returns a <code>Shape</code> whose interior defines the stroked outline 132 * of a specified <code>Shape</code>. 133 * 134 * @param s 135 * the <code>Shape</code> boundary be stroked 136 * @return the <code>Shape</code> of the stroked outline. 137 */ 138 public Shape createStrokedShape(Shape s) { 139 /* 140 * sun.java2d.pipe.RenderingEngine re = 141 * sun.java2d.pipe.RenderingEngine.getInstance(); return 142 * re.createStrokedShape(s, width, cap, join, miterlimit, dash, 143 * dash_phase); 144 */ 145 return null; 146 } 147 public Shape createStrokedShape(Polygon poly) { 148 /* 149 * sun.java2d.pipe.RenderingEngine re = 150 * sun.java2d.pipe.RenderingEngine.getInstance(); return 151 * re.createStrokedShape(s, width, cap, join, miterlimit, dash, 152 * dash_phase); 153 */ 154 ArrayList<POINT2>pts=poly.getPathIterator(null).getPoints(); 155 int j=0; 156 GeneralPath gp=new GeneralPath(); 157 POINT2 pt=null; 158 POINT2[]ptsx=new POINT2[pts.size()]; 159 int n=pts.size(); 160 //for(j=0;j<pts.size();j++) 161 for(j=0;j<n;j++) 162 { 163 pt=pts.get(j); 164 ptsx[j]=pt; 165 } 166 167 pts=GetInteriorPoints(ptsx,pts.size(), TacticalLines.DEPTH_AREA,this.width); 168 169 170 //for(j=0;j<pts.size();j++) 171 for(j=0;j<n;j++) 172 { 173 pt=pts.get(j); 174 if(j==0) 175 gp.moveTo(pt.x, pt.y); 176 else 177 gp.lineTo(pt.x, pt.y); 178 } 179 return gp; 180 } 181 182 public float getLineWidth() { 183 return width; 184 } 185 186 /** 187 * Returns the end cap style. 188 * 189 * @return the end cap style of this <code>BasicStroke</code> as one of the 190 * static <code>int</code> values that define possible end cap 191 * styles. 192 */ 193 public int getEndCap() { 194 return cap; 195 } 196 197 public int getLineJoin() { 198 return join; 199 } 200 201 /** 202 * Returns the limit of miter joins. 203 * 204 * @return the limit of miter joins of the <code>BasicStroke</code>. 205 */ 206 public float getMiterLimit() { 207 return miterlimit; 208 } 209 210 /** 211 * Returns the array representing the lengths of the dash segments. 212 * Alternate entries in the array represent the user space lengths of the 213 * opaque and transparent segments of the dashes. As the pen moves along the 214 * outline of the <code>Shape</code> to be stroked, the user space distance 215 * that the pen travels is accumulated. The distance value is used to index 216 * into the dash array. The pen is opaque when its current cumulative 217 * distance maps to an even element of the dash array and transparent 218 * otherwise. 219 * 220 * @return the dash array. 221 */ 222 public float[] getDashArray() { 223 if (dash == null) { 224 return null; 225 } 226 return (float[]) dash.clone(); 227 } 228 229 public float getDashPhase() { 230 return dash_phase; 231 } 232 233 /** 234 * Returns the hashcode for this stroke. 235 * 236 * @return a hash code for this stroke. 237 */ 238 public int hashCode() { 239 int hash = Float.floatToIntBits(width); 240 hash = hash * 31 + join; 241 hash = hash * 31 + cap; 242 hash = hash * 31 + Float.floatToIntBits(miterlimit); 243 if (dash != null) { 244 hash = hash * 31 + Float.floatToIntBits(dash_phase); 245 int n=dash.length; 246 //for (int i = 0; i < dash.length; i++) 247 for (int i = 0; i < n; i++) 248 { 249 hash = hash * 31 + Float.floatToIntBits(dash[i]); 250 } 251 } 252 return hash; 253 } 254 255 public static ArrayList<POINT2> GetInteriorPoints(POINT2[] pLinePoints, 256 int vblCounter, 257 int lineType, 258 double dist) { 259 //var j:int=0; 260 int j = 0; 261 //var index:int=-1; 262 int index = -1; 263 //var pt0:POINT2,pt1:POINT2,pt2:POINT2; 264 POINT2 pt0 = null, pt1 = null, pt2 = null; 265 ///var m01:refobj=new refobj(),m12:refobj=new refobj(); //slopes for lines pt0-pt1 and pt1-pt2 266 ref<double[]> m01 = new ref(), m12 = new ref(), m1 = new ref(), m2 = new ref(); 267 //var direction:int=-1; 268 int direction = -1; 269 //var array:Array=new Array(); 270 //ArrayList<POINT2>array=new ArrayList(); 271 //var intersectPt:POINT2=null; 272 POINT2 intersectPt = null; 273 //var m1:refobj=new refobj(),m2:refobj=new refobj(); 274 //var intersectPoints:Array=new Array(); 275 ArrayList<POINT2> intersectPoints = new ArrayList(); 276 //var b01:Number,b12:Number; //the y intercepts for the lines corresponding to m1,m2 277 double b01 = 0, b12 = 0; 278 //var dist:Number=10; 279 //double dist = 10; 280 //the first set of interior points 281 //this assumes the area is closed 282 for (j = 0; j < vblCounter; j++) { 283 284 if (j == 0 || j == vblCounter - 1) { 285 //pt0=new POINT2(pLinePoints[vblCounter-2]); 286 //pt1=new POINT2(pLinePoints[0]); 287 //pt2=new POINT2(pLinePoints[1]); 288 pt0 = pLinePoints[vblCounter - 2]; 289 pt1 = pLinePoints[0]; 290 pt2 = pLinePoints[1]; 291 } else { 292 //pt0=new POINT2(pLinePoints[j-1]); 293 //pt1=new POINT2(pLinePoints[j]); 294 //pt2=new POINT2(pLinePoints[j+1]); 295 pt0 = pLinePoints[j - 1]; 296 pt1 = pLinePoints[j]; 297 pt2 = pLinePoints[j+1]; 298 } 299 300 //the interiior points 301 //var pt00:POINT2,pt01:POINT2; 302 //var pt10:POINT2,pt11:POINT2; 303 POINT2 pt00 = null, pt01 = null; 304 POINT2 pt10 = null, pt11 = null; 305 306 index = j - 1; 307 if (index < 0) { 308 index = vblCounter - 1; 309 } 310 311 direction = arraysupport.GetInsideOutsideDouble2(pt0, pt1, pLinePoints, vblCounter, index, lineType); 312 //reverse the directions since these are interior points 313 //pt00-pt01 will be the interior line inside line pt0-pt1 314 //pt00 is inside pt0, pt01 is inside pt1 315 switch (direction) { 316 case 0: 317 //direction=1; 318 pt00 = lineutility.ExtendDirectedLine(pt0, pt1, pt0, 1, dist); 319 pt01 = lineutility.ExtendDirectedLine(pt0, pt1, pt1, 1, dist); 320 break; 321 case 1: 322 //direction=0; 323 pt00 = lineutility.ExtendDirectedLine(pt0, pt1, pt0, 0, dist); 324 pt01 = lineutility.ExtendDirectedLine(pt0, pt1, pt1, 0, dist); 325 break; 326 case 2: 327 //direction=3; 328 pt00 = lineutility.ExtendDirectedLine(pt0, pt1, pt0, 3, dist); 329 pt01 = lineutility.ExtendDirectedLine(pt0, pt1, pt1, 3, dist); 330 break; 331 case 3: 332 //direction=2; 333 pt00 = lineutility.ExtendDirectedLine(pt0, pt1, pt0, 2, dist); 334 pt01 = lineutility.ExtendDirectedLine(pt0, pt1, pt1, 2, dist); 335 break; 336 } 337 338 //pt10-pt11 will be the interior line inside line pt1-pt2 339 //pt10 is inside pt1, pt11 is inside pt2 340 index = j; 341 if (j == vblCounter - 1) { 342 index = 0; 343 } 344 direction = arraysupport.GetInsideOutsideDouble2(pt1, pt2, pLinePoints, vblCounter, index, lineType); 345 //reverse the directions since these are interior points 346 switch (direction) { 347 case 0: 348 //direction=1; 349 pt10 = lineutility.ExtendDirectedLine(pt1, pt2, pt1, 1, dist); 350 pt11 = lineutility.ExtendDirectedLine(pt1, pt2, pt2, 1, dist); 351 break; 352 case 1: 353 //direction=0; 354 pt10 = lineutility.ExtendDirectedLine(pt1, pt2, pt1, 0, dist); 355 pt11 = lineutility.ExtendDirectedLine(pt1, pt2, pt2, 0, dist); 356 break; 357 case 2: 358 //direction=3; 359 pt10 = lineutility.ExtendDirectedLine(pt1, pt2, pt1, 3, dist); 360 pt11 = lineutility.ExtendDirectedLine(pt1, pt2, pt2, 3, dist); 361 break; 362 case 3: 363 //direction=2; 364 pt10 = lineutility.ExtendDirectedLine(pt1, pt2, pt1, 2, dist); 365 pt11 = lineutility.ExtendDirectedLine(pt1, pt2, pt2, 2, dist); 366 break; 367 } //end switch 368 //intersectPt=new POINT2(null); 369 //get the intersection of pt01-p00 and pt10-pt11 370 //so it it is the interior intersection of pt0-pt1 and pt1-pt2 371 372 //first handle the case of vertical lines. 373 if (pt0.x == pt1.x && pt1.x == pt2.x) { 374 intersectPt = new POINT2(pt01); 375 intersectPoints.add(intersectPt); 376 continue; 377 } 378 //it's the same situation if the slopes are identical, 379 //simply use pt01 or pt10 since they already uniquely define the intesection 380 lineutility.CalcTrueSlopeDouble2(pt00, pt01, m01); 381 lineutility.CalcTrueSlopeDouble2(pt10, pt11, m12); 382 if (m01.value[0] == m12.value[0]) { 383 intersectPt = new POINT2(pt01); 384 intersectPoints.add(intersectPt); 385 continue; 386 } 387 //now we are assuming a non-trivial intersection 388 //calculate the y-intercepts using y=mx+b (use b=y-mx) 389 b01 = pt01.y - m01.value[0] * pt01.x; 390 b12 = pt11.y - m12.value[0] * pt11.x; 391 392 intersectPt = lineutility.CalcTrueIntersectDouble2(m01.value[0], b01, m12.value[0], b12, 1, 1, 0, 0); 393 intersectPoints.add(intersectPt); 394 }//end for 395 return intersectPoints; 396 } 397}