sixth level
diff --git a/src/elements/AmbientLight.java b/src/elements/AmbientLight.java
index 88a95cd..362c750 100644
--- a/src/elements/AmbientLight.java
+++ b/src/elements/AmbientLight.java
@@ -8,33 +8,20 @@
  * @author Adiel
  *
  */
-public class AmbientLight {
-
-	/**
-	 * Intensity of ambient light color
-	 */
-	final private Color _intensity;
+public class AmbientLight extends Light {
 
 	/**
 	 * 
-	 * AmbientLight constructor calculates the final power of fill lighting stored in
-	 *  a field _intensity
-	 *  
-	 * @param iA for original fill light (light intensity according to RGB components)
+	 * AmbientLight constructor calculates the final power of fill lighting stored
+	 * in a field _intensity in superClass
+	 * 
+	 * @param iA for original fill light (light intensity according to RGB
+	 *           components)
 	 * @param kA for coefficient of attenuation of filler light
 	 */
 	public AmbientLight(Color iA, double kA) {
+		super(iA.scale(kA));
 
-		this._intensity = iA.scale(kA);
-	}
-
-	/**
-	 * Getter intensity color
-	 * 
-	 * @return the _intensity
-	 */
-	public Color getIntensity() {
-		return _intensity;
 	}
 
 }
diff --git a/src/elements/DirectionalLight.java b/src/elements/DirectionalLight.java
new file mode 100644
index 0000000..2ab2a7e
--- /dev/null
+++ b/src/elements/DirectionalLight.java
@@ -0,0 +1,36 @@
+package elements;
+
+import primitives.Color;
+import primitives.Point3D;
+import primitives.Vector;
+
+public class DirectionalLight extends Light implements LightSource {
+	
+	
+	private Vector direction;
+
+	/**
+	 * DirectionalLight constructor initializes directional light with it's intensity and direction
+	 *  
+	 * @param intensity for the light
+	 * @param direction for direction vector
+	 */
+	public DirectionalLight(Color intensity, Vector direction) {
+		super(intensity);
+		this.direction = direction.normalized();
+	}
+
+	@Override
+	public Color getIntensity(Point3D p) {
+		
+		return super.getIntensity();
+	}
+
+	@Override
+	public Vector getL(Point3D p) {
+		
+		return direction;
+	}
+	
+
+}
diff --git a/src/elements/Light.java b/src/elements/Light.java
new file mode 100644
index 0000000..97412f2
--- /dev/null
+++ b/src/elements/Light.java
@@ -0,0 +1,34 @@
+/**
+ * 
+ */
+package elements;
+
+import primitives.Color;
+
+/**
+ * @author Adiel
+ * 
+ */
+ abstract class Light {
+	 
+	 private Color intensity;
+
+	/**
+	 * Light constructor
+	 * @param intensity
+	 */
+	protected Light(Color intensity) {
+		this.intensity = intensity;
+	}
+
+	/**
+	 * Getter the intensity
+	 * @return the intensity
+	 */
+	public Color getIntensity() {
+		return intensity;
+	}
+
+	
+
+}
diff --git a/src/elements/LightSource.java b/src/elements/LightSource.java
new file mode 100644
index 0000000..5b98f07
--- /dev/null
+++ b/src/elements/LightSource.java
@@ -0,0 +1,12 @@
+package elements;
+
+import primitives.Color;
+import primitives.Point3D;
+import primitives.Vector;
+
+public interface LightSource {
+	
+	public Color getIntensity(Point3D p);
+	public Vector getL(Point3D p);
+
+}
diff --git a/src/elements/PointLight.java b/src/elements/PointLight.java
new file mode 100644
index 0000000..2d5efa8
--- /dev/null
+++ b/src/elements/PointLight.java
@@ -0,0 +1,42 @@
+package elements;
+
+import primitives.Color;
+import primitives.Point3D;
+import primitives.Vector;
+
+public class PointLight extends Light implements LightSource {
+
+	private Point3D position;
+	private double kC;
+	private double kL;
+	private double kQ;
+
+	/**
+	 * @param intensity
+	 * @param position
+	 * @param kC
+	 * @param kL
+	 * @param kQ
+	 */
+	public PointLight(Color intensity, Point3D position, double kC, double kL, double kQ) {
+		super(intensity);
+		this.position = position;
+		this.kC = kC;
+		this.kL = kL;
+		this.kQ = kQ;
+	}
+
+	@Override
+	public Color getIntensity(Point3D p) {
+		
+		return getIntensity().reduce(kC + kL * p.distance(position) + kQ * p.distanceSquared(position));
+	}
+
+	@Override
+	public Vector getL(Point3D p) {
+
+		
+		return p.subtract(position).normalize();
+	}
+
+}
diff --git a/src/elements/SpotLight.java b/src/elements/SpotLight.java
new file mode 100644
index 0000000..783ebbd
--- /dev/null
+++ b/src/elements/SpotLight.java
@@ -0,0 +1,43 @@
+
+package elements;
+
+import primitives.Color;
+import primitives.Point3D;
+import primitives.Vector;
+
+public class SpotLight extends PointLight {
+
+	private Vector direction;
+
+	/**
+	 * @param direction
+	 * @param intensity 
+	 * @param position 
+	 * @param kC 
+	 */
+	public SpotLight(Color intensity, Point3D position,Vector direction,double kC,double kL,double kQ) {
+		super(intensity, position, kC, kL, kQ);
+		this.direction = direction.normalized();
+	}
+
+	@Override
+	public Color getIntensity(Point3D p) {
+		Vector l=getL(p);
+		/*
+		 * if(l==null) { return Color.BLACK; }
+		 */
+		double d=direction.dotProduct(l);
+		if(d<=0) {
+			return Color.BLACK;
+		}
+		//d=Math.pow(d, d)
+
+		return super.getIntensity(p).scale(d);
+	}
+	
+	/*
+	 * @Override public Vector getL(Point3D p) {
+	 * 
+	 * // TODO Auto-generated method stub return null; }
+	 */
+}
diff --git a/src/geometries/Geometries.java b/src/geometries/Geometries.java
index e84fde0..4889a8b 100644
--- a/src/geometries/Geometries.java
+++ b/src/geometries/Geometries.java
@@ -5,7 +5,6 @@
 
 import primitives.Point3D;
 import primitives.Ray;
-
 import java.util.Arrays;
 import java.util.LinkedList;
 import java.util.List;
@@ -27,6 +26,7 @@
 
 	/**
 	 * Constructor for the geometries
+	 * 
 	 * @param geometries for the intersections
 	 */
 	public Geometries(Intersectable... geometries) {
@@ -37,6 +37,7 @@
 
 	/**
 	 * Adding to list
+	 * 
 	 * @param geometries
 	 */
 	public void add(Intersectable... geometries) {
@@ -44,21 +45,34 @@
 
 	}
 
-	@Override
-	public List<Point3D> findIntersections(Ray ray) {
-		List<Point3D> result = null;
+	/*
+	 * @Override public List<Point3D> findIntersections(Ray ray) { List<Point3D>
+	 * result = null;
+	 * 
+	 * // A loop that adds to the list all the intersection points that the ray has
+	 * // with // all the geometric bodies for (Intersectable item :
+	 * _intersectableList) { List<Point3D> elementList =
+	 * item.findIntersections(ray); if (elementList != null) { if (result == null) {
+	 * result = new LinkedList<>(); } result.addAll(elementList); } } return result;
+	 * }
+	 */
 
-		//A loop that adds to the list all the intersection points that the ray has with 
-		//all the geometric bodies
-		for (Intersectable item : _intersectableList) {
-			List<Point3D> elementList = item.findIntersections(ray);
-			if (elementList != null) {
-				if (result == null) {
-					result = new LinkedList<>();
+	@Override
+	public List<GeoPoint> findGeoIntersections(Ray ray) {
+		List<GeoPoint> intersections = null;
+	
+		for (Intersectable geometry : _intersectableList ) {
+			var geoIntersectoions = geometry.findGeoIntersections(ray);
+			if (geoIntersectoions != null) {
+				if(intersections==null) {
+					intersections=new LinkedList<>(); 
+				
 				}
-				result.addAll(elementList);
+				intersections.addAll(geoIntersectoions);
 			}
 		}
-		return result;
+		return intersections;
 	}
+
+
 }
\ No newline at end of file
diff --git a/src/geometries/Geometry.java b/src/geometries/Geometry.java
index dcd47be..502f387 100644
--- a/src/geometries/Geometry.java
+++ b/src/geometries/Geometry.java
@@ -1,22 +1,71 @@
 package geometries;

 

 

+import primitives.Color;

+import primitives.Material;

 import primitives.Point3D;

 import primitives.Vector;

 

 /**

- * Interface for the geometric shapes

+ * Abstract class for the geometric shapes

  * 

  * @author Adiel

  *

  */

-public interface Geometry extends Intersectable{

+public abstract class Geometry implements Intersectable{

+	

+	protected Color emission=Color.BLACK;

+	private Material material=new Material();

+	

+	

+	/**

+	 * Getter for the emission

+	 * @return the emission

+	 */

+	public Color getEmission() {

+		return emission;

+	}

+

+

+	/**

+	 * Getter for material

+	 * @return the material

+	 */

+	public Material getMaterial() {

+		return material;

+	}

+	

+

+

+	/**

+	 * Setter for material

+	 * @param material the material to set

+	 * @return the Geometry itself

+	 */

+	public Geometry setMaterial(Material material) {

+		this.material = material;

+		return this;

+	}

+	

+

+

+	/**

+	 * Setter for the emission

+	 * @param emmission the emission to set 

+	 * @return the Geometry itself

+	 */

+	public Geometry setEmission(Color emission) {

+		this.emission = emission;

+		return this;

+	}

+

+

 	/**

 	 * 

 	 * @param point3D of the vector

 	 * @return normalized vector 

 	 */

-	Vector getNormal(Point3D point3D);

+	public abstract Vector getNormal(Point3D point3D);

 

 

 }

diff --git a/src/geometries/Intersectable.java b/src/geometries/Intersectable.java
index c3e8508..c132e20 100644
--- a/src/geometries/Intersectable.java
+++ b/src/geometries/Intersectable.java
@@ -6,6 +6,7 @@
 import primitives.*;
 
 import java.util.List;
+import java.util.stream.Collectors;
 
 /**
  * @author Adiel
@@ -13,11 +14,62 @@
  * Interface for intersection points
  */
 public interface Intersectable {
-    /**
+	/**
+	 * Static Internal Auxiliary Class (PDS) that is a tuple of references to a specific geometry 
+	 * and its intersection point
+	 * 
+	 *
+	 */
+	public static class GeoPoint{
+		public Geometry geometry;
+		public Point3D point;
+		
+		/**
+		 * GeoPoint constructor for geometry and point
+		 * 
+		 * @param geometry reference to current geometry
+		 * @param point reference to current point on geometry
+		 */
+		public GeoPoint(Geometry geometry, Point3D point) {
+			
+			this.geometry = geometry;
+			this.point = point;
+		}
+		
+		@Override
+		public boolean equals(Object obj) {
+			if (this == obj)
+				return true;
+			if (obj == null)
+				return false;
+			if (!(obj instanceof GeoPoint))
+				return false;
+			GeoPoint other = (GeoPoint) obj;
+			return geometry.equals(other.geometry) && point.equals(other.point);
+
+		}
+		
+		
+		
+		
+	}
+	
+	/**
+	 * Find all intersection points from the ray with the geometry
+	 * 
+	 * @param ray the famous Ray pointing to
+	 * @return list of intersection points
+	 */
+	List<GeoPoint> findGeoIntersections(Ray ray); 
+    
+	/**
      * Find all intersection points from the ray
      *
      * @param ray the famous Ray pointing to
      * @return intersection points
      */
-    List<Point3D> findIntersections(Ray ray);
+   default List<Point3D> findIntersections(Ray ray){
+	   var geoList=findGeoIntersections(ray);
+	   return geoList==null ? null : geoList.stream().map(gp->gp.point).collect(Collectors.toList());
+   }
 }
diff --git a/src/geometries/Plane.java b/src/geometries/Plane.java
index 26ae874..8f8d1c1 100644
--- a/src/geometries/Plane.java
+++ b/src/geometries/Plane.java
@@ -12,7 +12,7 @@
  * @author Adiel

  *

  */

-public class Plane implements Geometry {

+public class Plane extends Geometry {

 

 	final Point3D q0;

 	final Vector normal;

@@ -72,9 +72,30 @@
 	}

 

 	

+	/*

+	 * @Override public List<Point3D> findIntersections(Ray ray) { List<Point3D>

+	 * result = null;

+	 * 

+	 * //Check if q0=p0 if (q0.equals(ray.getP0())) { return null; }

+	 * 

+	 * double numerator = alignZero(normal.dotProduct(q0.subtract(ray.getP0())));

+	 * double denominator = alignZero(normal.dotProduct(ray.getDir()));

+	 * 

+	 * //Check if numerator or denominator equal zero if (isZero(numerator) ||

+	 * isZero(denominator)) { return null; }

+	 * 

+	 * double t = numerator / denominator; if (t < 0) { return result;//result=null

+	 * }

+	 * 

+	 * 

+	 * return List.of(ray.getPoint(t));

+	 * 

+	 * }

+	 */

+

 	@Override

-	public List<Point3D> findIntersections(Ray ray) {

-		List<Point3D> result = null;

+	public List<GeoPoint> findGeoIntersections(Ray ray) {

+List<GeoPoint> result = null;

 		

 		//Check if q0=p0 

 		if (q0.equals(ray.getP0())) {

@@ -95,7 +116,7 @@
 		}

 

 		

-		return List.of(ray.getPoint(t));

+		return List.of(new GeoPoint(this,ray.getPoint(t)));

 

 	}

 

diff --git a/src/geometries/Polygon.java b/src/geometries/Polygon.java
index ec98b6b..d55d95a 100644
--- a/src/geometries/Polygon.java
+++ b/src/geometries/Polygon.java
@@ -10,7 +10,7 @@
  * 

  * @author Dan

  */

-public class Polygon implements Geometry {

+public class Polygon extends Geometry {

 	/**

 	 * List of polygon's vertices

 	 */

@@ -86,16 +86,42 @@
 		return plane.getNormal();

 	}

 

+	/*

+	 * @Override public List<Point3D> findIntersections(Ray ray) { List<Point3D>

+	 * result = plane.findIntersections(ray);

+	 * 

+	 * // Check if intersect ray with the plane. if (result == null) { return null;

+	 * }

+	 * 

+	 * // Check if the intersection point with its plane is inside the polygon

+	 * Vector v = ray.getDir(); Point3D P0 = ray.getP0(); Vector v1 =

+	 * vertices.get(0).subtract(P0); Vector v2 = vertices.get(1).subtract(P0);

+	 * 

+	 * double t = alignZero(v.dotProduct(v1.crossProduct(v2).normalize())); if

+	 * (isZero(t)) { return null; }

+	 * 

+	 * boolean sign = t > 0; int size = vertices.size(); Vector vn =

+	 * vertices.get(size - 1).subtract(P0); t =

+	 * alignZero(v.dotProduct(vn.crossProduct(v1).normalize())); if (isZero(t) ||

+	 * sign ^ (t > 0)) { return null; }

+	 * 

+	 * // Check if all vertices have the same sign for (int i = 2; i < size; i++) {

+	 * v1 = v2; v2 = vertices.get(i).subtract(P0); t =

+	 * alignZero(v.dotProduct(v1.crossProduct(v2).normalize())); if (isZero(t) ||

+	 * sign ^ (t > 0)) { return null; }

+	 * 

+	 * } return result; }

+	 */

 	@Override

-	public List<Point3D> findIntersections(Ray ray) {

-		List<Point3D> result = plane.findIntersections(ray);

-		

-		//Check if intersect ray with the plane.

+	public List<GeoPoint> findGeoIntersections(Ray ray) {

+		List<GeoPoint> result = plane.findGeoIntersections(ray);

+

+		// Check if intersect ray with the plane.

 		if (result == null) {

 			return null;

 		}

-		

-		//Check if the intersection point with its plane is inside the polygon

+

+		// Check if the intersection point with its plane is inside the polygon

 		Vector v = ray.getDir();

 		Point3D P0 = ray.getP0();

 		Vector v1 = vertices.get(0).subtract(P0);

@@ -105,7 +131,7 @@
 		if (isZero(t)) {

 			return null;

 		}

-		

+

 		boolean sign = t > 0;

 		int size = vertices.size();

 		Vector vn = vertices.get(size - 1).subtract(P0);

@@ -113,8 +139,8 @@
 		if (isZero(t) || sign ^ (t > 0)) {

 			return null;

 		}

-		

-		//Check if all vertices have the same sign

+

+		// Check if all vertices have the same sign

 		for (int i = 2; i < size; i++) {

 			v1 = v2;

 			v2 = vertices.get(i).subtract(P0);

@@ -124,6 +150,6 @@
 			}

 

 		}

-		return result;

+		return List.of(new GeoPoint(this,result.get(0).point));

 	}

 }

diff --git a/src/geometries/Sphere.java b/src/geometries/Sphere.java
index 45bc424..4b8c071 100644
--- a/src/geometries/Sphere.java
+++ b/src/geometries/Sphere.java
@@ -13,7 +13,7 @@
  * @author Adiel

  *

  */

-public class Sphere implements Geometry {

+public class Sphere extends Geometry {

 

 	final Point3D center;

 	final double radius;

@@ -58,15 +58,42 @@
 		return vector.normalize();

 	}

 

+	/*

+	 * @Override public List<Point3D> findIntersections(Ray ray) { List<Point3D>

+	 * result = null; Point3D P0 = ray.getP0(); Vector v = ray.getDir();

+	 * //P0==center if (center.equals(P0)) {

+	 * 

+	 * return List.of(ray.getPoint(radius));

+	 * 

+	 * }

+	 * 

+	 * Vector u = center.subtract(P0);

+	 * 

+	 * double tm = alignZero(u.dotProduct(v)); double d =

+	 * alignZero(Math.sqrt(u.lengthSquared() - tm * tm));

+	 * 

+	 * if (d > radius) { return null; } double th = alignZero(Math.sqrt(radius *

+	 * radius - d * d));

+	 * 

+	 * double t1 = alignZero(tm - th); double t2 = alignZero(tm + th);

+	 * 

+	 * if (t1 > 0 && t2 > 0) { return List.of(ray.getPoint(t1), ray.getPoint(t2));

+	 * 

+	 * } else if (t1 > 0) { return List.of(ray.getPoint(t1));

+	 * 

+	 * } else if (t2 > 0) { return List.of(ray.getPoint(t2)); }

+	 * 

+	 * return result; }

+	 */

 	@Override

-	public List<Point3D> findIntersections(Ray ray) {

-		List<Point3D> result = null;

+	public List<GeoPoint> findGeoIntersections(Ray ray) {

+		List<GeoPoint> result = null;

 		Point3D P0 = ray.getP0();

 		Vector v = ray.getDir();

         //P0==center

 		if (center.equals(P0)) {

 			

-			return List.of(ray.getPoint(radius));

+			return List.of(new GeoPoint(this,ray.getPoint(radius)));

 

 		}

 

@@ -84,13 +111,14 @@
 		double t2 = alignZero(tm + th);

 

 		if (t1 > 0 && t2 > 0) {

-			return List.of(ray.getPoint(t1), ray.getPoint(t2));

+			return List.of(new GeoPoint(this,ray.getPoint(t1)),

+					new GeoPoint(this, ray.getPoint(t2)));

 		

 		} else if (t1 > 0) {

-			return List.of(ray.getPoint(t1));

+			return List.of(new GeoPoint(this,ray.getPoint(t1)));

 		

 		} else if (t2 > 0) {

-			return List.of(ray.getPoint(t2));

+			return List.of(new GeoPoint(this,ray.getPoint(t2)));

 		}

 		

 		return result;

diff --git a/src/geometries/Triangle.java b/src/geometries/Triangle.java
index 9efcba7..25044dc 100644
--- a/src/geometries/Triangle.java
+++ b/src/geometries/Triangle.java
@@ -27,4 +27,5 @@
 		return vertices + ", " + plane;

 	}

 

+	

 }

diff --git a/src/geometries/Tube.java b/src/geometries/Tube.java
index c7df809..5580660 100644
--- a/src/geometries/Tube.java
+++ b/src/geometries/Tube.java
@@ -13,7 +13,7 @@
  * @author Adiel

  *

  */

-public class Tube implements Geometry {

+public class Tube extends Geometry {

 

 	protected Ray axisRay;

 	protected double radius;

@@ -71,8 +71,10 @@
 		return vector.normalize();

 	}

 

+	

+

 	@Override

-	public List<Point3D> findIntersections(Ray ray) {

+	public List<GeoPoint> findGeoIntersections(Ray ray) {

 		// TODO Auto-generated method stub

 		return null;

 	}

diff --git a/src/primitives/Material.java b/src/primitives/Material.java
new file mode 100644
index 0000000..d0e2dd6
--- /dev/null
+++ b/src/primitives/Material.java
@@ -0,0 +1,35 @@
+package primitives;
+
+public class Material {
+
+	public double kD=0.0;
+	public double kS=0.0;
+	public int nShininess=0;
+	
+	/**
+	 * @param kD the kD to set
+	 * @return 
+	 */
+	public Material setkD(double kD) {
+		this.kD = kD;
+		return this;
+	}
+	/**
+	 * @param kS the kS to set
+	 * @return 
+	 */
+	public Material setkS(double kS) {
+		this.kS = kS;
+		return this;
+	}
+	/**
+	 * @param nShininess the nShininess to set
+	 * @return 
+	 */
+	public Material setnShininess(int nShininess) {
+		this.nShininess = nShininess;
+		return this;
+	}
+	
+	
+}
diff --git a/src/primitives/Ray.java b/src/primitives/Ray.java
index 6ccd995..3a27aca 100644
--- a/src/primitives/Ray.java
+++ b/src/primitives/Ray.java
@@ -1,6 +1,7 @@
 package primitives;

 

 import java.util.List;

+import geometries.Intersectable.GeoPoint;

 

 /**

  * Class Ray is the class representing a set of points on a line that are on one

@@ -80,12 +81,12 @@
 	public Point3D findClosestPoint(List<Point3D> points) {

 

 		Point3D result;

-		

-		//Check that the list is not empty

+

+		// Check that the list is not empty

 		if (points.size() > 0) {

 			result = points.get(0);

-			//A loop that goes through on the list 

-			//and checks what is the closest point to the beginning of the ray

+			// A loop that goes through on the list

+			// and checks what is the closest point to the beginning of the ray

 			for (Point3D other : points) {

 				if ((p0.distance(other)) < p0.distance(result)) {

 					result = other;

@@ -98,4 +99,33 @@
 		return null;

 	}

 

+	/**

+	 * 

+	 * Finding the closest point and geometry to the p0 of the camera

+	 * 

+	 * @param intersections list of points and geometries, the function should find from this list

+	 * the closest point and geometry to p0 of the camera in the scene 

+	 * @return the closest point and geometry to the camera

+	 */

+	public GeoPoint getClosestGeoPoint(List<GeoPoint> intersections) {

+		GeoPoint result;

+

+		// Check that the list is not empty

+		if (intersections.size() > 0) {

+			result = intersections.get(0);

+			

+			// A loop that goes through on the list

+			// and checks what is the closest point to the beginning of the ray

+			for (GeoPoint other : intersections) {

+				if ((other.point.distance(p0)) < result.point.distance(p0)) {

+					result = other;

+

+				}

+			}

+			return result;

+		}

+

+		return null;

+

+	}

 }

diff --git a/src/renderer/RayTracerBasic.java b/src/renderer/RayTracerBasic.java
index 3cc47c5..958a2b5 100644
--- a/src/renderer/RayTracerBasic.java
+++ b/src/renderer/RayTracerBasic.java
@@ -1,11 +1,14 @@
 package renderer;
 
-import java.util.List;
 
+import geometries.Intersectable.GeoPoint;
 import primitives.Color;
-import primitives.Point3D;
 import primitives.Ray;
+import primitives.Vector;
 import scene.Scene;
+import static primitives.Util.*;
+
+import elements.LightSource;
 
 /**
  * The class inherits from the abstract class RayTracerBase
@@ -28,25 +31,64 @@
 
 	/**
 	 * A private auxiliary function that receives a point and returns color
+	 * @param ray 
 	 * 
 	 * @param point for point
 	 * @return color of ambient light of the scene
 	 */
-	private Color calcColor(Point3D point) {
-		return scene.ambientLight.getIntensity();
+	private Color calcColor(GeoPoint intersection, Ray ray) {
+		return scene.ambientLight.getIntensity().add(intersection.geometry.getEmission())
+				.add(calcLocalEffects(intersection, ray));
 	}
 
 	@Override
 	public Color traceRay(Ray ray) {
-		List<Point3D> intersections = scene.geometries.findIntersections(ray);
+		var intersections=scene.geometries.findGeoIntersections(ray);
 
 		// If no intersection points were found
 		if (intersections == null) {
 			return scene.background;
 		}
 
-		Point3D closestPoint = ray.findClosestPoint(intersections);
-		return calcColor(closestPoint);
+		GeoPoint closestPoint = ray.getClosestGeoPoint(intersections);
+		return calcColor(closestPoint,ray);
 	}
 
+	private Color calcLocalEffects(GeoPoint intersection,Ray ray) {
+		Vector v=ray.getDir();
+		Vector n=intersection.geometry.getNormal(ray.getP0());
+		double nv=alignZero(n.dotProduct(v));
+		if(nv==0)
+			return Color.BLACK;
+		int nShininess=intersection.geometry.getMaterial().nShininess;
+		double kd=intersection.geometry.getMaterial().kD;
+		double ks=intersection.geometry.getMaterial().kS;
+		
+		Color color=Color.BLACK;
+		for(LightSource lightSource:scene.lights) {
+			Vector l=lightSource.getL(intersection.point);
+			double nl=alignZero(n.dotProduct(l));
+			if(nl*nv>0) {//sign(nl)==sign(nv)
+                   Color lightIntensity=lightSource.getIntensity(intersection.point);	
+                   color=color.add(calcDiffusive(kd,l,n,lightIntensity)
+                		   .add(calcSpecular(ks,l,n,v,nShininess,lightIntensity)));
+			}
+		}
+		return color;
+	}
+
+	private Color calcSpecular(double ks, Vector l, Vector n, Vector v, int nShininess, Color lightIntensity) {
+		
+		Vector r=l.subtract(n.scale(2*l.dotProduct(n)));
+		double vr=alignZero(-v.dotProduct(r));
+		if(vr>0) {
+			return lightIntensity.scale(ks* Math.pow(vr,nShininess));
+		}
+		return lightIntensity.scale(0);
+	}
+
+	private Color calcDiffusive(double kd, Vector l, Vector n, Color lightIntensity) {
+		return lightIntensity.scale(kd*Math.abs(l.dotProduct(n)));
+	
+	}
 }
diff --git a/src/renderer/Render.java b/src/renderer/Render.java
index 9a82a63..396516d 100644
--- a/src/renderer/Render.java
+++ b/src/renderer/Render.java
@@ -7,6 +7,7 @@
 import primitives.Ray;
 import scene.Scene;
 
+
 /**
  * This class creates from the scene the color matrix of the image
  * 
@@ -86,7 +87,7 @@
 			for (int j = 0; j < nY; ++j) {
 				ray = camera.constructRayThroughPixel(nX, nY, j, i);
 				color = rayTracer.traceRay(ray);
-				imageWriter.writePixel(i, j, color);
+				imageWriter.writePixel(j, i, color);
 
 			}
 	}
diff --git a/src/scene/Scene.java b/src/scene/Scene.java
index 270e7a0..dd09625 100644
--- a/src/scene/Scene.java
+++ b/src/scene/Scene.java
@@ -1,7 +1,11 @@
 package scene;
 
 
+import java.util.LinkedList;
+import java.util.List;
+
 import elements.AmbientLight;
+import elements.LightSource;
 import geometries.Geometries;
 import primitives.Color;
 
@@ -17,6 +21,7 @@
 	public Color background=Color.BLACK;
 	public AmbientLight ambientLight=new AmbientLight(Color.BLACK, 0.0);
 	public Geometries geometries=null;
+	public List<LightSource> lights=new LinkedList<LightSource>();
 	
 	/**
 	 * Scene constructor who gets the name of the scene and 
@@ -64,6 +69,17 @@
 		this.geometries = geometries;
 		return this;
 	}
+
+
+
+	
+	/**
+	 * @param lights the lights to set
+	 */
+	public Scene setLights(List<LightSource> lights) {
+		this.lights = lights;
+		return this;
+	}
 	
 	
 	
diff --git a/src/unittests/lights/LightsTests.java b/src/unittests/lights/LightsTests.java
new file mode 100644
index 0000000..70ae5fd
--- /dev/null
+++ b/src/unittests/lights/LightsTests.java
@@ -0,0 +1,178 @@
+package unittests.lights;
+
+import org.junit.Test;
+
+import elements.*;
+import geometries.*;
+import primitives.*;
+import renderer.*;
+import scene.Scene;
+
+/**
+ * Test rendering a basic image
+ * 
+ * @author Dan
+ */
+public class LightsTests {
+	private Scene scene1 = new Scene("Test scene");
+	private Scene scene2 = new Scene("Test scene") //
+			.setAmbientLight(new AmbientLight(new Color(java.awt.Color.WHITE), 0.15));
+	private Camera camera1 = new Camera(new Point3D(0, 0, 1000), new Vector(0, 0, -1), new Vector(0, 1, 0)) //
+			.setViewPlaneSize(150, 150) //
+			.setVpDistance(1000);
+	private Camera camera2 = new Camera(new Point3D(0, 0, 1000), new Vector(0, 0, -1), new Vector(0, 1, 0)) //
+			.setViewPlaneSize(200, 200) //
+			.setVpDistance(1000);
+
+	private static Geometry triangle1 = new Triangle( //
+			new Point3D(-150, -150, -150), new Point3D(150, -150, -150), new Point3D(75, 75, -150));
+	private static Geometry triangle2 = new Triangle( //
+			new Point3D(-150, -150, -150), new Point3D(-70, 70, -50), new Point3D(75, 75, -150));
+	private static Geometry sphere = new Sphere(50, new Point3D(0, 0, -50)) //
+			.setEmission(new Color(java.awt.Color.BLUE)) //
+			.setMaterial(new Material().setkD(0.5).setkS(0.5).setnShininess(100));
+
+	/**
+	 * Produce a picture of a sphere lighted by a directional light
+	 */
+	@Test
+	public void sphereDirectional() {
+		scene1.geometries.add(sphere);
+		scene1.lights.add(new DirectionalLight(new Color(500, 300, 0), new Vector(1, 1, -1)));
+
+		ImageWriter imageWriter = new ImageWriter("sphereDirectional", 500, 500);
+		Render render = new Render()//
+				.setImageWriter(imageWriter) //
+				.setScene(scene1) //
+				.setCamera(camera1) //
+				.setRayTracer(new RayTracerBasic(scene1));
+		render.renderImage();
+		render.writeToImage();
+	}
+
+	/**
+	 * Produce a picture of a sphere lighted by a point light
+	 */
+	@Test
+	public void spherePoint() {
+		scene1.geometries.add(sphere);
+		scene1.lights.add(new PointLight(new Color(500, 300, 0), new Point3D(-50, -50, 50), 1, 0.00001, 0.000001));
+
+		ImageWriter imageWriter = new ImageWriter("spherePoint", 500, 500);
+		Render render = new Render()//
+				.setImageWriter(imageWriter) //
+				.setScene(scene1) //
+				.setCamera(camera1) //
+				.setRayTracer(new RayTracerBasic(scene1));
+		render.renderImage();
+		render.writeToImage();
+	}
+
+	/**
+	 * Produce a picture of a sphere lighted by a spot light
+	 */
+	@Test
+	public void sphereSpot() {
+		scene1.geometries.add(sphere);
+		scene1.lights.add(new SpotLight(new Color(500, 300, 0), new Point3D(-50, -50, 50), new Vector(1, 1, -2), 1,
+				0.00001, 0.00000001));
+
+		ImageWriter imageWriter = new ImageWriter("sphereSpot", 500, 500);
+		Render render = new Render()//
+				.setImageWriter(imageWriter) //
+				.setScene(scene1) //
+				.setCamera(camera1) //
+				.setRayTracer(new RayTracerBasic(scene1));
+		render.renderImage();
+		render.writeToImage();
+	}
+
+	/**
+	 * Produce a picture of a two triangles lighted by a directional light
+	 */
+	@Test
+	public void trianglesDirectional() {
+		scene2.geometries.add(triangle1.setMaterial(new Material().setkD(0.8).setkS(0.2).setnShininess(300)), //
+				triangle2.setMaterial(new Material().setkD(0.8).setkS(0.2).setnShininess(300)));
+		scene2.lights.add(new DirectionalLight(new Color(300, 150, 150), new Vector(0, 0, -1)));
+
+		ImageWriter imageWriter = new ImageWriter("trianglesDirectional", 500, 500);
+		Render render = new Render()//
+				.setImageWriter(imageWriter) //
+				.setScene(scene2) //
+				.setCamera(camera2) //
+				.setRayTracer(new RayTracerBasic(scene2));
+		render.renderImage();
+		render.writeToImage();
+	}
+
+	/**
+	 * Produce a picture of a two triangles lighted by a point light
+	 */
+	@Test
+	public void trianglesPoint() {
+		scene2.geometries.add(triangle1.setMaterial(new Material().setkD(0.5).setkS(0.5).setnShininess(300)), //
+				triangle2.setMaterial(new Material().setkD(0.5).setkS(0.5).setnShininess(300)));
+		scene2.lights.add(new PointLight(new Color(500, 250, 250), new Point3D(10, -10, -130), 1, 0.0005, 0.0005));
+
+		ImageWriter imageWriter = new ImageWriter("trianglesPoint", 500, 500);
+		Render render = new Render()//
+				.setImageWriter(imageWriter) //
+				.setScene(scene2) //
+				.setCamera(camera2) //
+				.setRayTracer(new RayTracerBasic(scene2));
+		render.renderImage();
+		render.writeToImage();
+	}
+
+	/**
+	 * Produce a picture of a two triangles lighted by a spot light
+	 */
+	@Test
+	public void trianglesSpot() {
+		scene2.geometries.add(triangle1.setMaterial(new Material().setkD(0.5).setkS(0.5).setnShininess(300)),
+				triangle2.setMaterial(new Material().setkD(0.5).setkS(0.5).setnShininess(300)));
+		scene2.lights.add(new SpotLight(new Color(500, 250, 250), new Point3D(10, -10, -130), new Vector(-2, -2, -1), 1,
+				0.0001, 0.000005));
+
+		ImageWriter imageWriter = new ImageWriter("trianglesSpot", 500, 500);
+		Render render = new Render()//
+				.setImageWriter(imageWriter) //
+				.setScene(scene2) //
+				.setCamera(camera2) //
+				.setRayTracer(new RayTracerBasic(scene2));
+		render.renderImage();
+		render.writeToImage();
+	}
+
+	/*	*//**
+			 * Produce a picture of a sphere lighted by a narrow spot light
+			 */
+	/*
+	 * @Test public void sphereSpotSharp() { scene1.geometries.add(sphere);
+	 * scene1.lights.add(new SpotLight(new Color(500, 300, 0), new Point3D(-50, -50,
+	 * 50), new Vector(1, 1, -2), 1, 0.000005, 0.00000025, 5));
+	 * 
+	 * ImageWriter imageWriter = new ImageWriter("sphereSpotSharp", 500, 500);
+	 * Render render = new Render()// .setImageWriter(imageWriter) //
+	 * .setScene(scene1) // .setCamera(camera1) // .setRayTracer(new
+	 * RayTracerBasic(scene1)); render.renderImage(); render.writeToImage(); }
+	 * 
+	 *//**
+		 * Produce a picture of a two triangles lighted by a narrow spot light
+		 */
+	/*
+	 * @Test public void trianglesSpotSharp() {
+	 * scene2.geometries.add(triangle1.setMaterial(new
+	 * Material().setkD(0.5).setkS(0.5).setnShininess(300)),
+	 * triangle2.setMaterial(new
+	 * Material().setkD(0.5).setkS(0.5).setnShininess(300))); scene2.lights.add(new
+	 * SpotLight(new Color(800, 400, 400), new Point3D(10, -10, -130), new
+	 * Vector(-2, -2, -1), 1, 0.00005, 0.0000025, 5));
+	 * 
+	 * ImageWriter imageWriter = new ImageWriter("trianglesSpotSharp", 500, 500);
+	 * Render render = new Render()// .setImageWriter(imageWriter) //
+	 * .setScene(scene2) // .setCamera(camera2) // .setRayTracer(new
+	 * RayTracerBasic(scene2)); render.renderImage(); render.writeToImage(); }
+	 * 
+	 */}
diff --git a/src/unittests/primitives/RayTests.java b/src/unittests/primitives/RayTests.java
index 50449b0..cd52412 100644
--- a/src/unittests/primitives/RayTests.java
+++ b/src/unittests/primitives/RayTests.java
@@ -67,4 +67,10 @@
 		
 	}
 
+	
+	/**
+	 * Test method for {@link primitives.Ray#findClosestPoint(java.util.List)}.
+	 */
+	@Test
+	public void testGetClosestGeoPoint() {}
 }
diff --git a/src/unittests/renderer/ImageWriterTest.java b/src/unittests/renderer/ImageWriterTest.java
index b85d9b6..dd4371d 100644
--- a/src/unittests/renderer/ImageWriterTest.java
+++ b/src/unittests/renderer/ImageWriterTest.java
@@ -3,7 +3,6 @@
  */
 package unittests.renderer;
 
-
 import org.junit.Test;
 
 import renderer.ImageWriter;
@@ -24,21 +23,22 @@
 	public void writeImageTest() {
 
 		ImageWriter picture = new ImageWriter("test blue", 800, 500);
-		
-		//A loop that passes over the view plane and creates an image in one color
-		//and a grid of lines in a second color
+
+		// A loop that passes over the view plane and creates an image in one color
+		// and a grid of lines in a second color
 		for (int i = 0; i < 800; i++) {
-			for (int j = 0; j <500; j++) {
-				if (i % 50 == 0) {//for rows
-					//Writing pixel for grid
-					picture.writePixel(i, j,  new Color(255, 0, 255));
-		 		} 
-				else if (j % 50== 0) {//for columns
-					//Writing pixel for grid
+			for (int j = 0; j < 500; j++) {
+				if (i % 50 == 0) {// for rows
+					// Writing pixel for grid
 					picture.writePixel(i, j, new Color(255, 0, 255));
-				} 
+				}
+				
+				  else if (j % 50== 0) {//for columns
+					  //Writing pixel for grid
+				  picture.writePixel(i, j, new Color(255, 0, 255)); }
+				 
 				else {
-					//Writing blue pixel
+					// Writing blue pixel
 					picture.writePixel(i, j, new Color(0, 0, 255));
 				}
 			}
diff --git a/src/unittests/renderer/RenderTests.java b/src/unittests/renderer/RenderTests.java
index f5386cc..3adbd0f 100644
--- a/src/unittests/renderer/RenderTests.java
+++ b/src/unittests/renderer/RenderTests.java
@@ -1,6 +1,17 @@
 package unittests.renderer;
 
+import java.io.IOException;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+import javax.xml.parsers.ParserConfigurationException;
+
 import org.junit.Test;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.SAXException;
 
 import elements.*;
 import geometries.*;
@@ -8,15 +19,13 @@
 import renderer.*;
 import scene.Scene;
 
-
-
 /**
  * Test rendering a basic image
  * 
  * @author Dan
  */
 public class RenderTests {
-	private Camera camera = new Camera(Point3D.ZERO, new Vector(0, 0, -1), new Vector(0, -1, 0)) //
+	private Camera camera = new Camera(Point3D.ZERO, new Vector(0, 0, -1), new Vector(0, 1, 0)) //
 			.setVpDistance(100) //
 			.setViewPlaneSize(500, 500);
 
@@ -38,8 +47,8 @@
 																													// right
 				new Triangle(new Point3D(-100, 0, -100), new Point3D(0, -100, -100), new Point3D(-100, -100, -100)), // down
 																														// left
-				new Triangle(new Point3D(100, 0, -100), new Point3D(0, -100, -100), new Point3D(100, -100, -100))); // down
-																													// right
+		new Triangle(new Point3D(100, 0, -100), new Point3D(0, -100, -100), new Point3D(100, -100, -100))); // down
+																											// right
 
 		ImageWriter imageWriter = new ImageWriter("base render test", 1000, 1000);
 		Render render = new Render() //
@@ -54,25 +63,65 @@
 	}
 
 	/**
-	
- * Test for XML based scene - for bonus
+	 * 
+	 * Test for XML based scene - for bonus
 	 * 
 	 *
 	 */
 
+	
 	/*
 	 * @Test public void basicRenderXml() { Scene scene = new
 	 * Scene("XML Test scene"); // enter XML file name and parse from XML file into
-	 * scene object //
+	 * scene object // DocumentBuilderFactory
+	 * factory=DocumentBuilderFactory.newInstance(); try { DocumentBuilder builder=
+	 * factory.newDocumentBuilder(); Document doc=builder.parse("scene.xml");
+	 * NodeList geometriesList=doc.getElementsByTagName("geometries"); for(int i=0;
+	 * i<geometriesList.getLength(); i++) { Node p=geometriesList.item(i);
+	 * if(p.getNodeType()==Node.ELEMENT_NODE) { Element geometry=(Element) p; String
+	 * radius=geometry.getAttribute("radius"); NodeList
+	 * nameList=geometry.getChildNodes(); for(int j=0;j<nameList.getLength();j++) {
+	 * Node n= nameList.item(j); if(n.getNodeType()==Node.ELEMENT_NODE) { Element
+	 * name=(Element) n; System.out.println("geometries "+radius+":"+
+	 * name.getTagName()+"="+name.getAttribute("radius")); } }
 	 * 
+	 * }
+	 * 
+	 * } } catch (ParserConfigurationException e) { // TODO Auto-generated catch
+	 * block e.printStackTrace(); } catch (SAXException e) { // TODO Auto-generated
+	 * catch block e.printStackTrace(); } catch (IOException e) { // TODO
+	 * Auto-generated catch block e.printStackTrace(); }
 	 * 
 	 * ImageWriter imageWriter = new ImageWriter("xml render test", 1000, 1000);
-	 * Render render = new Render() // .setImageWriter(imageWriter) //
-	 * .setScene(scene) // .setCamera(camera) // .setRayTracer(new
-	 * RayTracerBasic(scene));
+	 * Render render = new Render() .setImageWriter(imageWriter) .setScene(scene)
+	 * .setCamera(camera) .setRayTracer(new RayTracerBasic(scene));
 	 * 
 	 * render.renderImage(); render.printGrid(100, new
 	 * Color(java.awt.Color.YELLOW)); render.writeToImage(); }
 	 */
+	  @Test
+		public void basicRenderMultiColorTest() {
+			Scene scene = new Scene("Test scene")//
+					.setAmbientLight(new AmbientLight(new Color(java.awt.Color.WHITE), 0.2)); //
 
+			scene.geometries.add(new Sphere(50, new Point3D(0, 0, -100)), //
+					new Triangle(new Point3D(-100, 0, -100), new Point3D(0, 100, -100), new Point3D(-100, 100, -100)) // up left
+							.setEmission(new Color(java.awt.Color.GREEN)),
+					new Triangle(new Point3D(100, 0, -100), new Point3D(0, 100, -100), new Point3D(100, 100, -100)), // up right
+					new Triangle(new Point3D(-100, 0, -100), new Point3D(0, -100, -100), new Point3D(-100, -100, -100)) // down left
+							.setEmission(new Color(java.awt.Color.RED)),
+					new Triangle(new Point3D(100, 0, -100), new Point3D(0, -100, -100), new Point3D(100, -100, -100)) // down right
+							.setEmission(new Color(java.awt.Color.BLUE)));
+
+			ImageWriter imageWriter = new ImageWriter("color render test", 1000, 1000);
+			Render render = new Render() //
+					.setImageWriter(imageWriter) //
+					.setScene(scene) //
+					.setCamera(camera) //
+					.setRayTracer(new RayTracerBasic(scene));
+
+			render.renderImage();
+			render.printGrid(100, new Color(java.awt.Color.WHITE));
+			render.writeToImage();
+		}
 }