def __init__(self, jsonData, lightRay): """ Creates an instance of scene. Attributes: jsonData (dict): The json data containing the information of the scene to be instanciated. lightRay (Ray, None): The initial light ray, if present in the scene. """ self.width = jsonData.get('width') self.height = jsonData.get('height') self.center = Point3D(self.width/2, self.height/2, 0) self.objects = [ Box(self.center, self.width, self.height) ] self.lightRay = lightRay for o in jsonData.get('objects'): type = o.get('type') c = o.get('center') center = Point3D(c[0], c[1], 0) if type == "circle": radius = o.get('radius') self.objects.append( Circle(center, radius) ) elif type == "box": width = o.get('width') height = o.get('height') self.objects.append( Box(center, width, height) )
def intersection(self, line): """ Returns the intersection between self and another line. Args: line (Line): The line that may intersect with self. Returns: Point3D, Line, None: The result of the intersection, which may be empty, a single point or the entire line. """ nullVector = Vector3D.zero() if(self.direction == nullVector or line.direction == nullVector): # No intersection return None p1 = self.point p2 = line.point # choosing another point p2 to represent "line" if p1 == p2 if (p1 == p2): p2 = Point3D(p2.x + line.direction.x, p2.y + line.direction.y, p2.z + line.direction.z) if (line.contains(p1)): if (self.contains(p2)): # line and self represent the same line return self else: # Unique point return p1 elif (self.contains(p2)): # Unique point return p2 else: s = 1 u = line.point - self.point v = line.direction.cross_product(u) w = line.direction.cross_product(self.direction) # Since we are in 2D, the z component for all point is 0, which means # that the result of any cross-product is a vector with both x and y = 0. # We only need to verify the z component. if (v.z == 0 or w.z == 0): # No intersection return None elif ( (v.z > 0 and w.z < 0) or \ (v.z < 0 and w.z > 0) ): s = -s d = s * v.norm() / w.norm() px = p1.x + d * self.direction.x py = p1.y + d * self.direction.y pz = p1.z + d * self.direction.z return Point3D(px, py, pz)
def __init__(self, center, width, height): """ Creates a box """ self.center = center self.width = width self.height = height p1 = Point3D(center.x - width/2, center.y - height/2, 0) p2 = Point3D(center.x + width/2, center.y - height/2, 0) p3 = Point3D(center.x + width/2, center.y + height/2, 0) p4 = Point3D(center.x - width/2, center.y + height/2, 0) self.lineSegments = [LineSegment(p1, p2), \ LineSegment(p2, p3), \ LineSegment(p3, p4), \ LineSegment(p4, p1)]
def __init__(self, radius, nbLon, nbLat): """ Creates an instance of Obj. """ self.radius = radius self.center = Point3D(0.0, 0.0, 0.0) self.nbLon = nbLon self.nbLat = nbLat self.vertices = [] self.faces = []
def getPoint(self, u, v): """ Finds a point on self's surface using u, v coordinates. Args: u (float): The u coordinate, in radians. v (float): The v coordinate, in randians. """ return Point3D((self.radius + self.minorRadius*cos(u))*cos(v),\ (self.radius + self.minorRadius*cos(u))*sin(v),\ self.minorRadius*sin(u))
def contains(self, point): """ Verifies if self contains a given point. Args: point (Point3D): The point to verify. Returns: bool: True if self contains "point", false otherwise. """ p1 = self.point p2 = Point3D(p1.x + self.direction.x, p1.y + self.direction.y, 0) p1p0 = point - p1 p1p2 = point - p2 return (p1p0.cross_product(p1p2) == Vector3D.zero())
def reflectedRay(self, lightRay): """ Returns the light ray reflected on self and originating from "lightRay", if exists. Args: lightRay (Ray): The originating light ray Returns: Ray, None: The reflected light ray, if exists. "None" otherwise. """ distance = lightRay.origin - self.center a = lightRay.direction.square_norm() b = 2 * lightRay.direction.dot_product(distance) c = distance.square_norm() - self.radius ** 2 d = b**2 - 4*a*c s = 1 # no intersection if (d < 0): return None t1 = (-b - sqrt(b**2 - 4*a*c))/(2*a) t2 = (-b + sqrt(b**2 - 4*a*c))/(2*a) # no intersection if (t1 < 0.001 and t2 < 0.001): return None # two intersection, taking the closest one to lightRay's origin elif (t1 > 0.001 and t2 > 0.001): t = min([t1, t2]) # one intersection, the one with a positive t value else: t = max([t1, t2]) origin = Point3D(lightRay.origin.x + lightRay.direction.x*t, lightRay.origin.y + lightRay.direction.y*t, lightRay.origin.z + lightRay.direction.z*t) normal = origin - self.center direction = lightRay.direction.reflect(normal) return Ray(origin, direction, lightRay.intensity - 1)
def loadScene(): """ Returns the scene using data (json file path, light ray parameters) specified in argv. Returns: Scene: The loaded scene. """ # Opening Json file cwd = os.path.dirname(os.path.realpath(__file__)) sceneFile = cwd + "/" + sys.argv[1] try: jsonData = json.loads(open(sceneFile).read()) except: print(ERR_INVALID_FILENAME) sys.exit(0) lightRay = None # creating Ray object if the parameters were specified if (len(sys.argv) > 3): params = [float(s) for s in sys.argv[3].split(",")] if (len(params) != 5): print(ERR_LIGHT_RAY_PARAMS) sys.exit(0) origin = Point3D(params[0], params[1], 0) direction = Vector3D(params[2], params[3], 0) intensity = params[4] lightRay = Ray(origin, direction, intensity) # creating scene object try: scene = Scene(jsonData, lightRay) except: print(ERR_INVALID_JSON) sys.exit(0) return scene