001 package physics3d; 002 003 004 /** 005 * PlaneCircle represents a plane circle in 3 space 006 * 007 * @specfield centerPoint : Vect3 // center of circle 008 * @specfield normal : Vect3 // a unit vector perpendicular to the circle 009 * @specfield radius : double // radius of circle 010 * @specfield texture : String // texture of this object 011 */ 012 public strictfp class PlaneCircle implements PhysicsShape { 013 private final Vect3 centerPoint; 014 015 private final Vect3 normal; 016 017 private final double radius; 018 019 private final String texture; 020 021 // Rep. Invariant: 022 // centerPoint != null && 023 // normal != null && 024 // radius >= 0.0 025 026 // Abstraction Function: 027 // The circle with a center at 'centerPoint' and a radius 'radius' 028 // oriented in the 'normal' direction 029 030 /** 031 * @requires <code>r</code> >= 0, <code>center</code> != null, 032 * <code>normal</code> != null, <code>normal.rho()</code> != 0, 033 * <code>texture</code> != null, 034 * 035 * 036 * @effects Creates a new circle with the specified size and location and 037 * orientation in 3D. 038 * 039 * @param center 040 * the center point of the circle 041 * @param normal 042 * the orientation of the circle 043 * @param r 044 * the radius of the circle 045 * 046 */ 047 public PlaneCircle(Vect3 center, Vect3 normal, double r, String texture) { 048 if ((r < 0) || (center == null) || (normal == null)) { 049 throw new IllegalArgumentException(); 050 } 051 this.centerPoint = center; 052 this.normal = normal.times(1 / normal.rho()); 053 this.radius = r; 054 this.texture = texture; 055 // checkRep(); 056 } 057 058 /** 059 * @requires <code>r</code> >= 0, <code>center</code> != null, 060 * <code>normal</code> != null, <code>normal.rho()</code> > 0 061 * 062 * @effects Creates a new circle with the specified size and location and 063 * orientation in 3D. 064 * 065 * @param center 066 * the center point of the circle 067 * @param normal 068 * the orientation of the circle 069 * @param r 070 * the radius of the circle 071 */ 072 public PlaneCircle(Vect3 center, Vect3 normal, double r) { 073 if ((r < 0) || (center == null) || (normal == null)) { 074 throw new IllegalArgumentException(); 075 } 076 this.centerPoint = center; 077 this.normal = normal.unitSize(); 078 this.radius = r; 079 this.texture = null; 080 // checkRep(); 081 } 082 083 @SuppressWarnings("unused") 084 private void checkRep() { 085 if (centerPoint == null || normal == null || radius < 0.0) { 086 throw new RuntimeException(); 087 } 088 } 089 090 // Observers -------------------------------------- 091 092 /** 093 * @return the center point of this circle. 094 */ 095 public Vect3 getCenter() { 096 // checkRep(); 097 return centerPoint; 098 } 099 100 /** 101 * @return the unit vector perpendicular to the given circle with correct 102 * orientation as specified at initilization. 103 */ 104 public Vect3 getNormal() { 105 // checkRep(); 106 return normal; 107 } 108 109 /** 110 * @return the radius of this circle. 111 */ 112 public double getRadius() { 113 // checkRep(); 114 return radius; 115 } 116 117 /** 118 * @return texture of this object 119 */ 120 public String getTexture() { 121 // checkRep(); 122 return this.texture; 123 } 124 125 /** 126 * @return the plane containing <code>this</code> 127 */ 128 public Plane planeContainingObject() { 129 // checkRep(); 130 return new Plane(normal, centerPoint); 131 } 132 133 /** 134 * @requires v != null 135 * @return true if <code>p</code> is within the geometric shape created by 136 * the intersection of a sphere of <code>radius</code> centered at 137 * <code>centerPoint</code> and the geometric shape created by 138 * moving <code>this</code> up and down <code>this.normal</code> 139 * by <code>GameConstants.TOLERANCE</code>, false otherwise 140 */ 141 public boolean containsPoint(Vect3 p) { 142 // checkRep(); 143 Vect3 v = p.minus(centerPoint); 144 Vect3 vPerp = v.projectOnToB(this.getNormal()); 145 Vect3 vPar = v.minus(vPerp); 146 if (vPar.rho() < radius && vPerp.rho() < GameConstants.TOLERANCE) { 147 return true; 148 } 149 return false; 150 } 151 152 /** 153 * @requires <code>p</code> is not null 154 * @return the minimum distance between <code>p</code> and <code>this</code> 155 */ 156 public double minDistanceToObjectFromP(Vect3 p) { 157 // checkRep(); 158 Vect3 v = this.planeContainingObject().perpVectorFromPlaneToPoint(p); 159 Vect3 pOnPlane = p.minus(v); 160 if (this.containsPoint(pOnPlane)) { 161 return v.rho(); 162 } 163 Vect3 obliqueVect = p.minus(centerPoint); 164 Vect3 perpVect = obliqueVect.projectOnToB(normal); 165 Vect3 parallelVect = obliqueVect.minus(perpVect); 166 Vect3 point = centerPoint.plus(parallelVect.unitSize().times(radius)); 167 return p.minus(point).rho(); 168 } 169 170 /** 171 * @requires center != null, axis != null, axis.rho() > 0, tAngle != null. 172 * @return A PlaneCircle rotated about the line created by center and axis 173 * counterclockwise by an amount tAngle with same texture 174 */ 175 public PlaneCircle rotateAboutCwithAxisAandAngleT(Vect3 center, Vect3 axis, 176 Angle tAngle) { 177 return new PlaneCircle(this.getCenter().minus(center).rotateAroundVect( 178 axis, tAngle).plus(center), this.getNormal().rotateAroundVect(axis, 179 tAngle), this.getRadius(), this.texture); 180 } 181 182 /** 183 * @requires t != null 184 * @return A PlaneCircle translated by t with same texture 185 */ 186 public PlaneCircle translateByT(Vect3 t) { 187 return new PlaneCircle(this.getCenter().plus(t), this.getNormal(), this 188 .getRadius(), this.texture); 189 } 190 191 // object methods 192 // 193 // public boolean equals(PlaneCircle c) { 194 // if (c == null) return false; 195 // return (radius == c.radius) && centerPoint.equals(c.centerPoint) 196 // && (Math.abs(normal.dot(c.normal)) == 1); 197 // } 198 // 199 // public boolean equals(Object o) { 200 // if (o instanceof PlaneCircle) 201 // return equals((PlaneCircle) o); 202 // else 203 // return false; 204 // } 205 // 206 public String toString() { 207 return "[Circle center=" + centerPoint + " radius=" + radius 208 + " normal vector=" + normal + "]"; 209 } 210 // 211 // public int hashCode() { 212 // return centerPoint.hashCode(); 213 // } 214 215 public ShapeClassification getShapeClassification() { 216 return ShapeClassification.PLANE_CIRCLE; 217 } 218 }