//Input: Physical Object ref and array of PointF to rotate around the object center point //Output: PointF array each with the new coordinates after the point has rotated around the object center point public static PointF[] RotatePointFArray(PhysicalObject ob, PointF[] p) { for (int i = 0; i < p.Length; i++) { p[i] = RotatePointF(ob, p[i]); } return(p); }
// // ----- Main Receiving Function ----- // This is the main function, which handle the events after the user click on the Display // The function, depending on the selected picturebox, will create a new object (lens, source or other) // while creating the new object it will give it some initial data depending on which object is it // such as the curser loctation on the display and the object type private void Display_MouseClick(object sender, MouseEventArgs e) { try { if (objectsList.Count < maxObjects && selectedPic != -1) { // setting new point, which is where the cursor is on the display Point currentLocation = this.displayScreen.PointToClient(Cursor.Position); //creating objects corresponding to the dropped picturebox if (selectedPic == 1 || selectedPic == 2 || selectedPic == 3 || selectedPic == 4 || selectedPic == 5) { objectsList.Add(new Lens(selectedPic)); } else if (selectedPic == 6) { objectsList.Add(new StraightSource()); } else if (selectedPic == 7) { objectsList.Add(new CircularSource()); } else if (selectedPic == 8) { objectsList.Add(new Block()); } else if (selectedPic == 9) { objectsList.Add(new Medium()); } else if (selectedPic == 10) { objectsList.Add(new Mirror()); } PhysicalObject ob = objectsList[objectsList.Count - 1]; ob.X = currentLocation.X; ob.Y = currentLocation.Y; highlightedIndex = objectsList.Count - 1; SaveObjectsState(); propTab.SelectedIndex = 0; UpdateInfo(); selectedPic = -1; } else if (objectsList.Count >= maxObjects && selectedPic != -1) { MessageBox.Show("Too many obejcts on screen"); } selectedPic = -1; } catch (Exception ex) { MessageBox.Show(ex.Message); } }
//copy button private void copyToolStripMenuItem_Click(object sender, EventArgs e) { try { if (highlightedIndex != -1) { saveObjectsList = (PhysicalObject)objectsList[highlightedIndex].GetCopy(); } } catch (Exception ex) { MessageBox.Show(ex.Message); } }
//Input: Physical Object ref and PointF to rotate around the object center point //Output: PointF with the new coordinates after the point has rotated around the object center point public static PointF RotatePointF(PhysicalObject ob, PointF pointToRotate) { double angleInRadians = -ob.Angle * (Math.PI / 180); PointF centerPoint = new PointF(ob.X, ob.Y); double cosTheta = Math.Cos(angleInRadians); double sinTheta = Math.Sin(angleInRadians); return(new PointF { X = (float) (cosTheta * (pointToRotate.X - centerPoint.X) - sinTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.X), Y = (float) (sinTheta * (pointToRotate.X - centerPoint.X) + cosTheta * (pointToRotate.Y - centerPoint.Y) + centerPoint.Y) }); }
//Input: Light list, graphics g, Physical object //Output: Change the Light list to the path casued by the Block public static void BlockAlgoritem(List <Light> lightList, Graphics g, PhysicalObject obj) { Light last = lightList[lightList.Count - 1]; PointF pi = last.pi; PointF pf = last.pf; Color lightColor = last.LightColor; Region BlockReg = obj.GetRegion(); Region rayReg = last.GetRegion(); BlockReg.Intersect(rayReg); //Intersect area of lens and the last light if (!BlockReg.IsEmpty(g)) { //getting the heat point RectangleF boundsRect = BlockReg.GetBounds(g); PointF hit = new PointF((boundsRect.Right + boundsRect.Left) / 2, (boundsRect.Top + boundsRect.Bottom) / 2); lightList[lightList.Count - 1] = new Light(pi, hit, lightColor); //light from start to hit point } }
//Input: Light and Graphics in which the light and the lens found at and index to ignore //Output: return the closest object which is IReflect in the screen public static int ClosestReflectionObject(Light light, Graphics g, int ignore) { int closesObj = -1; double minDistance = Main_Form.displayWidth, temp; for (int i = 0; i < Main_Form.objectsList.Count; i++) { if (Main_Form.objectsList[i] is IInteract && i != ignore) { PhysicalObject obj = Main_Form.objectsList[i]; if (((IInteract)obj).IsIntersect(light, g)) { temp = MathHelper.DistanceBetweenPointF(light.pi, obj.CenterPoint); if (temp < minDistance) { minDistance = temp; closesObj = i; } } } } return(closesObj); }
//Input: Graphics g, point which the last light start from, Lens object, angle of last light and the hit point //Output: calculate the angle in which the light comes out of the lens public static double GetImagePointAngle(Graphics g, PointF firstPoint, Lens obj, double angle, PointF hit) { bool imaginary = false; float f = (float)obj.FocalPoint; float u = (float)Math.Abs(obj.X - firstPoint.X); float ho = firstPoint.Y - obj.Y; float v = 1 / ((1 / f) - (1 / u)); float hi = (v * ho / u); PointF imagePoint = new PointF(); bool isVertical = obj.Angle > 225 && obj.Angle < 315 || obj.Angle > 45 && obj.Angle < 135; if (!isVertical) { Color imageColor = obj.RealImageColor; if (v * u < 0) { imageColor = obj.ImaginaryImageColor; imaginary = true; } if (firstPoint.X > obj.X) { v *= -1; } imagePoint = new PointF(obj.X + (float)(v), obj.Y - (float)hi); /*double angleToRotate = obj.Angle; * if (angleToRotate >= 90 && angleToRotate <= 270) angleToRotate = angleToRotate + 180; * imagePoint = MathHelper.RotatePointF(imagePoint, obj.CenterPoint, 0*angleToRotate);*/ //drawing image if (obj.ShowImage) { g.FillEllipse(new SolidBrush(imageColor), imagePoint.X - 5, imagePoint.Y - 5, 10, 10); } } else { u = (float)Math.Abs(obj.Y - firstPoint.Y); ho = -firstPoint.X + obj.X; v = 1 / ((1 / f) - (1 / u)); hi = (v * ho / u); Color imageColor = obj.RealImageColor; if (v * u < 0) { imageColor = obj.ImaginaryImageColor; imaginary = true; } if (firstPoint.Y > obj.Y) { v *= -1; } imagePoint = new PointF(obj.X + (float)(v), obj.Y - (float)hi); /*double angleToRotate = obj.Angle; * if (angleToRotate >= 0 && angleToRotate <= 180) angleToRotate = angleToRotate + 180; * imagePoint = MathHelper.RotatePointF(imagePoint, obj.CenterPoint, angleToRotate);*/ //drawing image if (obj.ShowImage) { g.FillEllipse(new SolidBrush(imageColor), imagePoint.X - 5, imagePoint.Y - 5, 10, 10); } } //give information to data class if (Main_Form.highlightedIndex != -1) { PhysicalObject highlighted = Main_Form.objectsList[Main_Form.highlightedIndex]; if (highlighted == obj) { LensInfo.focal = Math.Round(f, 3); LensInfo.u = Math.Round(u, 3); LensInfo.v = Math.Round(-v, 3); LensInfo.ho = Math.Round(-ho, 3); LensInfo.hi = Math.Round(hi, 3); } } double angleToReturn = new Light(hit, imagePoint).GetAngle(); if (imaginary) { angleToReturn = new Light(hit, imagePoint).GetAngle() + 180; } return(angleToReturn); }
//Input: Light list, graphics g, Physical object, screen index, medium index //Output: Change the Light list to the path casued by the Medium public static void MediumAlgoritem(List <Light> lightList, Graphics g, PhysicalObject obj, double n1, double n2) { Light last = lightList[lightList.Count - 1]; PointF pi = last.pi; PointF pf = last.pf; PointF firstPoint = new PointF(pi.X, pi.Y); Color lightColor = last.LightColor; Region mediumReg = obj.GetRegion(); Region rayReg = last.GetRegion(); double angle = last.GetAngle(); mediumReg.Intersect(rayReg); //Intersect area of lens and the last light if (!mediumReg.IsEmpty(g)) { PointF hit = GetHitPoint(pf, mediumReg, g); bool oppSide = false, isCritical = false; double alpha = 0, beta = 0, tempBeta = 0, criticalAngle = 0;//angles //getting hiting angle using math PointF[] points = obj.GetPoints(); Light first = new Light(firstPoint, hit); Light second = new Light(firstPoint, hit);//need to modified if (points.Length == 2) { second = new Light(points[0], points[1]); } alpha = 90 - MathHelper.AngleBetweenLights(first, second); // if ((firstPoint.X - hit.X) * (obj.X - hit.X) > 0) { oppSide = true; } //calculate critical angle if (!oppSide) { if (n1 > n2) { criticalAngle = Math.Round(Math.Asin(n2 / n1) * 180 / Math.PI); } isCritical = criticalAngle != 0 && alpha >= criticalAngle; } else { if (n2 > n1) { criticalAngle = Math.Round(Math.Asin(n1 / n2) * 180 / Math.PI); } isCritical = criticalAngle != 0 && alpha >= criticalAngle; } // if (isCritical)//act like a mirror { MirrorAlgoritem(lightList, g, obj); } else { if (!oppSide) { beta = (Math.Asin(n1 / n2 * Math.Sin(alpha * Math.PI / 180)) * 180 / Math.PI); //snal law beta = Math.Round(beta); tempBeta = beta; //save beta value } else //opposite side { beta = (Math.Asin(n2 / n1 * Math.Sin(alpha * Math.PI / 180)) * 180 / Math.PI); //snal law tempBeta = Math.Round(beta); //save beta value beta = 180 - Math.Round(beta); } //fix light direction float dirction = (firstPoint.Y - hit.Y) / (firstPoint.X - hit.X); dirction = Math.Abs(dirction) / dirction; if (oppSide) { dirction *= -1; } if (dirction == 1) { beta = 360 - beta; } // if (alpha % 90 != 0) { lightList[lightList.Count - 1] = new Light(firstPoint, hit, lightColor);//light from the start to the hit point lightList.Add(new Light(hit, MathHelper.GetEndLight(hit, beta + obj.Angle), lightColor)); } } //give information to data class if (Main_Form.highlightedIndex != -1) { PhysicalObject highlighted = Main_Form.objectsList[Main_Form.highlightedIndex]; if (highlighted == obj) { MediumInfo.alphaAngle = alpha; MediumInfo.betaAngle = tempBeta; MediumInfo.mediumIndex = n2; MediumInfo.criticalAngle = criticalAngle; } } } }
//Input: Light list, graphics g and a Physical object //Output: Change the Light list to the path casued by the Mirror public static void MirrorAlgoritem(List <Light> lightList, Graphics g, PhysicalObject obj) { Light last = lightList[lightList.Count - 1]; PointF pi = last.pi; PointF pf = last.pf; PointF firstPoint = new PointF(pi.X, pi.Y); Color lightColor = last.LightColor; Region mirrorReg = obj.GetRegion(); Region rayReg = last.GetRegion(); double angle = last.GetAngle(); bool vertical = false; mirrorReg.Intersect(rayReg); //Intersect area of lens and the last light if (!mirrorReg.IsEmpty(g)) { PointF hit = GetHitPoint(pf, mirrorReg, g); lightList[lightList.Count - 1] = new Light(pi, hit, lightColor); //light from the start to the hit point double alpha = 180 - (angle - 2 * obj.Angle); //check if the light hiting the vertical part of the mirror PointF[] points = obj.GetPoints(); if (points.Length == 4) { PointF p1 = points[0]; PointF p2 = points[1]; PointF p3 = points[2]; PointF p4 = points[3]; float x = hit.X; float y = hit.Y; bool check1 = x >= Math.Min(p1.X, p4.X) && x <= Math.Max(p1.X, p4.X) && y >= Math.Min(p1.Y, p4.Y) && y <= Math.Max(p1.Y, p4.Y); bool check2 = x >= Math.Min(p2.X, p3.X) && x <= Math.Max(p2.X, p3.X) && y >= Math.Min(p2.Y, p3.Y) && y <= Math.Max(p2.Y, p3.Y); vertical = check1 || check2; if (vertical) { alpha += 180; } } lightList.Add(new Light(hit, MathHelper.GetEndLight(hit, alpha), lightColor)); //light from the hit point farther //draw image and give info Color imageColor = Color.Blue; Mirror mirror = obj as Mirror; if (mirror != null && mirror.ShowImage) { //calc image imageColor = mirror.ImageColor; double beta = alpha + 180; double radius = MathHelper.DistanceBetweenPointF(hit, firstPoint); float height = (float)(radius * Math.Sin(beta * Math.PI / 180)); float width = (float)(radius * Math.Cos(beta * Math.PI / 180)); float addWidth = obj.X - hit.X; float addHeight = obj.Y - hit.Y; // //draw image PointF imagePoint = new PointF(obj.X + width + addWidth, obj.Y - height + addHeight); double angleToRotate = obj.Angle; if (angleToRotate >= 180 && angleToRotate <= 360) { angleToRotate = angleToRotate + 180; } imagePoint = MathHelper.RotatePointF(imagePoint, obj.CenterPoint, angleToRotate); g.FillEllipse(new SolidBrush(imageColor), imagePoint.X - 5, imagePoint.Y - 5, 10, 10); // //give information to data class if (Main_Form.highlightedIndex != -1) { PhysicalObject highlighted = Main_Form.objectsList[Main_Form.highlightedIndex]; if (highlighted == obj) { MirrorInfo.startPoint = firstPoint; //MirrorInfo.imagePoint = imagePoint; } } } // } }