public virtual bool directedTowardsObjectside(Scientrace.SurfaceSide side, Scientrace.Trace aTrace) { switch (side) { case Scientrace.SurfaceSide.Back: // == SurfaceSide.Inside throw new NotImplementedException("Side "+side.ToString()+" not implemented for class"+this.GetType().ToString()); //break; case Scientrace.SurfaceSide.Front: throw new NotImplementedException("Side "+side.ToString()+" not implemented for class"+this.GetType().ToString()); //break; case Scientrace.SurfaceSide.Both: return true; //break; default: throw new NotImplementedException("Side "+side.ToString()+" not implemented"); //break; } }
public void write2dHistogramForPlane(Scientrace.PhysicalObject3d anObject, string plane_descr, Scientrace.UnitVector plane_vector) { Scientrace.UnitVector normvec = anObject.getSurfaceNormal(); Dictionary<string, double> angle_histogram = this.getHistogramTemplate(); foreach(Scientrace.Spot casualty in this.tj.spots) { //only count casualties for current object. if (casualty.object3d != anObject) continue; if (casualty == null) { Console.WriteLine("Error: Casualty is null when writing angle histogram2d for {"+anObject.ToString()+"} plane {"+plane_descr+"}..."); continue; } double angle_rad; if (plane_vector == null) { angle_rad = anObject.getSurfaceNormal().negative().angleWith(casualty.trace.traceline.direction); } else { //2d unraveling Scientrace.Vector vecOnPlane = casualty.trace.traceline.direction.projectOnPlaneWithNormal(plane_vector); //The angle on which the histogram bin is based. angle_rad = normvec.negative().angleWith(vecOnPlane); } string bin = this.radiansToRoundedDegString(angle_rad); double reweigh_factor = (this.lightsource_weigh_intensity) ? (casualty.trace.lightsource.weighted_intensity/casualty.trace.lightsource.total_lightsource_intensity) : 1; //Console.WriteLine("Line: "+casualty.trace.traceline.direction.trico()+" becomes: "+vecOnPlane.trico()+" angle:"+angle_rad+" / "+bin); this.addToBin(angle_histogram, bin, casualty.intensity*reweigh_factor, true); } string angle_histogram_csv_filename = this.tj.exportpath+this.angle_histogram_csv_filename.Replace("%o",anObject.tag).Replace("%t",this.tag).Replace("%s",plane_descr.Replace(" ", "_")); this.addHist2dConfigVars(normvec, plane_descr); //this.extra_exportable_config_vars.Add(plane_description, plane_vector); this.appendWriteWithConfigVariables(angle_histogram_csv_filename, angle_histogram); }
public override void write(Scientrace.PhysicalObject3d anObject) { Dictionary<string, double> angle_histogram = this.getHistogramTemplate(); foreach(Scientrace.Spot casualty in this.tj.spots) { //only count casualties for current object. if (casualty.object3d != anObject) continue; if (casualty == null) { Console.WriteLine("Error: Casualty is null when writing angle histogram for {"+anObject.ToString()+"}..."); continue; } //The angle on which the histogram bin is based. double angle_rad = anObject.getSurfaceNormal().negative().angleWith(casualty.trace.traceline.direction); //Moved to new method: radiansToRoundedDegString /*double angle_deg = angle_rad*180/Math.PI; double angle_deg_mod =((180+angle_deg)%360)-180; string bin = this.toResString(angle_deg_mod);*/ string bin = this.radiansToRoundedDegString(angle_rad); double reweigh_factor = (this.lightsource_weigh_intensity) ? (casualty.trace.lightsource.weighted_intensity/casualty.trace.lightsource.total_lightsource_intensity) : 1; this.addToBin(angle_histogram, bin, casualty.intensity*reweigh_factor, true); /* //Console.WriteLine("bin: "+bin+", angledegmod:"+angle_deg_mod+", hist_res:"+this.angle_histogram_resolution); if (angle_histogram.ContainsKey(bin)) //{ angle_histogram[bin] = angle_histogram[bin]+casualty.intensity; //Console.WriteLine("bin {"+bin+"} increased."); } else { this.addToOtherBin(casualty.intensity, angle_histogram); //Console.WriteLine("WARNING: BIN {"+bin+"} NOT FOUND FOR HISTOGRAM."+angle_deg_mod+"/"+angle_deg);\ } */ } string angle_histogram_csv_filename = this.tj.exportpath+this.angle_histogram_csv_filename.Replace("%o",anObject.tag); this.appendWriteWithConfigVariables(angle_histogram_csv_filename, angle_histogram); }
public Scientrace.Location traceLeavesEnvironment(Scientrace.Trace trace) { trace.currentObject = this; Scientrace.Line line = trace.traceline; UnitVector dir = line.direction; dir.check(); Vector loc = line.startingpoint; /* find locations where line leaves a sphere of radius this.radius around 0,0,0 * derivation: * r^2 = |l*dir + loc|^2 * hence: * 0 = l^2 * |dir|^2 + 2*l*|dir.loc| + |loc|^2 - r^2 //the "." represents a dotproduct * Solve ABC formula for l: * a = |dir|^2 * b = 2 * (loc . dir) * c = |loc|^2 - r^2 */ double a = Math.Pow(dir.x,2)+Math.Pow(dir.y,2)+Math.Pow(dir.z,2); double b = 2*(loc.x*dir.x+loc.y*dir.y+loc.z*dir.z); double c = Math.Pow(loc.x,2)+Math.Pow(loc.y,2)+Math.Pow(loc.z,2)-(Math.Pow(this.radius,2)); double discriminant = Math.Pow(b,2) - 4* a*c; if (discriminant < 0) { throw new ArgumentOutOfRangeException("Trace leaves environment from within environment. Are the boundaries of your environment perhaps smaller than your objects?\n Environment radius: "+this.radius+"\n Trace data:"+trace.ToString()); } //ABC formula double ans1 = (-b + Math.Sqrt(discriminant)) / (2*a); double ans2 = (-b - Math.Sqrt(discriminant)) / (2*a); double ans = Math.Max(ans1,ans2); //Console.WriteLine("\n"+ans.ToString()+" * "+dir.trico()+"( = "+(dir*ans).trico()+") +"+loc.trico()+" = "+((dir*ans)+loc).toLocation().ToCompactString()+" is ..."); // throw new AccessViolationException(); //Console.WriteLine("IT ENDS HERE: "+((dir*Math.Max(ans1,ans2))+loc).toLocation().ToString()); Scientrace.Location leavelocation = (dir*ans+loc).toLocation(); /* Console.WriteLine("Direction: "+dir.trico()+ "ABS ANS: "+(Math.Pow(b,2) - 4* a*c)+ "Location: "+loc.trico());*/ trace.perish(leavelocation); return leavelocation; }
public string exportSVG(Scientrace.PhysicalObject3d anObject, Scientrace.SurfaceSide side, Scientrace.PDPSource pdpSource) { //Scientrace.Parallelogram surface = anObject.getDistributionSurface(); //this.spotsize = Math.Sqrt(Math.Pow(surface.u.length,2)+Math.Pow(surface.v.length,2))*this.spotdiagonalfraction; this.spotsize = Math.Sqrt(Math.Pow(anObject.svgxsize,2)+Math.Pow(anObject.svgysize,2))*this.spotdiagonalfraction; StringBuilder retstr = new StringBuilder(10000000); // this string may become very big, allocating this amount of memory may help. retstr.Append(this.exportSVGOpening(anObject)); Scientrace.Location loc2d; StringBuilder pol_lines = new StringBuilder("<!-- START OF POLARISATION LINES -->",300000); StringBuilder centerSpots = new StringBuilder("<!-- START OF SPOTS CENTERS -->",300000); //Console.WriteLine("Now writing "+this.spots.Count+" spots"); //int icount = 0; foreach(Scientrace.Spot casualty in this.spots) { if ((casualty.object3d == anObject) && (anObject.directedTowardsObjectside(side, casualty.trace))) { loc2d = anObject.getSVG2DLoc(casualty.loc); // double pol_fac_1 = Math.Pow(casualty.pol_vec_1.length,2)*1.0;//*casualty.pol_vec_1.length * casualty.intensity*3; // double pol_fac_2 = Math.Pow(casualty.pol_vec_2.length,2)*1.0;//*casualty.pol_vec_2.length * casualty.intensity*3; double pol_fac_1 = Math.Pow(casualty.pol_vec_1.length,1)*1.00*Math.Sqrt(casualty.intensity);//*casualty.pol_vec_1.length * casualty.intensity*3; double pol_fac_2 = Math.Pow(casualty.pol_vec_2.length,1)*1.00*Math.Sqrt(casualty.intensity);//*casualty.pol_vec_2.length * casualty.intensity*3; Scientrace.Vector pol_vec_1_2d = (anObject.get2DLoc( casualty.pol_vec_1.projectOnPlaneWithNormal(anObject.getSurfaceNormal()).toLocation() )-anObject.get2DLoc(Location.ZeroLoc())).normaliseIfNotZero() * pol_fac_1; Scientrace.Vector pol_vec_2_2d = (anObject.get2DLoc( casualty.pol_vec_2.projectOnPlaneWithNormal(anObject.getSurfaceNormal()).toLocation() )-anObject.get2DLoc(Location.ZeroLoc())).normaliseIfNotZero() * pol_fac_2; if (this.svg_export_photoncloud) { retstr.Append(@"<g> <circle cx='"+loc2d.x+"' cy='"+(anObject.svgysize-loc2d.y)+"' r='"+(casualty.intensity*this.spotsize)+"' style='"+ "fill:"+this.getPhotonColourForPDPSource(casualty, pdpSource, anObject) +@";fill-opacity:0.3;stroke:none'> <title><!-- Tooltip -->"+this.spotDescriptor(casualty, anObject,true)+@"</title> </circle> </g>"); } // end if draw photoncloud (to create the frogg-egg kinda image) centerSpots.Append(@"<g> <circle cx='"+loc2d.x+"' cy='"+(anObject.svgysize-loc2d.y)+"' r='"+(casualty.intensity*this.spotsize/(this.svg_export_photoncloud?4:1))+"' style='"+ "fill:"+this.getPhotonColourForPDPSource(casualty, pdpSource, anObject) +@";fill-opacity:8;stroke:none'> <title><!-- Tooltip -->"+this.spotDescriptor(casualty, anObject,false)+@"</title> </circle> </g>"); pol_lines.Append(@" <line x1='"+(loc2d.x-(pol_vec_1_2d.x*this.spotsize))+"' y1='"+(anObject.svgysize-(loc2d.y-(pol_vec_1_2d.y*this.spotsize)))+"' x2='"+(loc2d.x+(pol_vec_1_2d.x*this.spotsize))+"' y2='"+(anObject.svgysize-(loc2d.y+(pol_vec_1_2d.y*this.spotsize)))+"' style='stroke:rgb(0,96,192);stroke-width:"+(casualty.intensity*this.spotsize/5)+@"' /> <line x1='"+(loc2d.x-(pol_vec_2_2d.x*this.spotsize))+"' y1='"+(anObject.svgysize-(loc2d.y-(pol_vec_2_2d.y*this.spotsize)))+"' x2='"+(loc2d.x+(pol_vec_2_2d.x*this.spotsize))+"' y2='"+(anObject.svgysize-(loc2d.y+(pol_vec_2_2d.y*this.spotsize)))+"' style='stroke:rgb(192,96,0);stroke-width:"+(casualty.intensity*this.spotsize/5)+@"' /> <line x1='"+(loc2d.x-(pol_vec_1_2d.x*this.spotsize))+"' y1='"+(anObject.svgysize-(loc2d.y-(pol_vec_1_2d.y*this.spotsize)))+"' x2='"+(loc2d.x+(pol_vec_1_2d.x*this.spotsize))+"' y2='"+(anObject.svgysize-(loc2d.y+(pol_vec_1_2d.y*this.spotsize)))+"' style='stroke:rgb(256,256,256);stroke-width:"+(casualty.intensity*this.spotsize/8)+@"' /> <line x1='"+(loc2d.x-(pol_vec_2_2d.x*this.spotsize))+"' y1='"+(anObject.svgysize-(loc2d.y-(pol_vec_2_2d.y*this.spotsize)))+"' x2='"+(loc2d.x+(pol_vec_2_2d.x*this.spotsize))+"' y2='"+(anObject.svgysize-(loc2d.y+(pol_vec_2_2d.y*this.spotsize)))+"' style='stroke:rgb(256,256,256);stroke-width:"+(casualty.intensity*this.spotsize/8)+@"' /> "); } // end condition for spot to be on the correct object and from the proper direction } centerSpots.Append("<!-- END OF CENTERSPOTS -->"); pol_lines.Append("<!-- END OF POLARISATION LINES -->"); retstr.Append(centerSpots); retstr.Append(pol_lines); foreach(Scientrace.SurfaceMarker marker in anObject.markers) { retstr.Append(marker.exportSVG()); } if (this.inline_legend) { retstr.Append("<!-- Start Legend for "+pdpSource.ToString()+" -->"); retstr.Append(this.colourLegend(pdpSource)); retstr.Append("<!-- End Legend for "+pdpSource.ToString()+" -->"); } retstr.Append("</svg> "); return retstr.ToString(); }
public void init(Scientrace.Location startloc, Scientrace.Location endloc) { if (startloc.distanceTo(endloc) <= 0) { throw new ArgumentOutOfRangeException("ERROR: Startloc ("+startloc.ToString()+") and endloc ("+endloc.ToString()+") are equal for linepiece, no line nor direction possible"); } this.startingpoint = startloc; this.endingpoint = endloc; this.calculateDirection(); }
/// <summary> /// Creates a line starting at the projection of this.loc on the intersection between this and another Plane. /// The direction of the line is that of the crossproduct of this.normal and anotherPlane.normal. /// </summary> /// <returns>A line along the intersection of this and anotherPlane, returns "null" if two planes are significantly parallel</returns> /// <param name="anotherPlane">A plane to calculate the intersection with</param> public Scientrace.Line getIntersectionLineWith(Scientrace.Plane anotherPlane) { Scientrace.UnitVector n1, n2; n1 = this.getNorm(); n2 = anotherPlane.getNorm(); Vector tw = n1.crossProduct(n2); if (tw.length < MainClass.SIGNIFICANTLY_SMALL) { //Console.WriteLine("WARNING: two planes do not intersect since they are parallel."); return null; } UnitVector intersection_direction = tw.tryToUnitVector(); Vector tl1 = n1.crossProduct(intersection_direction); if (tl1.length == 0) throw new Exception("Plane.getIntersectionLineWith/l1.length can never be zero. If this happens, notify the [email protected] about this..."+this.ToString()+anotherPlane.ToString()); // l1 lies in "this" plane, and is orthogonal to the intersectionline-direction UnitVector l1 = tl1.tryToUnitVector(); // where l1, starting at this.loc, meets anotherPlane we found a location on the intersectionline. Scientrace.Location retLoc = anotherPlane.lineThroughPlane(new Line(this.loc, l1)); if (retLoc == null) { Console.WriteLine("WARNING: retLoc == null; l1: "+l1.ToString()+" ; anotherPlane:"+anotherPlane.getNorm().ToString()); return null; } return new Line(retLoc, intersection_direction); }
/* END CONSTRUCTORS */ public override bool directedTowardsObjectside(Scientrace.SurfaceSide side, Trace aTrace) { Scientrace.NonzeroVector traceline_direction = aTrace.traceline.direction; switch (side) { case Scientrace.SurfaceSide.Back: // == SurfaceSide.Inside // Vector is directed TOWARDS (so in the contrary direction) of the surface normal // if (aVector.dotProduct(this.front_normal_direction)>0) /*Console.WriteLine(aTrace.traceid+" analysing: "+traceline_direction.tricon()+" from: "+aTrace.traceline.startingpoint.tricon()+ aTrace.parent.intensityFraction()+" = intensity \n"+ " DISTANCE: "+(aTrace.endloc-aTrace.traceline.startingpoint).length +" direction along: "+this.front_normal_direction.trico()+ " @"+aTrace.currentObject.GetType()); */ return (traceline_direction.dotProduct(this.front_normal_direction)>0); //break; case Scientrace.SurfaceSide.Front: // Vector is directed AWAY FROM (so along the direction) of the surface normal return (traceline_direction.dotProduct(this.front_normal_direction)<0); //break; case Scientrace.SurfaceSide.Both: return true; //break; default: throw new NotImplementedException("Side "+side.ToString()+" not implemented"); //break; } }
public float getRefractiveIndex(Scientrace.Trace trace) { throw new SubclassResponsibilityException("Implementation required of getRefractiveIndex(trace) function required at"+this.GetType().ToString()+trace.ToString()); }