/// <summary> /// Adds segments, tracks and vertices of a volume to another one. /// </summary> /// <param name="refvol">the volume to be augmented with the content of the other.</param> /// <param name="addvol">segments, tracks and vertices from this volume are added to the other.</param> /// <param name="ds">the dataset that should be assigned to imported tracks.</param> /// <param name="fds">the dataset that should be imported; if this parameter is <c>null</c>, all datasets are imported.</param> /// <param name="flt">track mapping filter function.</param> /// <param name="logstrw">the stream where logging information is to be dumped; set to <c>null</c> to disable logging.</param> public void AddToVolume(SySal.TotalScan.Flexi.Volume refvol, SySal.TotalScan.Flexi.Volume addvol, SySal.TotalScan.Flexi.DataSet ds, SySal.TotalScan.Flexi.DataSet fds, MapManager.dMapFilter flt, System.IO.TextWriter logstrw) { if (logstrw != null) { logstrw.WriteLine("Begin AddToVolume."); } #if !DEBUG try { #endif int i, j, n; SySal.DAQSystem.Scanning.IntercalibrationInfo[] calinfo = new SySal.DAQSystem.Scanning.IntercalibrationInfo[addvol.Layers.Length]; for (i = 0; i < addvol.Layers.Length; i++) { for (j = 0; j < refvol.Layers.Length && (refvol.Layers[j].BrickId != addvol.Layers[i].BrickId || refvol.Layers[j].SheetId != addvol.Layers[i].SheetId || refvol.Layers[j].Side != addvol.Layers[i].Side); j++) { ; } if (j == refvol.Layers.Length) { throw new Exception("No reference layer found for Brick/Sheet/Side = " + addvol.Layers[i].BrickId + "/" + addvol.Layers[i].SheetId + "/" + addvol.Layers[i].Side); } if (logstrw != null) { logstrw.WriteLine("Seeking mapping for layer " + i + " Brick/Sheet/Side " + refvol.Layers[i].BrickId + "/" + refvol.Layers[i].SheetId + "/" + refvol.Layers[i].Side); } calinfo[i] = MapTransform(MapManager.ExtractMap(refvol.Layers[j], (MapSide)refvol.Layers[j].Side, flt, true), MapManager.ExtractMap(addvol.Layers[i], (MapSide)refvol.Layers[j].Side, flt, true), null, logstrw); } for (i = 0; i < addvol.Layers.Length; i++) { SySal.TotalScan.Layer lay = addvol.Layers[i]; n = lay.Length; SySal.DAQSystem.Scanning.IntercalibrationInfo cinfo = calinfo[i]; SySal.DAQSystem.Scanning.IntercalibrationInfo alinfo = new SySal.DAQSystem.Scanning.IntercalibrationInfo(); SySal.TotalScan.AlignmentData al = lay.AlignData; alinfo.MXX = al.AffineMatrixXX * cinfo.MXX + al.AffineMatrixXY * cinfo.MYX; alinfo.MXY = al.AffineMatrixXX * cinfo.MXY + al.AffineMatrixXY * cinfo.MYY; alinfo.MYX = al.AffineMatrixYX * cinfo.MXX + al.AffineMatrixYY * cinfo.MYX; alinfo.MYY = al.AffineMatrixYX * cinfo.MXY + al.AffineMatrixYY * cinfo.MYY; double rx = lay.RefCenter.X - cinfo.RX; double ry = lay.RefCenter.Y - cinfo.RY; alinfo.RX = lay.RefCenter.X; alinfo.RY = lay.RefCenter.Y; double dx = cinfo.MXX * rx + cinfo.MXY * ry - rx + cinfo.TX; double dy = cinfo.MYX * rx + cinfo.MYY * ry - ry + cinfo.TY; alinfo.TX = al.AffineMatrixXX * dx + al.AffineMatrixXY * dy + al.TranslationX; alinfo.TY = al.AffineMatrixYX * dx + al.AffineMatrixYY * dy + al.TranslationY; for (j = 0; j < n; j++) { SySal.TotalScan.Flexi.Segment seg = (SySal.TotalScan.Flexi.Segment)lay[j]; SySal.Tracking.MIPEmulsionTrackInfo info = seg.OriginalInfo; info.Slope = alinfo.Deform(info.Slope); info.Intercept = alinfo.Transform(info.Intercept); seg.SetInfo(info); } } if (logstrw != null) { logstrw.Write("Importing volume..."); } refvol.ImportVolume(ds, addvol, fds); if (logstrw != null) { logstrw.WriteLine("Done."); } #if !DEBUG } catch (Exception x) { if (logstrw != null) { logstrw.WriteLine("Error:\r\n" + x.ToString()); } } finally { if (logstrw != null) { logstrw.WriteLine("End AddToVolume."); } } #endif }
/// <summary> /// Maps a pattern of tracks onto another one. /// </summary> /// <param name="refpattern">the reference pattern.</param> /// <param name="mappattern">the pattern to be mapped.</param> /// <param name="flt">the filter function for mapping.</param> /// <param name="logstrw">the output stream where logging information is written; set to <c>null</c> to disable logging.</param> /// <returns>the transformation obtained.</returns> public SySal.DAQSystem.Scanning.IntercalibrationInfo MapTransform(SySal.Tracking.MIPEmulsionTrackInfo[] refpattern, SySal.Tracking.MIPEmulsionTrackInfo[] mappattern, MapManager.dMapFilter flt, System.IO.TextWriter logstrw) { SySal.DAQSystem.Scanning.IntercalibrationInfo calinfo = new SySal.DAQSystem.Scanning.IntercalibrationInfo(); try { if (logstrw != null) { logstrw.WriteLine("Begin pattern mapping."); } calinfo.MXX = calinfo.MYY = 1.0; calinfo.MXY = calinfo.MYX = 0.0; calinfo.RX = calinfo.RY = calinfo.TX = calinfo.TY = calinfo.TZ = 0.0; int nr = refpattern.Length; int na = mappattern.Length; if (logstrw != null) { logstrw.WriteLine("Ref tracks: " + nr); logstrw.WriteLine("Add tracks: " + na); } if (nr == 0 || na == 0) { return(calinfo); } SySal.BasicTypes.Rectangle refrect = new SySal.BasicTypes.Rectangle(); SySal.BasicTypes.Rectangle addrect = new SySal.BasicTypes.Rectangle(); SySal.Tracking.MIPEmulsionTrackInfo refinfo = refpattern[0]; SySal.Tracking.MIPEmulsionTrackInfo addinfo = mappattern[0]; refrect.MinX = refrect.MaxX = refinfo.Intercept.X; refrect.MinY = refrect.MaxY = refinfo.Intercept.Y; addrect.MinX = addrect.MaxX = addinfo.Intercept.X; addrect.MinY = addrect.MaxY = addinfo.Intercept.Y; int i; for (i = 1; i < nr; i++) { refinfo = refpattern[i]; if (refinfo.Intercept.X < refrect.MinX) { refrect.MinX = refinfo.Intercept.X; } else if (refinfo.Intercept.X > refrect.MaxX) { refrect.MaxX = refinfo.Intercept.X; } if (refinfo.Intercept.Y < refrect.MinY) { refrect.MinY = refinfo.Intercept.Y; } else if (refinfo.Intercept.Y > refrect.MaxY) { refrect.MaxY = refinfo.Intercept.Y; } } for (i = 1; i < na; i++) { addinfo = mappattern[i]; if (addinfo.Intercept.X < addrect.MinX) { addrect.MinX = addinfo.Intercept.X; } else if (addinfo.Intercept.X > addrect.MaxX) { addrect.MaxX = addinfo.Intercept.X; } if (addinfo.Intercept.Y < addrect.MinY) { addrect.MinY = addinfo.Intercept.Y; } else if (addinfo.Intercept.Y > addrect.MaxY) { addrect.MaxY = addinfo.Intercept.Y; } } SySal.BasicTypes.Rectangle maprect = new SySal.BasicTypes.Rectangle(); maprect.MinX = Math.Max(refrect.MinX, addrect.MinX); maprect.MaxX = Math.Min(refrect.MaxX, addrect.MaxX); maprect.MinY = Math.Max(refrect.MinY, addrect.MinY); maprect.MaxY = Math.Min(refrect.MaxY, addrect.MaxY); int xcells = (int)Math.Ceiling((maprect.MaxX - maprect.MinX) / m_Config.MapSize); int ycells = (int)Math.Ceiling((maprect.MaxY - maprect.MinY) / m_Config.MapSize); if (logstrw != null) { logstrw.WriteLine("Ref rect: " + refrect.MinX + " " + refrect.MaxX + " " + refrect.MinY + " " + refrect.MaxY); logstrw.WriteLine("Map rect: " + addrect.MinX + " " + addrect.MaxX + " " + addrect.MinY + " " + addrect.MaxY); logstrw.WriteLine("Common rect: " + maprect.MinX + " " + maprect.MaxX + " " + maprect.MinY + " " + maprect.MaxY); logstrw.WriteLine("X cells: " + xcells + " Y cells: " + ycells); } if (xcells <= 0 || ycells <= 0) { return(calinfo); } int ix, iy; System.Collections.ArrayList[,] rmaps = new System.Collections.ArrayList[ycells, xcells]; System.Collections.ArrayList[,] amaps = new System.Collections.ArrayList[ycells, xcells]; for (ix = 0; ix < xcells; ix++) { for (iy = 0; iy < ycells; iy++) { rmaps[iy, ix] = new System.Collections.ArrayList(); amaps[iy, ix] = new System.Collections.ArrayList(); } } for (i = 0; i < nr; i++) { refinfo = refpattern[i]; ix = (int)((refinfo.Intercept.X - maprect.MinX) / m_Config.MapSize); if (ix < 0 || ix >= xcells) { continue; } iy = (int)((refinfo.Intercept.Y - maprect.MinY) / m_Config.MapSize); if (iy < 0 || iy >= ycells) { continue; } if (flt == null || flt(refinfo)) { rmaps[iy, ix].Add(refinfo); } } for (i = 0; i < na; i++) { addinfo = mappattern[i]; ix = (int)((addinfo.Intercept.X - maprect.MinX) / m_Config.MapSize); if (ix < 0 || ix >= xcells) { continue; } iy = (int)((addinfo.Intercept.Y - maprect.MinY) / m_Config.MapSize); if (iy < 0 || iy >= ycells) { continue; } if (flt == null || flt(addinfo)) { amaps[iy, ix].Add(addinfo); } } System.Collections.ArrayList mres = new System.Collections.ArrayList(); for (ix = 0; ix < xcells; ix++) { for (iy = 0; iy < ycells; iy++) { SySal.Tracking.MIPEmulsionTrackInfo[] ri = (SySal.Tracking.MIPEmulsionTrackInfo[])rmaps[iy, ix].ToArray(typeof(SySal.Tracking.MIPEmulsionTrackInfo)); if (ri.Length <= 0) { continue; } SySal.Tracking.MIPEmulsionTrackInfo[] ai = (SySal.Tracking.MIPEmulsionTrackInfo[])amaps[iy, ix].ToArray(typeof(SySal.Tracking.MIPEmulsionTrackInfo)); if (ai.Length <= 0) { continue; } MapResult mr = Map(ri, ai)[0]; if (mr.Valid) { SySal.BasicTypes.Vector2 p = new SySal.BasicTypes.Vector2(); p.X = maprect.MinX + m_Config.MapSize * (ix + 0.5); p.Y = maprect.MinY + m_Config.MapSize * (iy + 0.5); mres.Add(new object[] { p, mr }); logstrw.WriteLine("Z ix " + ix + " iy " + iy + " matches " + mr.Matches + " X " + p.X + " Y " + p.Y + " DeltaX/Y " + mr.DeltaPos.X + "/" + mr.DeltaPos.Y + " RMSX/Y " + mr.DeltaPosRMS.X + "/" + mr.DeltaPosRMS.Y + " DeltaSX/Y " + mr.DeltaSlope.X + "/" + mr.DeltaSlope.Y + " RMSX/Y " + mr.DeltaSlopeRMS.X + "/" + mr.DeltaSlopeRMS.Y); } else if (logstrw != null) { logstrw.WriteLine("Z ix " + ix + " iy " + iy + " matches " + mr.Matches); } } } double[,] inXY = new double[mres.Count, 2]; double[,] dXY = new double[mres.Count, 2]; for (i = 0; i < mres.Count; i++) { object[] o = (object[])mres[i]; inXY[i, 0] = ((SySal.BasicTypes.Vector2)o[0]).X; inXY[i, 1] = ((SySal.BasicTypes.Vector2)o[0]).Y; dXY[i, 0] = -((MapResult)o[1]).DeltaPos.X; dXY[i, 1] = -((MapResult)o[1]).DeltaPos.Y; if (logstrw != null) { logstrw.WriteLine("Zone " + i + " matches " + ((MapResult)o[1]).Matches + " " + inXY[i, 0] + " " + inXY[i, 1] + " " + dXY[i, 0] + " " + dXY[i, 1]); } } switch (mres.Count) { case 0: return(calinfo); case 1: return(calinfo = TransformFitter.FindTranslation(inXY, dXY)); case 2: return(calinfo = TransformFitter.FindRototranslation(inXY, dXY)); default: try { return(calinfo = TransformFitter.FindAffineTransformation(inXY, dXY)); } catch (Exception) { return(calinfo = TransformFitter.FindRototranslation(inXY, dXY)); } } } finally { if (logstrw != null) { logstrw.WriteLine("End mapping with RX/Y " + calinfo.RX + "/" + calinfo.RY + " MXX/XY/YX/YY " + calinfo.MXX + "/" + calinfo.MXY + "/" + calinfo.MYX + "/" + calinfo.MYY + " TX/Y " + calinfo.TX + "/" + calinfo.TY + "."); } } }