using System.Collections; using System.Collections.Generic; using System.Net.Http.Headers; using TMPro; using UnityEngine; public class CrossManager : BackButton { [SerializeField] GraphManager graphManager; [SerializeField] GameObject graphs; [SerializeField] TextMeshPro[] crossTexts; [SerializeField] GameObject crossOptionMenu; [SerializeField] GameObject nonCrossOptionMenu; private GraphData[] graphDatas; //private Material[] materials; マテリアルの保存...未実装 private GraphData[] crossGraphDatas = new GraphData[3]; public void updateGraphDatas(GraphData[] graphDatas) { this.graphDatas = graphDatas; } //呼ばれたら全て新しくする public void crossChecker(GraphData[] graphDatas) { foreach (TextMeshPro tm in crossTexts) { tm.text = ""; } foreach (GraphData cross in crossGraphDatas) { if (cross != null) { if (cross.getgraphObject() != null) { Destroy(cross.getgraphObject()); } } } crossGraphDatas = new GraphData[3]; updateGraphDatas(graphDatas); int numberOfGraphObjcet = 0; foreach (GraphData data in graphDatas) { if(data != null) { if (data.isDataListInputted()) { numberOfGraphObjcet++; } } } switch (numberOfGraphObjcet) { case 0: //データ数0こ case 1: //データ数1こ break; case 2: //データ数2こ,index = 0,1 crossGraphDatas[0] = crossCalculate(graphDatas[0], graphDatas[1]); setCrossText(crossGraphDatas[0],0); break; case 3: //データ数3こ, index = 0,1,2 crossGraphDatas[0] = crossCalculate(graphDatas[0], graphDatas[1]); crossGraphDatas[1] = crossCalculate(graphDatas[0], graphDatas[2]); crossGraphDatas[2] = crossCalculate(graphDatas[1], graphDatas[2]); for(int i = 0;i < 3; i++) { setCrossText(crossGraphDatas[i],i); } break; } } private void setCrossText(GraphData data,int index) { crossTexts[index].fontSize = 0.06f; switch (data.getGraphNum()) { case 0: //直線 switch (data.getCrossMessage() % 10) { case 0: //交線あり crossTexts[index].text = "点(" + data.getLinePassingPoint().x + " ," + data.getLinePassingPoint().y + " ," + data.getLinePassingPoint().z + ")を通る" + "\nベクトル(" + data.getLineDirection().x + " ," + data.getLineDirection().y + " ," + data.getLineDirection().z + ")に平行な直線"; crossTexts[index].fontSize = 0.06f; break; case 1: //平行 crossTexts[index].text = "平行"; break; case 2: //全く同じ平面 crossTexts[index].text = "同一の平面"; break; } break; case 3: //点 switch (data.getCrossMessage() % 10) { case 0: //交点あり crossTexts[index].text = "点("+data.getCrossPoint().x +", "+data.getCrossPoint().y+", "+data.getCrossPoint().z+")"; break; case 1: crossTexts[index].text = "平行"; break; case 2: crossTexts[index].text = "同一の直線"; break; case 4: if(data.getCrossMessage()/10 == 1) { crossTexts[index].text = "ねじれの位置"; } else { crossTexts[index].text = "平面上の直線"; } break; } break; } } private GraphData crossCalculate(GraphData data1,GraphData data2) { GraphData newerData = new GraphData(); switch (data1.getGraphNum() + data2.getGraphNum()) { case 0: //直線と直線 -> 点 newerData = crossLineLineCalculate(data1, data2); break; case 1: //直線と平面 -> 点 switch (data1.getGraphNum()) { case 0: //data1が直線 newerData = crossLinePlaneCalculate(data1, data2); break; case 1: //data2が平面 newerData = crossLinePlaneCalculate(data2, data1); break; } break; case 2: //平面と平面 -> 直線 newerData = crossPlanePlaneCalculate(data1, data2); break; } return newerData; } private GraphData crossLineLineCalculate(GraphData l1, GraphData l2) { GraphData point = new GraphData(); Vector3 outer = Vector3.Cross(l1.getLineDirection(), l2.getLineDirection()); Vector3 l1p = l1.getLinePassingPoint(); Vector3 l1d = l1.getLineDirection(); Vector3 l2p = l2.getLinePassingPoint(); Vector3 l2d = l2.getLineDirection(); ; //媒介変数 float s = 0; float t = 0; point.setGraphNum(3); if (outer.z == 0) //x,y成分が平行 { if(outer.x == 0)//y,z成分が平行 { /*この時点でx,y,z成分が平行 * ->同じ直線の可能性。もしくは * 平行で交点なし(ねじれの位置ではない) */ //同じ直線かどうか -> l2の通過点をl1が通るかで判断 if (l1d.x != 0) //x方向が0でない { t = (l2p.x - l1p.x)/l1d.x; if ((l1p.y + t * l1d.y) == l2p.y) { if ((l1p.z + t * l1d.z) == l2p.z) { //通過点をもう片方が通る point.setCrossMessage(12); return point; } } //平行でした point.setCrossMessage(11); return point; } else if (l1d.y != 0) //x方向が0で、y方向が0でない { //xの通過点を比較 if (l1p.x != l2p.x) { point.setCrossMessage(11); return point; } t = (l2p.y - l1p.y) / l1d.y; if ((l1p.x + t * l1d.x) == l2p.x) { if ((l1p.z + t * l1d.z) == l2p.z) { //通過点をもう片方が通る point.setCrossMessage(12); return point; } } //平行でした point.setCrossMessage(11); return point; } else //z方向が0でない { //xの通過点を比較 if (l1p.x != l2p.x) { point.setCrossMessage(11); return point; } //yの通過点を比較 if (l1p.y != l2p.y) { point.setCrossMessage(11); return point; } t = (l2p.z - l1p.z) / l1d.z; if ((l1p.y + t * l1d.y) == l2p.y) { if ((l1p.x + t * l1d.x) == l2p.x) { //通過点をもう片方が通る point.setCrossMessage(12); return point; } } //平行でした point.setCrossMessage(11); } //3成分が平行の際の結果 return point; } /* x,y平面上でピッタリ重なっていなければ交わることはない */ //ピッタリ重なるのか if (isLine1OverlapLine2(new Vector2(l1p.x,l1p.y), new Vector2(l1d.x, l1d.y), new Vector2(l2p.x, l2p.y), new Vector2(l2d.x, l2d.y))) { //必ず交点をもつ(平行処理は既実施) t = (l1d.z * (l1p.y - l2p.y) - l1d.y * (l1p.z - l2p.z))/(l1d.z*l2d.y-l1d.y*l2d.z); point.setCrossPoint(l2p + t*l2d); point.setCrossMessage(10); } else { point.setCrossMessage(14); return point; } } else if(outer.x == 0) //x,y成分は平行ではないが、y,z成分は平行 { /*y,z平面上で重なっていなければ交わることはない */ //ピッタリ重なるのか if (isLine1OverlapLine2(new Vector2(l1p.y, l1p.z), new Vector2(l1d.y, l1d.z), new Vector2(l2p.y, l2p.z), new Vector2(l2d.y, l2d.z))) { //必ず交点をもつ t = (l1d.x * (l1p.y - l2p.y) - l1d.y * (l1p.x - l2p.x)) / (l1d.x * l2d.y - l1d.y * l2d.x); point.setCrossPoint(l2p + t * l2d); point.setCrossMessage(10); } else { point.setCrossMessage(14); return point; } } else //全て平行ではない -> 媒介変数ごり押し計算 { //x,y成分にて s = (l2d.x * (l1p.y - l2p.y) - l2d.y * (l1p.x - l2p.x)) / (l1d.x * l2d.y - l1d.y * l2d.x); t = (l1d.x * (l1p.y - l2p.y) - l1d.y * (l1p.x - l2p.x)) / (l1d.x * l2d.y - l1d.y * l2d.x); //z成分の左辺、右辺で判断 if ((l1p.z + s*l1d.z)==(l2p.z + t*l2d.z)) { //媒介変数を入れた点が左右で一致 point.setCrossPoint(l1p + s*l1d); point.setCrossMessage(10); } else { point.setCrossMessage(14); return point; } } point.setDataFormulaInputted(true); GameObject g = GameObject.CreatePrimitive(PrimitiveType.Sphere); g.transform.parent = graphs.transform; g.transform.localPosition = point.getCrossPoint(); g.transform.localScale = new Vector3(0.03f, 0.03f, 0.03f); Material m = g.GetComponent<MeshRenderer>().material; m.color = new Color(1, 0, 0, 1); point.setGraphObject(g); return point; } //平行な2直線がピッタリ重なるのか private bool isLine1OverlapLine2(Vector2 l1p,Vector2 l1d, Vector2 l2p, Vector2 l2d) { bool b = false; if (l1d.x == 0) { if(l1p.x == l2p.x) { b = true; } } else { float yIntercept1 = l1p.y - (l1p.y * l1d.y) / l1d.x; float yIntercept2 = l2p.y - (l2p.y * l2d.y) / l2d.x; if(yIntercept1 == yIntercept2) { b = true; } } return b; } private GraphData crossLinePlaneCalculate(GraphData l,GraphData p) { GraphData point = new GraphData(); Vector3 p3v = new Vector3(p.getPlaneCoefficient().x, p.getPlaneCoefficient().y, p.getPlaneCoefficient().z); point.setGraphNum(3); //平行か->方向ベクトル、法線ベクトルの内積が0 if (Vector3.Dot(l.getLineDirection(),p3v) == 0) { point.setCrossMessage(21); float d = l.getLinePassingPoint().x * p3v.x + l.getLinePassingPoint().y * p3v.y + l.getLinePassingPoint().z * p3v.z; //同一平面上か if(d == -p.getPlaneCoefficient().w) { point.setCrossMessage(23); } return point; } Vector3 lp = l.getLinePassingPoint(); Vector3 ld = l.getLineDirection(); float uUpper = p3v.x * lp.x + p3v.y * lp.y + p3v.z * lp.z + p.getPlaneCoefficient().w; float uLower = p3v.x * ld.x + p3v.y * ld.y + p3v.z * ld.z; float u = 1; if (uLower != 0) { u = -uUpper / uLower; } else { Debug.Log("内積が0処理ミスエラー"); return null; } point.setCrossPoint(u * ld + lp); point.setGraphNum(3); point.setDataFormulaInputted(true); point.setCrossMessage(20); GameObject s = GameObject.CreatePrimitive(PrimitiveType.Sphere); s.transform.parent = graphs.transform; s.transform.localPosition = point.getCrossPoint(); s.transform.localScale = new Vector3(0.03f,0.03f,0.03f); Material m = s.GetComponent<MeshRenderer>().material; m.color = new Color(1, 0, 0, 1); point.setGraphObject(s); return point; } private GraphData crossPlanePlaneCalculate(GraphData plane1, GraphData plane2) { GraphData line = new GraphData(); Vector4 p1 = plane1.getPlaneCoefficient(); Vector4 p2 = plane2.getPlaneCoefficient(); Vector3 p1v3 = new Vector3(p1.x, p1.y,p1.z); Vector3 p2v3 = new Vector3(p2.x, p2.y, p2.z); line.setGraphNum(0); //位置関係判断 if (Vector3.Cross(p1v3,p2v3) == Vector3.zero) { if (p1.w == p2.w) { line.setCrossMessage(32); } else { line.setCrossMessage(31); } return line; } float ab = p1.x * p2.y - p1.y * p2.x; float bc = p1.y * p2.z - p1.z * p2.y; float ca = p1.z * p2.x - p1.x * p2.z; float ad = p1.x * p2.w - p1.w * p2.x; float bd = p1.y * p2.w - p1.w * p2.y; float cd = p1.z * p2.w - p1.w * p2.z; if(ca != 0) { line.setLinePassingPoint(new Vector3(-cd / ca, 0, ad / ca)); line.setCrossMessage(30); } else if (ab != 0) { line.setLinePassingPoint(new Vector3(bd / ab, -ad / ab, 0)); line.setCrossMessage(30); } line.setLineDirection(Vector3.Cross(p1v3, p2v3)); line.setGraphNum(0); line.setDataFormulaInputted(true); Vector3 inLinePoint = new Vector3(); GameObject ln = GameObject.CreatePrimitive(PrimitiveType.Cylinder); ln.transform.parent = graphs.transform; if (line.getLineDirection().y != 0) { float uY0 = -1 * line.getLinePassingPoint().y / line.getLineDirection().y; inLinePoint = new Vector3( line.getLinePassingPoint().x + uY0 * line.getLineDirection().x, 0, line.getLinePassingPoint().z + uY0 * line.getLineDirection().z); } else if (line.getLineDirection().x != 0) { float uX0 = -1 * line.getLinePassingPoint().x / line.getLineDirection().x; inLinePoint = new Vector3( 0, line.getLinePassingPoint().y + uX0 * line.getLineDirection().y, line.getLinePassingPoint().z + uX0 * line.getLineDirection().z); } else if (line.getLineDirection().z != 0) { float uZ0 = -1 * line.getLinePassingPoint().z / line.getLineDirection().z; inLinePoint = new Vector3( line.getLinePassingPoint().x + uZ0 * line.getLineDirection().x, line.getLinePassingPoint().y + uZ0 * line.getLineDirection().y, 0); } else { //全て0の場合 //たぶんない。処理済みなはず Debug.Log("係数が無効です"); return null; } ln.transform.localRotation = Quaternion.FromToRotation(Vector3.up, line.getLineDirection()); ln.transform.localPosition = inLinePoint; ln.transform.localScale = new Vector3(0.01f, 20, 0.01f); Material m = ln.GetComponent<MeshRenderer>().material; m.color = new Color(1, 0, 0, 1); line.setGraphObject(ln); return line; } public void pressedButton(int i) { if (crossGraphDatas[i] != null) { if (crossGraphDatas[i].isDataFormulaInputted()) { switch (i) { case 0: crossOptionMenu.SetActive(true); crossOptionMenu.GetComponent<CrossOptionMenu>().Initialize(crossGraphDatas[i], graphDatas[0], graphDatas[1]); base.anotherButtonAction(); break; case 1: crossOptionMenu.SetActive(true); crossOptionMenu.GetComponent<CrossOptionMenu>().Initialize(crossGraphDatas[i], graphDatas[0], graphDatas[2]); base.anotherButtonAction(); break; case 2: crossOptionMenu.SetActive(true); crossOptionMenu.GetComponent<CrossOptionMenu>().Initialize(crossGraphDatas[i], graphDatas[1], graphDatas[2]); base.anotherButtonAction(); break; } } else { switch (i) { case 0: nonCrossOptionMenu.SetActive(true); nonCrossOptionMenu.GetComponent<NonCrossOptionMenu>().Initialize(crossGraphDatas[i], graphDatas[0], graphDatas[1]); base.anotherButtonAction(); break; case 1: nonCrossOptionMenu.SetActive(true); nonCrossOptionMenu.GetComponent<NonCrossOptionMenu>().Initialize(crossGraphDatas[i], graphDatas[0], graphDatas[2]); base.anotherButtonAction(); break; case 2: nonCrossOptionMenu.SetActive(true); nonCrossOptionMenu.GetComponent<NonCrossOptionMenu>().Initialize(crossGraphDatas[i], graphDatas[1], graphDatas[2]); base.anotherButtonAction(); break; } } } } }