void ParseScene_V2() { // get all the current axes A = SceneManager.Instance.sceneAxes; // ============================================================================== // ======================== PASS0: PARSING SPs ================================== // ============================================================================== foreach (var axis in A) { if (axis != null) { axis.UpdateCoords(); } } // Pass 0: Producing SPs // Stage 1: produce SPs of degree 3 for (int i = 0; i < A.Count; i++) { for (int j = 0; j < A.Count; j++) { for (int k = 0; k < A.Count; k++) { if (k == j || k == i || i == j) { continue; } if (A[i].isPrototype && A[j].isPrototype && A[k].isPrototype) { continue; } if (RSP1(A[i], A[j], A[k]) && adjacency[i, j, k] == null) { //create a 3D SPLOM // create a visualization object GameObject visObj = (GameObject)Instantiate(visualizationPrefab); Visualization vis = visObj.GetComponent <Visualization>(); vis.AddAxis(A[i]); vis.AddAxis(A[j]); vis.AddAxis(A[k]); adjacency[i, j, k] = vis; if (SP.Any(x => x.axes.Count == 1 && x.axes.Contains(A[i]))) { var toRemove = SP.Single(x => x.axes.Count == 1 && x.axes.Contains(A[i])); Destroy(SP.Find(x => x.axes.Count == 1 && x.axes.Contains(A[i])).gameObject); SP.Remove(toRemove); } if (SP.Any(x => x.axes.Count == 1 && x.axes.Contains(A[j]))) { var toRemove = SP.Single(x => x.axes.Count == 1 && x.axes.Contains(A[j])); Destroy(SP.Find(x => x.axes.Count == 1 && x.axes.Contains(A[j])).gameObject); SP.Remove(toRemove); } if (SP.Any(x => x.axes.Count == 1 && x.axes.Contains(A[k]))) { var toRemove = SP.Single(x => x.axes.Count == 1 && x.axes.Contains(A[k])); Destroy(SP.Find(x => x.axes.Count == 1 && x.axes.Contains(A[k])).gameObject); SP.Remove(toRemove); } //add it to 3D SPLOM LIST SP.Add(vis); //add the 3 axes to the used axis in 3DSPLOMS if (!usedAxisIn3DSP.Contains(A[i])) { usedAxisIn3DSP.Add(A[i]); } if (!usedAxisIn3DSP.Contains(A[j])) { usedAxisIn3DSP.Add(A[j]); } if (!usedAxisIn3DSP.Contains(A[k])) { usedAxisIn3DSP.Add(A[k]); } } //destroy the visualisation if not satisfying RSP1 anymore else if (RSP1_Distance(A[i], A[j], A[k]) && adjacency[i, j, k] != null) { Visualization v = adjacency[i, j, k]; //destroy the visualisation adjacency[i, j, k] = null; if (v != null) { // >>>>>>>>>>> HERE WHEN A 2D SP BECOMES A 3D SP <<<<<<<<<<<< //Clean the memory lists SPLOM3D sp = this.SPLOMS3D.Find(x => x.BaseVisualization == v); if (sp != null) { this.SPLOMS3D.Remove(sp); //sp.showAllHistogramsOnClear(); sp.ClearSplom(ref SP); Destroy(sp.gameObject); } //Clean the memory lists SP.Remove(v); Destroy(v.gameObject); } //Only remove from the list if no other 3DSP is using it if (!SP.Any(x => x.axes.Count == 3 && x.axes.Contains(A[i]))) { usedAxisIn3DSP.Remove(A[i]); } if (!SP.Any(x => x.axes.Count == 3 && x.axes.Contains(A[j]))) { usedAxisIn3DSP.Remove(A[j]); } if (!SP.Any(x => x.axes.Count == 3 && x.axes.Contains(A[k]))) { usedAxisIn3DSP.Remove(A[k]); } } } } } // Pass 0: // Stage 2: produce SPs of degree 2 // RULE: Degree 3 consumes lower degrees for (int i = 0; i < A.Count; i++) { for (int j = 0; j < A.Count; j++) { if (i == j) { continue; } if (A[i].isPrototype && A[j].isPrototype) { continue; } if ((RSP1(A[i], A[j])) && adjacency[i, j, i] == null && !usedAxisIn3DSP.Contains(A[i]) && !usedAxisIn3DSP.Contains(A[j])) { // create a visualization object GameObject visObj = (GameObject)Instantiate(visualizationPrefab); Visualization vis = visObj.GetComponent <Visualization>(); vis.AddAxis(A[i]); vis.AddAxis(A[j]); if (SP.Any(x => x.axes.Count == 1 && x.axes.Contains(A[i]))) { var toRemove = SP.Single(x => x.axes.Count == 1 && x.axes.Contains(A[i])); Destroy(SP.Find(x => x.axes.Count == 1 && x.axes.Contains(A[i])).gameObject); SP.Remove(toRemove); } if (SP.Any(x => x.axes.Count == 1 && x.axes.Contains(A[j]))) { var toRemove = SP.Single(x => x.axes.Count == 1 && x.axes.Contains(A[j])); Destroy(SP.Find(x => x.axes.Count == 1 && x.axes.Contains(A[j])).gameObject); SP.Remove(toRemove); } adjacency[i, j, i] = vis; adjacency[i, j, j] = vis; if (!usedAxisIn2DSP.Contains(A[i])) { usedAxisIn2DSP.Add(A[i]); } if (!usedAxisIn2DSP.Contains(A[j])) { usedAxisIn2DSP.Add(A[j]); } SP.Add(vis); //create a 2D SPLOM if only A[i] and A[j] do not belong to 3D SPLOM LIST //add it to 3D SPLOM LIST } else if (usedAxisIn3DSP.Contains(A[i]) && usedAxisIn3DSP.Contains(A[j]) && adjacency[i, j, i] != null) { //destroy the visualisation Visualization v = adjacency[i, j, i]; adjacency[i, j, i] = null; if (v != null) { // >>>>>>>>>>> HERE WHEN A 2D SP BECOMES A 3D SP <<<<<<<<<<<< //Clean the memory lists SPLOM3D sp = SPLOMS3D.Find(x => x.BaseVisualization == v); if (sp != null) { SPLOMS3D.Remove(sp); //sp.showAllHistogramsOnClear(); sp.ClearSplom(ref SP); Destroy(sp.gameObject); } SP.Remove(v); Destroy(v.gameObject); } //Only remove from the list if no other 2DSP is using it if (!SP.Any(x => x.axes.Count == 2 && x.axes.Contains(A[i]))) { usedAxisIn2DSP.Remove(A[i]); } if (!SP.Any(x => x.axes.Count == 2 && x.axes.Contains(A[j]))) { usedAxisIn2DSP.Remove(A[j]); } } else if (RSP1_Distance(A[i], A[j]) && adjacency[i, j, i] != null) { //destroy the visualisation Visualization v = adjacency[i, j, i]; SPLOM3D sp = SPLOMS3D.Find(x => x.BaseVisualization == v); if (sp != null) { SPLOMS3D.Remove(sp); //sp.showAllHistogramsOnClear(); sp.ClearSplom(ref SP); Destroy(sp.gameObject); } adjacency[i, j, i] = null; if (v != null) { //Clean the memory lists SP.Remove(v); Destroy(v.gameObject); } //Only remove from the list if no other 2DSP is using it if (!SP.Any(x => x.axes.Count == 2 && x.axes.Contains(A[i]))) { usedAxisIn2DSP.Remove(A[i]); } if (!SP.Any(x => x.axes.Count == 2 && x.axes.Contains(A[j]))) { usedAxisIn2DSP.Remove(A[j]); } } } } // Pass 0: // Stage 2: produce 1D Sps for (int i = 0; i < A.Count; i++) { // if A[i] does not belong to any higher order visualisation, // enable histogram and if (!SP.Any(x => x.axes.Count == 1 && x.axes[0] == A[i]) && !usedAxisIn2DSP.Contains(A[i]) && !usedAxisIn3DSP.Contains(A[i])) { GameObject visObj = (GameObject)Instantiate(visualizationPrefab); Visualization vis = visObj.GetComponent <Visualization>(); vis.AddAxis(A[i]); SP.Add(vis); } } // Pass 0: // Stage 3: produce Scatterplot Matrices for (int i = 0; i < SP.Count; i++) { // Pass 0: // Stage 4: produce Scatterplot 3D Matrices if ((SP[i].viewType == Visualization.ViewType.Scatterplot3D ||// SPLOM3Ds build on scatterplots 3D SP[i].viewType == Visualization.ViewType.Scatterplot2D) && // && SP[i].IsBaseSPLOM // !SPLOMS3D.Any(x => x.BaseVisualization == SP[i]) && !SP[i].IsSPLOMElement) // { //the SP is now a base for a SPLOM List <Axis> visuAxes = SP[i].axes; Axis x3D = SP[i].ReferenceAxis1.horizontal; // visuAxes[0].IsHorizontal ? visuAxes[0] : visuAxes[1].IsHorizontal ? visuAxes[1] : visuAxes[2]; Axis y3D = SP[i].ReferenceAxis1.vertical; //visuAxes.First(x => x != x3D && x.IsVertical);// visuAxes[0] == x3D ? visuAxes[1] : visuAxes[2] == x3D? visuAxes[0] : visuAxes[1]; Axis z3D = SP[i].ReferenceAxis1.depth; //visuAxes.First(x => x != x3D && x != y3D); GameObject splomHolder = new GameObject("ScatterplotMatrix " + SP[i].name); //create a base SPLOM SPLOM3D newSplom = splomHolder.AddComponent <SPLOM3D>();// new SPLOM(); newSplom.initialiseBaseScatterplot(SP[i], x3D, y3D, z3D); newSplom.VisualizationPrefab = visualizationPrefab; SPLOMS3D.Add(newSplom); } } //update Scatterplot matrices 3D for (int sp3d = 0; sp3d < SPLOMS3D.Count; sp3d++)// (var splom3D in SPLOMS3D) { SPLOM3D splom3D = SPLOMS3D[sp3d]; Axis x3D = null; if (splom3D.XAxes1.Count > 0) { x3D = splom3D.XAxes1.Last(); // get the last X axis } Axis y3D = null; if (splom3D.YAxes1.Count > 0) { y3D = splom3D.YAxes1.Last(); // get the last Y axis } Axis z3D = null; if (splom3D.ZAxes1.Count > 0) { z3D = splom3D.ZAxes1.Last(); // get the last Z axis } //look for a new axis Axis newXAxis = null; Axis newYAxis = null; Axis newZAxis = null; foreach (var axis in A) { if (x3D != null && Vector3.Distance(x3D.MaxPosition, axis.MinPosition) < SP_DISTANCE / 4f && x3D.IsColinear(axis) && !splom3D.XAxes1.Contains(axis)) { newXAxis = axis; } else if (y3D != null && Vector3.Distance(y3D.MaxPosition, axis.MinPosition) < SP_DISTANCE / 4f && y3D.IsColinear(axis) && !splom3D.YAxes1.Contains(axis)) { newYAxis = axis; } else if (z3D != null && Vector3.Distance(z3D.MaxPosition, axis.MinPosition) < SP_DISTANCE / 4f && z3D.IsColinear(axis) && !splom3D.ZAxes1.Contains(axis)) { newZAxis = axis; } } int indexX = -1; int indexY = -1; int indexZ = -1; if (newXAxis != null) // => new x axis found on splom 2D { splom3D.updateXAxes(newXAxis, ref SP); } else // look for removed axis on the X axis of the SPLOM { for (int i = 0; i < splom3D.XAxes1.Count - 1; i++) { //look for the first broken axis if (Vector3.Distance(splom3D.XAxes1[i].MaxPosition, splom3D.XAxes1[i + 1].MinPosition) > SP_DISTANCE / 4f) //broken axis { indexX = i + 1; break; } } } if (newYAxis != null) // => new y axis found on splom 2D { splom3D.updateYAxes(newYAxis, ref SP); } else { for (int i = 0; i < splom3D.YAxes1.Count - 1; i++) { //look for the first broken axis if (Vector3.Distance(splom3D.YAxes1[i].MaxPosition, splom3D.YAxes1[i + 1].MinPosition) > SP_DISTANCE / 4f) //broken axis { indexY = i + 1; break; } } } if (newZAxis != null) // => new y axis found on splom 2D { splom3D.updateZAxes(newZAxis, ref SP); } else { for (int i = 0; i < splom3D.ZAxes1.Count - 1; i++) { //look for the first broken axis if (Vector3.Distance(splom3D.ZAxes1[i].MaxPosition, splom3D.ZAxes1[i + 1].MinPosition) > SP_DISTANCE / 4f) //broken axis { indexZ = i + 1; break; } } } if (indexX >= 0) { splom3D.deleteS3DFromXAxes(indexX, ref SP); //show histograms on disconnected axes for (int i = indexX; i < splom3D.XAxes1.Count; i++) { foreach (var sp1 in SP.Where(x => x.axes.Count == 1)) { if (sp1.axes[0] == splom3D.XAxes1[i]) { sp1.ShowHistogram(true); } } } } if (indexY >= 0) { splom3D.deleteS3DFromYAxes(indexY, ref SP); for (int i = indexY; i < splom3D.YAxes1.Count; i++) { foreach (var sp1 in SP.Where(x => x.axes.Count == 1)) { if (sp1.axes[0] == splom3D.YAxes1[i]) { sp1.ShowHistogram(true); } } } } if (indexZ >= 0) { splom3D.deleteS3DFromZAxes(indexZ, ref SP); for (int i = indexZ; i < splom3D.ZAxes1.Count; i++) { foreach (var sp1 in SP.Where(x => x.axes.Count == 1)) { if (sp1.axes[0] == splom3D.ZAxes1[i]) { sp1.ShowHistogram(true); } } } } } // ============================================================================== // ======================== PASS1: PARSING PCPs ================================= // ============================================================================== //Pass1: enable close linked visualisations //HACK: THIS IS A COMPLETE BANDAID TO FIX THE FLOATING VISUALIZATION BUG, //TODO: We should be trying to work out why the visualization bug is occuring in the first place. for (var i = SP.Count - 1; i >= 0; i--) { if (SP[i] == null) { SP.RemoveAt(i); } } //TODO: END OF HACK for (int i = 0; i < SP.Count; i++) { for (int j = 0; j < SP.Count; j++) { if (i != j) { string _name = SP[i] + "-" + SP[j]; string _nameReverse = SP[j] + "-" + SP[i]; //test the distance between 2 axes if linking 2 histograms if (SP[i].viewType == Visualization.ViewType.Histogram && SP[j].viewType == Visualization.ViewType.Histogram) { if (SP[i].transform.position != SP[j].transform.position && Vector3.Distance(SP[i].axes[0].transform.position, SP[j].axes[0].transform.position) < PCP_DISTANCE && !linkedVisualisationDictionary.ContainsKey(_name) && !linkedVisualisationDictionary.ContainsKey(_nameReverse)) { SP[i].ShowHistogram(false); SP[j].ShowHistogram(false); LinkVisualisations(_name, SP[i], SP[j]); } } else if (SP[i].viewType == Visualization.ViewType.Histogram && SP[j].viewType != Visualization.ViewType.Histogram) { if (SP[i].axes[0].transform.position != SP[j].transform.position && Vector3.Distance(SP[i].axes[0].transform.position, SP[j].transform.position) < PCP_DISTANCE && !linkedVisualisationDictionary.ContainsKey(_name) && !linkedVisualisationDictionary.ContainsKey(_nameReverse)) // && !SP[j].IsSPLOMElement) { if (SP[i].viewType == Visualization.ViewType.Histogram) { SP[i].ShowHistogram(false); } if (SP[j].viewType == Visualization.ViewType.Histogram) { SP[j].ShowHistogram(false); } LinkVisualisations(_name, SP[i], SP[j]); } } else { if (SP[i].transform.position != SP[j].transform.position && Vector3.Distance(SP[i].transform.position, SP[j].transform.position) < PCP_DISTANCE && !linkedVisualisationDictionary.ContainsKey(_name) && !linkedVisualisationDictionary.ContainsKey(_nameReverse)) { if (SP[i].viewType == Visualization.ViewType.Histogram) { SP[i].ShowHistogram(false); } if (SP[j].viewType == Visualization.ViewType.Histogram) { SP[j].ShowHistogram(false); } LinkVisualisations(_name, SP[i], SP[j]); } } } } } // Dirty... this pass makes sure that all histograms stay hidden // if they belong to a SPLOM2D or 3D foreach (var item in SP) { if (item.viewType == Visualization.ViewType.Histogram && AxisInScatterplotMaxtrix(item.axes[0])) { item.ShowHistogram(false); } } //cleaning the visualisations that needs to be destroyed toDestroy.Clear(); foreach (var item in linkedVisualisationDictionary.Values) { Visualization v1 = item.GetComponent <LinkedVisualisations>().V1; Visualization v2 = item.GetComponent <LinkedVisualisations>().V2; if (v1 == null || v2 == null || Vector3.Distance(v1.transform.position, v2.transform.position) > PCP_DISTANCE + 0.05f) { toDestroy.Add(item.name); } } //cleaning linked visualsiations foreach (var item in toDestroy) { GameObject lvv = linkedVisualisationDictionary[item]; linkedVisualisationDictionary.Remove(lvv.name); Visualization v1 = lvv.GetComponent <LinkedVisualisations>().V1; Visualization v2 = lvv.GetComponent <LinkedVisualisations>().V2; foreach (var ax1 in v1.axes) { ax1.isDirty = true; } foreach (var ax2 in v2.axes) { ax2.isDirty = true; } if (v1 != null && v1.viewType == Visualization.ViewType.Histogram) { //only show if not used in other linked visualizations if (linkedVisualisationDictionary.Values.None(x => x.GetComponent <LinkedVisualisations>().Contains(v1.axes[0]))) { v1.ShowHistogram(true); } } if (v2.viewType == Visualization.ViewType.Histogram && v2 != null) { if (linkedVisualisationDictionary.Values.None(x => x.GetComponent <LinkedVisualisations>().Contains(v2.axes[0]))) { v2.ShowHistogram(true); } } Destroy(lvv); } //display all sp symbols on the debug panel string grammarSymbols = "SP1: " + SP.Count(x => x.viewType == Visualization.ViewType.Histogram) + "\n" + "SP2: " + SP.Count(x => x.viewType == Visualization.ViewType.Scatterplot2D) + "\n" + "SP3: " + SP.Count(x => x.viewType == Visualization.ViewType.Scatterplot3D) + "\n" // + "SP2_SPLOM: " + SPLOMS2D.Count + "\n" + "SP3_SPLOM: " + SPLOMS3D.Count + "\n"; }
void Update3DSPLOM(ref List <Visualization> listOfVisualisations) { for (int i = 0; i < XAxes.Count; i++) { for (int j = 0; j < YAxes.Count; j++) { if (baseVisualization.viewType == Visualization.ViewType.Scatterplot3D) { for (int k = 0; k < ZAxes.Count; k++) { if (THE3DSPLOM[i, j, k] == null) { GameObject cloneX = XAxes[i].Clone(); GameObject cloneY = YAxes[j].Clone(); GameObject cloneZ = ZAxes[k].Clone(); float vectorLength = XAxes[i].transform.localScale.y; cloneX.transform.position = XAxes[0].transform.position + YAxes[0].transform.up * vectorLength * j + XAxes[0].transform.up * vectorLength * i + ZAxes[0].transform.up * vectorLength * k; cloneY.transform.position = YAxes[0].transform.position + YAxes[0].transform.up * vectorLength * j + XAxes[0].transform.up * vectorLength * i + ZAxes[0].transform.up * vectorLength * k; cloneZ.transform.position = ZAxes[0].transform.position + YAxes[0].transform.up * vectorLength * j + XAxes[0].transform.up * vectorLength * i + ZAxes[0].transform.up * vectorLength * k; cloneX.transform.rotation = XAxes[0].transform.rotation; cloneY.transform.rotation = YAxes[0].transform.rotation; cloneZ.transform.rotation = ZAxes[0].transform.rotation; GameObject visObj = Instantiate(visualizationPrefab); Visualization vis = visObj.GetComponent <Visualization>(); vis.axes.Clear(); vis.IsSPLOMElement = true; vis.TheSPLOMReference = this.gameObject; //enable SPLOM linking listOfVisualisations.Add(vis); vis.AddAxis(cloneX.GetComponent <Axis>()); vis.AddAxis(cloneY.GetComponent <Axis>()); vis.AddAxis(cloneZ.GetComponent <Axis>()); cloneX.GetComponent <Axis>().Ghost(XAxes[i]); cloneY.GetComponent <Axis>().Ghost(YAxes[j]); cloneZ.GetComponent <Axis>().Ghost(ZAxes[k]); THE3DSPLOM[i, j, k] = vis; splomVisualizations.Add(vis); Tuple <int, int, int> indexInsplom = new Tuple <int, int, int>(i, j, k); if (!ghostAxes.ContainsKey(indexInsplom)) { ghostAxes.Add(indexInsplom, new List <GameObject>(new GameObject[] { cloneX, cloneY, cloneZ })); } } } } else { if (THE3DSPLOM[i, j, 0] == null) { GameObject cloneX = XAxes[i].Clone(); GameObject cloneY = YAxes[j].Clone(); float vectorLength = XAxes[i].transform.localScale.y; cloneX.transform.position = XAxes[0].transform.position + YAxes[0].transform.up * (vectorLength) * ((float)j) + XAxes[0].transform.up * (vectorLength) * ((float)i); cloneY.transform.position = YAxes[0].transform.position + YAxes[0].transform.up * (vectorLength) * ((float)j) + XAxes[0].transform.up * (vectorLength) * ((float)i); cloneX.transform.rotation = XAxes[0].transform.rotation; cloneY.transform.rotation = YAxes[0].transform.rotation; GameObject visObj = Instantiate(visualizationPrefab); Visualization vis = visObj.GetComponent <Visualization>(); vis.axes.Clear(); vis.IsSPLOMElement = true; vis.TheSPLOMReference = this.gameObject; //enable SPLOM linking listOfVisualisations.Add(vis); vis.AddAxis(cloneX.GetComponent <Axis>()); vis.AddAxis(cloneY.GetComponent <Axis>()); cloneX.GetComponent <Axis>().Ghost(XAxes[i]); cloneY.GetComponent <Axis>().Ghost(YAxes[j]); THE3DSPLOM[i, j, 0] = vis; splomVisualizations.Add(vis); Tuple <int, int, int> indexInsplom = new Tuple <int, int, int>(i, j, 0); if (!ghostAxes.ContainsKey(indexInsplom)) { ghostAxes.Add(indexInsplom, new List <GameObject>(new GameObject[] { cloneX, cloneY })); } } } // end if } // end for j } // end for i }