### Voronoi Joint

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using VRTK;

//Set to Template option

public class Voronoi_Joint : MonoBehaviour
{
public enum GEOMETRY
{
TETRA,
OCTA,
};

public GEOMETRY geo = GEOMETRY.TETRA;

public GameObject[] centerRbs = new GameObject[6];//4
public GameObject[] connected_Joints = new GameObject[6];//4
private Vector3[] cj_12_EndPoints = new Vector3[12];
private Vector3[] cj_24_EndPoints = new Vector3[24];

private Vector3 startPosition;

//private int[,] vN_Points_to;

private Six_Splines    six_splines;
private Twelve_Splines twelve_Splines;

public bool bPrint_Debug = false;

public Button_VU bvToggle_Hi_Res;

/// <image url="$(SolutionDir)\EMB\EMB_Edge_Vert.png" scale="0.36" /> /// <image url="$(SolutionDir)\EMB\EMB_Edge_Vert_2.png" scale="0.1" />

public float outerforceMag = 10;
public float centering_Mult = 1;
public float torque_Coefficient = 1f;
private VRTK_InteractableObject vrtk_Interact_1;

public enum Handle_States
{
NORMAL,
TOUCHED,
GRABBED,
}

private Handle_States handle_State = Handle_States.NORMAL;

public Color handle_Base_Col;
public Color handle_Touched_Col;
public Color handle_Grabbed_Col;
private Color handle_Base_Emissive_Col;

private VU_UI_MANAGER VU_UI;

public bool bUsePhysics = true;
public bool bSetTetraPositions = false;
public GameObject TetraVoronoi;

void Start()
{
startPosition = transform.position;

bvToggle_Hi_Res.isON = false;

vrtk_Interact_1 = GetComponent<VRTK_InteractableObject>();
VU_UI = VU_UI_MANAGER.Instance;

if (geo == GEOMETRY.TETRA)
{
six_splines = GetComponentInChildren<Six_Splines>();
six_splines.Set_CJ_0_GO(connected_Joints[0]);//For OutII
}
else if(geo == GEOMETRY.OCTA)
{
twelve_Splines = GetComponentInChildren<Twelve_Splines>();
}

vrtk_Interact_1.InteractableObjectTouched += new InteractableObjectEventHandler(DoObject_1_Touched);
vrtk_Interact_1.InteractableObjectUntouched += new InteractableObjectEventHandler(DoObject_1_Untouched);

vrtk_Interact_1.InteractableObjectGrabbed += new InteractableObjectEventHandler(DoObject_1_Grabbed);
vrtk_Interact_1.InteractableObjectUngrabbed += new InteractableObjectEventHandler(DoObject_1_Ungrabbed);

if (!bUsePhysics)
{
Rigidbody[] rbs = GetComponentsInChildren<Rigidbody>();
foreach(Rigidbody rb in rbs)
{
rb.isKinematic = true;
}

for (int i = 0; i < centerRbs.Length; i++)
{
centerRbs[i].GetComponent<Rigidbody>().isKinematic = true;
centerRbs[i].GetComponent<ConfigurableJoint>().enablePreprocessing = false;
connected_Joints[i].GetComponent<Rigidbody>().isKinematic = true;
}
}
if(bSetTetraPositions)
{
Voronoi_Joint vj = TetraVoronoi.GetComponent<Voronoi_Joint>();

Vector3 thisBasePosition = transform.position;

float edgeLength = (connected_Joints[0].transform.position - connected_Joints[1].transform.position).magnitude;

Vector3 vfaceCenter = ( connected_Joints[0].transform.localPosition +
connected_Joints[1].transform.localPosition +
connected_Joints[2].transform.localPosition) / 3f;

Vector3 vDir = vfaceCenter.normalized;

float tetraHeight = edgeLength * Mathf.Sqrt(0.666666667f);

TetraVoronoi.transform.position = transform.position + vfaceCenter + vDir * edgeLength * Mathf.Sqrt(6) / 12f;

Vector3[] vTetraPos = new Vector3[4];

vTetraPos[0] = connected_Joints[0].transform.position;
vTetraPos[1] = connected_Joints[1].transform.position;
vTetraPos[2] = connected_Joints[2].transform.position;
vTetraPos[3] = thisBasePosition + vfaceCenter + vDir*edgeLength*Mathf.Sqrt(6)/3;

vj.SetPositions(ref vTetraPos);
}
}

public void SetPositions(ref Vector3[] positions)
{
for(int i = 0; i < connected_Joints.Length; i++)
{
connected_Joints[i].transform.position = positions[i];
}
}

private void DoObject_1_Touched(object sender, InteractableObjectEventArgs e)
{
handle_State = Handle_States.TOUCHED;
VU_UI.Report_Touched(vrtk_Interact_1.gameObject, e.interactingObject);
}

private void DoObject_1_Untouched(object sender, InteractableObjectEventArgs e)
{
handle_State = Handle_States.NORMAL;
VU_UI.Report_UnTouched(vrtk_Interact_1.gameObject, e.interactingObject);
}

private void DoObject_1_Grabbed(object sender, InteractableObjectEventArgs e)
{
handle_State = Handle_States.GRABBED;
}

private void DoObject_1_Ungrabbed(object sender, InteractableObjectEventArgs e)
{
handle_State = Handle_States.NORMAL;
}

private bool isValid_Vector(Vector3 v)
{
if (!float.IsNaN(v.x) && !float.IsNaN(v.y) && !float.IsNaN(v.z))
{
return true;
}
else
{
return false;
}
}

public void Return_To_Start_Position()
{
transform.position = startPosition;
}

void FixedUpdate()
{
if (bUsePhysics)
{
for (int j = 0; j < connected_Joints.Length; j++)
{
Vector3 vA = connected_Joints[j].transform.right;
GameObject gAlign = connected_Joints[0];

//subtract y component to get projection on current XZ plane
float yDot = Vector3.Dot(connected_Joints[j].transform.up, gAlign.transform.up);
Vector3 yProjected = gAlign.transform.up + yDot * gAlign.transform.up;

float torque = torque_Coefficient * Vector3.Dot(yProjected, connected_Joints[j].transform.forward);
Rigidbody rbc = connected_Joints[j].GetComponent<Rigidbody>();
}

//Distribute around sphere - Voronoi Action
foreach (GameObject go in connected_Joints)
{
Rigidbody rb = go.GetComponent<Rigidbody>();
Rigidbody rbInner;
Vector3 vFrom;
Vector3 vSum;
Vector3 vRecip;

foreach (GameObject gInner in connected_Joints)
{
vSum = Vector3.zero;

if (go != gInner)
{
rbInner = gInner.GetComponent<Rigidbody>();
vFrom = rb.position - rbInner.position;
r = vFrom.magnitude;
vRecip = (1f / r) * vFrom.normalized;
vSum += vRecip;
}
if (isValid_Vector(vSum))
{
}
}
}
//Pull centerRbs into Center of Sphere
Vector3 vDiff;
foreach (GameObject gCent in centerRbs)
{
Rigidbody rb = gCent.GetComponent<Rigidbody>();
vDiff = transform.position - rb.position;

rb.velocity = vDiff / Time.fixedDeltaTime;
}

if (bPrint_Debug)
{
//for (int i = 0; i < 4; i++)
//{
//    for (int j = 0; j < 3; j++)
//    {
//        print("VN_[" + i.ToString() + "," + j.ToString() + "] points to " + vN_Points_to[i, j].ToString());
//    }
//}
bPrint_Debug = false;
}
}
}

Color curr_Color;
Color curr_dot_Color;
Color targ_Color;
Color targ_dot_Color;

float theta = 390;
float target_theta = 0;

public void Animate_Handle_Material()//UI HANDLE
{
curr_Color = Color.Lerp(curr_Color, targ_Color, Time.deltaTime * 1.61803f);
curr_dot_Color = Color.Lerp(curr_dot_Color, targ_dot_Color, Time.deltaTime * 1.61803f);

if (handle_State == Handle_States.NORMAL)
{
//target_theta = 300;
targ_Color = handle_Base_Col;

}
else if (handle_State == Handle_States.TOUCHED)
{
//target_theta = 390;
targ_Color = handle_Touched_Col;
}
else if (handle_State == Handle_States.GRABBED)
{
//target_theta = 570;
targ_Color = handle_Grabbed_Col;

}
Renderer rend = GetComponent<Renderer>();
rend.material.SetColor("_Color", curr_Color);
rend.material.SetColor("_EmissionColor", curr_Color);
}

public void Toggle_Hi_Res_From_Voronoi()
{
bvToggle_Hi_Res.isON = !bvToggle_Hi_Res.isON;
six_splines = TetraVoronoi.GetComponentInChildren<Six_Splines>();
six_splines.Set_Hi_Res(bvToggle_Hi_Res.isON);
twelve_Splines.Set_Hi_Res(bvToggle_Hi_Res.isON);
}

private void Update()
{
//Animate_Handle_Material();
if (geo == GEOMETRY.TETRA)
{
cj_12_EndPoints[0] = connected_Joints[0].transform.localPosition;
cj_12_EndPoints[1] = connected_Joints[1].transform.localPosition;
cj_12_EndPoints[2] = connected_Joints[0].transform.localPosition;
cj_12_EndPoints[3] = connected_Joints[2].transform.localPosition;
cj_12_EndPoints[4] = connected_Joints[0].transform.localPosition;
cj_12_EndPoints[5] = connected_Joints[3].transform.localPosition;

cj_12_EndPoints[6] = connected_Joints[1].transform.localPosition;
cj_12_EndPoints[7] = connected_Joints[2].transform.localPosition;
cj_12_EndPoints[8] = connected_Joints[1].transform.localPosition;
cj_12_EndPoints[9] = connected_Joints[3].transform.localPosition;
cj_12_EndPoints[10] = connected_Joints[2].transform.localPosition;
cj_12_EndPoints[11] = connected_Joints[3].transform.localPosition;

six_splines.Generate_Splines(cj_12_EndPoints, transform.position);
}
else if(geo == GEOMETRY.OCTA)
{
cj_24_EndPoints[0] = connected_Joints[0].transform.localPosition;
cj_24_EndPoints[1] = connected_Joints[1].transform.localPosition;
cj_24_EndPoints[2] = connected_Joints[0].transform.localPosition;
cj_24_EndPoints[3] = connected_Joints[2].transform.localPosition;

cj_24_EndPoints[4] = connected_Joints[0].transform.localPosition;
cj_24_EndPoints[5] = connected_Joints[3].transform.localPosition;
cj_24_EndPoints[6] = connected_Joints[0].transform.localPosition;
cj_24_EndPoints[7] = connected_Joints[4].transform.localPosition;

cj_24_EndPoints[8] = connected_Joints[1].transform.localPosition;
cj_24_EndPoints[9] = connected_Joints[2].transform.localPosition;
cj_24_EndPoints[10] = connected_Joints[1].transform.localPosition;
cj_24_EndPoints[11] = connected_Joints[5].transform.localPosition;

cj_24_EndPoints[12] = connected_Joints[1].transform.localPosition;
cj_24_EndPoints[13] = connected_Joints[4].transform.localPosition;
cj_24_EndPoints[14] = connected_Joints[2].transform.localPosition;
cj_24_EndPoints[15] = connected_Joints[5].transform.localPosition;

cj_24_EndPoints[16] = connected_Joints[2].transform.localPosition;
cj_24_EndPoints[17] = connected_Joints[3].transform.localPosition;
cj_24_EndPoints[18] = connected_Joints[3].transform.localPosition;
cj_24_EndPoints[19] = connected_Joints[5].transform.localPosition;

cj_24_EndPoints[20] = connected_Joints[3].transform.localPosition;
cj_24_EndPoints[21] = connected_Joints[4].transform.localPosition;
cj_24_EndPoints[22] = connected_Joints[4].transform.localPosition;
cj_24_EndPoints[23] = connected_Joints[5].transform.localPosition;

twelve_Splines.Generate_Splines(cj_24_EndPoints, transform.position);
}
}
}

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using ProceduralToolkit;
using VRTK;
using UnityEngine.UI;
using VRTK.GrabAttachMechanics;

public class Six_Splines : MonoBehaviour
{
public Face_Tetra faces;
public GameObject test_Octahedron;

public GameObject Horn_Handle_Prefab;
private GameObject[] tangent_Handles = new GameObject[14];
[Range(0, 100f)]
public  float scale_tangent_Handles = 27f;
private bool  bEdge_Rotation_On = false;
private float edge_Angular_Rate = 0f;
public Slider sld_Edge_Angular_Rate;
private bool bHandles_On = true;
public Button_VU bvAngular_On;

private GameObject go_cj_0;

public Button_VU[] bvEdge_Switches;

private bool[] bEdge_Switch = new bool[6];

public Button_VU bvHorns_Handles_On;

public Slider sld_Tangent;
public Slider sld_Extend;

public float tan_Slide_Val = 0;
public float extend_Slide_Val = 0;

public bool bHi_Res_On = false;
public bool bRun_Once = false;

public Button_VU bv_Outii; //One Face Opposite Tangents

public Vector3[] tetra_Edges = new Vector3[12]; //edge 0 -> 0,1 | edge 1 -> 2-3 etc.

private VRTK_InteractableObject interact;

private ArgosMeshDraft aMD_Spline_Green;
private ArgosMeshDraft aMD_Spline_Red;
private ArgosMeshDraft aMD_Spline_Blue;
private ArgosMeshDraft aMD_Spline_Yellow;
private ArgosMeshDraft aMD_Spline_Orange;
private ArgosMeshDraft aMD_Spline_Violet;

private ArgosMeshDraft aMD_Spline_Cross;

public GameObject spline_Green;
public GameObject spline_Red;
public GameObject spline_Blue;
public GameObject spline_Yellow;
public GameObject spline_Orange;
public GameObject spline_Violet;

public GameObject spline_Cross;

public float[] spline_lens_Green  = new float[256];
public float[] spline_lens_Red    = new float[256];
public float[] spline_lens_Blue   = new float[256];
public float[] spline_lens_Yellow = new float[256];
public float[] spline_lens_Orange = new float[256];
public float[] spline_lens_Violet = new float[256];

public float[] spline_lens_Cross = new float[256];

private List<Vector3> lst_SplineGreen  = new List<Vector3>();
private List<Vector3> lst_SplineRed    = new List<Vector3>();
private List<Vector3> lst_SplineBlue   = new List<Vector3>();
private List<Vector3> lst_SplineYellow = new List<Vector3>();
private List<Vector3> lst_SplineOrange = new List<Vector3>();
private List<Vector3> lst_SplineViolet = new List<Vector3>();

//private List<Vector3> lst_SplineCross = new List<Vector3>();

private Vector3 p0_1, p0_2;
private Vector3 p1_1, p1_2;
private Vector3 p2_1, p2_2;
private Vector3 p3_1, p3_2;
private Vector3 p4_1, p4_2;
private Vector3 p5_1, p5_2;

[Range(0, 0.5f)]

[Range(-20, 20f)]
public float tangent_Mag = 1f;

[Range(-20, 20f)]

public bool bUpdate = false;
public bool bTangents_From_Octahedron = false;
public Twelve_Splines twelve_Splines;

private VU_UI_MANAGER VU_UI;

void Start ()
{
bv_Outii.isON = false;

//tan_Slide_Val = sld_Tangent.value;
//extend_Slide_Val = sld_Extend.value;
//edge_Angular_Rate = sld_Edge_Angular_Rate.value;

for (int i = 0; i<6; i++)
{
bEdge_Switch[i] = false;
}

VU_UI = VU_UI_MANAGER.Instance;

aMD_Spline_Green  = new ArgosMeshDraft();
aMD_Spline_Red    = new ArgosMeshDraft();
aMD_Spline_Blue   = new ArgosMeshDraft();
aMD_Spline_Yellow = new ArgosMeshDraft();
aMD_Spline_Orange = new ArgosMeshDraft();
aMD_Spline_Violet = new ArgosMeshDraft();

aMD_Spline_Cross = new ArgosMeshDraft();

//Generate_Splines();

spline_Green.GetComponent<MeshFilter>().mesh.MarkDynamic();
spline_Red.GetComponent<MeshFilter>().mesh.MarkDynamic();
spline_Blue.GetComponent<MeshFilter>().mesh.MarkDynamic();
spline_Yellow.GetComponent<MeshFilter>().mesh.MarkDynamic();
spline_Orange.GetComponent<MeshFilter>().mesh.MarkDynamic();
spline_Violet.GetComponent<MeshFilter>().mesh.MarkDynamic();

spline_Cross.GetComponent<MeshFilter>().mesh.MarkDynamic();

for (int i = 0; i < 12; i++)
{
tangent_Handles[i] = Instantiate(Horn_Handle_Prefab);
tangent_Handles[i].transform.localPosition = Vector3.zero;
tangent_Handles[i].transform.localRotation = Quaternion.identity;

if (!GetComponentInParent<Voronoi_Joint>().bUsePhysics)
{
tangent_Handles[i].GetComponent<Rigidbody>().isKinematic = true;
}
}
for (int i = 0; i < 12; i++)
{
if (i % 2 == 0)
{
tangent_Handles[i].GetComponent<Handle_Tangent_Interact>().Set_Dual(tangent_Handles[i + 1].GetComponent<Handle_Tangent_Interact>());
}
else
{
tangent_Handles[i].GetComponent<Handle_Tangent_Interact>().Set_Dual(tangent_Handles[i - 1].GetComponent<Handle_Tangent_Interact>());
}
}
}

public void Set_CJ_0_GO(GameObject cj_0_go)
{
go_cj_0 = cj_0_go;
}

public void Show_Handles(bool bON)
{
for (int i = 0; i < 14; i++)
{
tangent_Handles[i].SetActive(bON);
}
}

//public Slider sld_Tangent;
//public Slider sld_Extend;

public void onSld_Tangent()
{
tan_Slide_Val = sld_Tangent.value;
}

public void onSld_Extend()
{
extend_Slide_Val = sld_Extend.value;
}

public void Set_Hi_Res(bool bON)
{
bHi_Res_On = bON;
faces.Set_Hi_Res(bON);
bRun_Once = bON;
}

public void onBV_Outii()
{
bv_Outii.isON = !bv_Outii.isON;
}

public void On_Edge_Switch_BV(int i)
{
bEdge_Switch[i] = !bEdge_Switch[i];
if(bvEdge_Switches[0] != null)
{
bvEdge_Switches[i].isON = bEdge_Switch[i];
}
}

public void onSld_Cross_Tangent()
{
tan_Slide_Val = sld_Tangent.value;
}

public void onSld_Cross_Extend()
{
extend_Slide_Val = sld_Extend.value;
}

public void On_Edge_Angular_Rotation_sld()
{
edge_Angular_Rate = sld_Edge_Angular_Rate.value;
}

public void On_Edge_Rotation_Button()
{
bEdge_Rotation_On = !bEdge_Rotation_On;
bvAngular_On.isON = bEdge_Rotation_On;
}

public void OnHandles_OnOff()
{
bHandles_On = !bHandles_On;
bvHorns_Handles_On.isON = bHandles_On;

for(int i = 0; i<12; i++)
{
tangent_Handles[i].GetComponent<Handle_Tangent_Interact>().Show(bHandles_On);
}
}

float ang = 0;
void Update()
{
if (bUpdate)
{
if (bEdge_Rotation_On)
{
ang += edge_Angular_Rate * Time.deltaTime;
}
else
{
ang = 0;
}
for (int i = 0; i < 12; i++)
{
tangent_Handles[i].transform.localScale = scale_tangent_Handles * Vector3.one;
tangent_Handles[i].transform.position   = transform.position + transform.parent.TransformVector(tetra_Edges[i]);
}
Vector3 v_i1_i0;
Quaternion q0, q1;
Quaternion qZ_0, qZ_1;
for (int i = 0; i < 6; i++)
{
v_i1_i0 = tangent_Handles[i*2].transform.position - tangent_Handles[i*2+1].transform.position;

q0 = Quaternion.LookRotation(-v_i1_i0, tangent_Handles[i * 2].transform.position - transform.position);
q1 = Quaternion.LookRotation(v_i1_i0, tangent_Handles[i * 2 + 1].transform.position - transform.position);

float direction = 1f;
if(bEdge_Switch[i])
{
direction = -1f;
}

float tanDir = 1f;

Quaternion q0_bub = Quaternion.identity;
Quaternion q1_bub = Quaternion.identity;

qZ_0 = Quaternion.Euler(0, 0, direction*ang);
qZ_1 = Quaternion.Euler(0, 0, -direction*ang);

tangent_Handles[i * 2].transform.rotation = q0 * qZ_0 * Quaternion.Euler(new Vector3(tanDir*tan_Slide_Val, 0, 0))*q0_bub;
tangent_Handles[i * 2 + 1].transform.rotation = q1 * qZ_1 * Quaternion.Euler(new Vector3(tanDir*tan_Slide_Val, 0, 0)) * q1_bub;

//if (bv_Outii.isON && i > 2)
//{
//    if (i == 4)
//    {

//        //tanDir = -1f;
//        Vector3 nYellow0 = Vector3.Cross(go_cj_0.transform.up, tangent_Handles[i * 2].transform.forward).normalized;
//        Vector3 nYellow1 = Vector3.Cross(tangent_Handles[i * 2 + 1].transform.forward, go_cj_0.transform.up).normalized;

//        Vector3 nPlanar0 = Vector3.Cross(go_cj_0.transform.up, nYellow0).normalized;
//        Vector3 nPlanar1 = Vector3.Cross(go_cj_0.transform.up, nYellow1).normalized;

//        float cosTheta0 = Vector3.Dot(nPlanar0, nYellow0);
//        float cosTheta1 = Vector3.Dot(nPlanar1, nYellow1);

//        float ang0_R = Mathf.Acos(cosTheta0);
//        float ang1_R = Mathf.Acos(cosTheta1);

//        float convR_to_D = 180f / Mathf.PI;
//        float ang0_D = ang0_R * convR_to_D;
//        float ang1_D = ang1_R * convR_to_D;

//        q0_bub = Quaternion.AngleAxis(ang0_D, nYellow0);
//        q1_bub = Quaternion.AngleAxis(2 * ang1_D, nYellow1);

//        tangent_Handles[i * 2].transform.localRotation = q0_bub * tangent_Handles[i * 2].transform.localRotation;
//        //tangent_Handles[i * 2 + 1].transform.rotation = q1_bub;
//    }
//}

tangent_Handles[i * 2].GetComponent<Handle_Tangent_Interact>().Set_Tangent_Position(extend_Slide_Val);
tangent_Handles[i * 2 + 1].GetComponent<Handle_Tangent_Interact>().Set_Tangent_Position(extend_Slide_Val);
}
}
}

public void Generate_Splines(Vector3[] points, Vector3 vCenter)
{
if (!bHi_Res_On || bRun_Once)
{
bRun_Once = false;

aMD_Spline_Green.Clear();
aMD_Spline_Red.Clear();
aMD_Spline_Blue.Clear();
aMD_Spline_Yellow.Clear();
aMD_Spline_Orange.Clear();
aMD_Spline_Violet.Clear();

//aMD_Spline_Cross.Clear();

lst_SplineGreen.Clear();
lst_SplineRed.Clear();
lst_SplineBlue.Clear();
lst_SplineYellow.Clear();
lst_SplineOrange.Clear();
lst_SplineViolet.Clear();

//lst_SplineCross.Clear();

for (int i = 0; i < 12; i++)
{
tetra_Edges[i] = points[i];
}

p0_1 = points[0];//0
p0_2 = points[1];//1
p1_1 = points[2];//0
p1_2 = points[3];//2
p2_1 = points[4];//0
p2_2 = points[5];//3

p3_1 = points[6];//1
p3_2 = points[7];//2
p4_1 = points[8];//1
p4_2 = points[9];//3
p5_1 = points[10];//2
p5_2 = points[11];//3

Vector3 vTn_01, vTn_02, vTn_11, vTn_12, vTn_31, vTn_32;

if (bTangents_From_Octahedron)
{
//0-1
vTn_01 = twelve_Splines.getTan_Han(0).GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_01 = transform.parent.InverseTransformVector(vTn_01);

//1-0
vTn_02 = twelve_Splines.getTan_Han(1).GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_02 = transform.parent.InverseTransformVector(vTn_02);

//--------------------------
//0-2
vTn_11 = twelve_Splines.getTan_Han(2).GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_11 = transform.parent.InverseTransformVector(vTn_11);

//2-0
vTn_12 = twelve_Splines.getTan_Han(3).GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_12 = transform.parent.InverseTransformVector(vTn_12);

//---------------------------
//1-2
vTn_31 = twelve_Splines.getTan_Han(8).GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_31 = transform.parent.InverseTransformVector(vTn_31);

//2-1
vTn_32 = twelve_Splines.getTan_Han(9).GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_32 = transform.parent.InverseTransformVector(vTn_32);
}
else
{
//0-1
vTn_01 = tangent_Handles[0].GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_01 = transform.parent.InverseTransformVector(vTn_01);

//1-0
vTn_02 = tangent_Handles[1].GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_02 = transform.parent.InverseTransformVector(vTn_02);

//--------------------------
//0-2
vTn_11 = tangent_Handles[2].GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_11 = transform.parent.InverseTransformVector(vTn_11);
//2-0
vTn_12 = tangent_Handles[3].GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_12 = transform.parent.InverseTransformVector(vTn_12);

//---------------------------
//1-2
vTn_31 = tangent_Handles[6].GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_31 = transform.parent.InverseTransformVector(vTn_31);
//2-1
vTn_32 = tangent_Handles[7].GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_32 = transform.parent.InverseTransformVector(vTn_32);
}

//---------------------------
//0-3
Vector3 vTn_21 = tangent_Handles[4].GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_21 = transform.parent.InverseTransformVector(vTn_21);
//3-0
Vector3 vTn_22 = tangent_Handles[5].GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_22 = transform.parent.InverseTransformVector(vTn_22);

//---------------------------
//1-3
Vector3 vTn_41 = tangent_Handles[8].GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_41 = transform.parent.InverseTransformVector(vTn_41);
//3-1
Vector3 vTn_42 = tangent_Handles[9].GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_42 = transform.parent.InverseTransformVector(vTn_42);

//---------------------------
//2-3
Vector3 vTn_51 = tangent_Handles[10].GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_51 = transform.parent.InverseTransformVector(vTn_51);
//3-2
Vector3 vTn_52 = tangent_Handles[11].GetComponent<Handle_Tangent_Interact>().Get_Tangent_Position() - vCenter;
vTn_52 = transform.parent.InverseTransformVector(vTn_52);

//Local Coordinates
if (bv_Outii.isON)
{
//Mirror
Vector3 vLocal_Up_0 = transform.parent.InverseTransformVector(go_cj_0.transform.up).normalized;

Vector3 vHandle_Pos = tangent_Handles[6].gameObject.transform.position - vCenter;
vHandle_Pos = transform.parent.InverseTransformVector(vHandle_Pos);

Vector3 vTo_Tangent = vTn_31 - vHandle_Pos;

float dot;
dot = Vector3.Dot(vTo_Tangent, vLocal_Up_0);
float mir = -2f * dot;
vTn_31 += mir * vLocal_Up_0;
vTn_32 += mir * vLocal_Up_0;
vTn_41 += mir * vLocal_Up_0;
vTn_42 += mir * vLocal_Up_0;
vTn_51 += mir * vLocal_Up_0;
vTn_52 += mir * vLocal_Up_0;
}

//---------------------------
Compute_Dist_Spline(ref lst_SplineGreen, ref spline_lens_Green, p0_1, vTn_01, vTn_02, p0_2);
Compute_Dist_Spline(ref lst_SplineRed, ref spline_lens_Red, p1_1, vTn_11, vTn_12, p1_2);
Compute_Dist_Spline(ref lst_SplineBlue, ref spline_lens_Blue, p2_1, vTn_21, vTn_22, p2_2);

//---------------------------
Compute_Dist_Spline(ref lst_SplineYellow, ref spline_lens_Yellow, p3_1, vTn_31, vTn_32, p3_2);
Compute_Dist_Spline(ref lst_SplineOrange, ref spline_lens_Orange, p4_1, vTn_41, vTn_42, p4_2);
Compute_Dist_Spline(ref lst_SplineViolet, ref spline_lens_Violet, p5_1, vTn_51, vTn_52, p5_2);

spline_Green.GetComponent<MeshFilter>().mesh = aMD_Spline_Green.ToMeshInternal();
spline_Red.GetComponent<MeshFilter>().mesh = aMD_Spline_Red.ToMeshInternal();
spline_Blue.GetComponent<MeshFilter>().mesh = aMD_Spline_Blue.ToMeshInternal();
spline_Yellow.GetComponent<MeshFilter>().mesh = aMD_Spline_Yellow.ToMeshInternal();
spline_Orange.GetComponent<MeshFilter>().mesh = aMD_Spline_Orange.ToMeshInternal();
spline_Violet.GetComponent<MeshFilter>().mesh = aMD_Spline_Violet.ToMeshInternal();

//p0 = p0_1
//p1 = p1_1
//p2 = p2_1

//Tangents
//  6 & 7 -> tan 1,2 tu1 & tu2
//
//  tv1 =

//cj_12_EndPoints[0] = connected_Joints[0].transform.localPosition;
//cj_12_EndPoints[1] = connected_Joints[1].transform.localPosition;
//cj_12_EndPoints[2] = connected_Joints[0].transform.localPosition;
//cj_12_EndPoints[3] = connected_Joints[2].transform.localPosition;
//cj_12_EndPoints[4] = connected_Joints[0].transform.localPosition;
//cj_12_EndPoints[5] = connected_Joints[3].transform.localPosition;

//cj_12_EndPoints[6] = connected_Joints[1].transform.localPosition;
//cj_12_EndPoints[7] = connected_Joints[2].transform.localPosition;
//cj_12_EndPoints[8] = connected_Joints[1].transform.localPosition;
//cj_12_EndPoints[9] = connected_Joints[3].transform.localPosition;
//cj_12_EndPoints[10] = connected_Joints[2].transform.localPosition;
//cj_12_EndPoints[11] = connected_Joints[3].transform.localPosition;

/*test_Octahedron.transform.localPosition = */

faces.Clear_Faces();
faces.Generate_Face(tetra_Edges[0],  tetra_Edges[3], tetra_Edges[1],  vTn_32, vTn_31,  vTn_12, vTn_02, vTn_11, vTn_01 );
faces.Generate_Face(tetra_Edges[0],  tetra_Edges[5], tetra_Edges[3],  vTn_52, vTn_51,  vTn_22, vTn_12, vTn_21, vTn_11 );
faces.Generate_Face(tetra_Edges[0],  tetra_Edges[1], tetra_Edges[5],  vTn_41, vTn_42,  vTn_02, vTn_22, vTn_01, vTn_21 );
faces.Generate_Face(tetra_Edges[6],  tetra_Edges[7], tetra_Edges[9],  vTn_51, vTn_52,  vTn_32, vTn_42, vTn_31, vTn_41 );

faces.toMesh_Internal();

//Generate_Face(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 tu1, Vector3 tu2, Vector3 tv1, Vector3 tv2, Vector3 tv01, Vector3 tv02)
}
/// <image url="\$(SolutionDir)\EMB\EMB_tetra_Faces.png" scale="0.15" />

}

private void Compute_Spline(ref List<Vector3> spline_lst, ref float[] lengths,  Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
{
float t = 0.0f;
float dt = 1f / 72f;

Vector3 vB = GetPointOnBezierCurve(p0, p1, p2, p3, get_Adjusted(t, ref lengths));

for (int i = 0; i < 72; i++)
{
vB = GetPointOnBezierCurve(p0, p1, p2, p3, get_Adjusted(t, ref lengths));

t += dt;
}
}

private float get_Adjusted(float t, ref float[] lengths)
{
int i = 0;
while (i < 256 && lengths[i] < t)
{
i++;
}
return (float)i / 256;
}

private void Compute_Dist_Spline(ref List<Vector3> spline_lst, ref float[] lengths, Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3)
{
float t = 0.0f;
float dt = 1f / 256;

Vector3 vB = GetPointOnBezierCurve(p0, p1, p2, p3, t);
Vector3 vB_Last = vB;
float running_Len = 0;

for (int i = 0; i < 256; i++)
{
vB = GetPointOnBezierCurve(p0, p1, p2, p3, t);
running_Len += (vB - vB_Last).magnitude;
lengths[i] = running_Len;
vB_Last = vB;
t += dt;
}
for (int i = 0; i < 256; i++)
{
lengths[i] /= running_Len;
}
Compute_Spline(ref spline_lst, ref lengths, p0, p1, p2, p3);
}

public Vector3 GetPointOnBezierCurve(Vector3 p0, Vector3 p1, Vector3 p2, Vector3 p3, float t)
{
float u = 1f - t;
float t2 = t * t;
float u2 = u * u;
float u3 = u2 * u;
float t3 = t2 * t;

Vector3 result =
(u3) * p0 +
(3f * u2 * t) * p1 +
(3f * u * t2) * p2 +
(t3) * p3;

return result;
}
}


## EU Meetup January 30, 2018

 Do electrons and protons maintain their identity ? 1 message

Juan Calsiano <juancalsiano@gmail.com> Mon, Jan 29, 2018 at 1:39 PM
To: Edo Kael <edwinkaal00@gmail.com>
Cc: Jim Weninger <jwen1@yahoo.com>, "dj@argos.vu" <dj@argos.vu>
 "Does any portion of the universe maintain its identity?" If one assumes an absolutely boundless universe, then the answer is no. Any portion of a Boundless Universe is endlessly integrated and endlessly divided and fluctuates in a permanent process of becoming. Each portion is absolutely unique with respect to all other portions, and each portion is different from itself from one instant to the next. Regarding that last part as it relates to identity: we all know that all portions of the universe with which we relate everyday are ever-changing and in constant flux. If it doesn't seem so, it is just that we haven't observed or measured it carefully, or waited long enough. The only constant is change. A triangle is changeless, but a triangle is just an idea. The totality of evidence indicates that the external world is in permanent flux. That doesn't mean that portions of the universe cannot have qualities with remarkably persistent properties, of course, not only protons and electrons but all portions of matter have such qualities. The important point is that, in a Boundless Universe, all such portions also have countless other qualities that are fluctuating. So, overall, any portion of the universe is constantly evolving and has a unique inexhaustible structure that is never absolutely the same moment to moment. As I said before, a galactic observer would be amazed by the remarkably persistent properties of the solar system. A remarkably persistent solar system mass, orbits following geometrical proportions, the main solar cycle and a large etcétera. If you were only to measure such properties (something reasonable considering their relative simplicity), one could postulate that those are only the variables that actually exist and pose that the solar system is remarkably simple. So, in terms of such variables, the solar system "identity" is maintained. As we know, the solar system is mindbogglingly complex, not only in terms of its fruit salad planetary system, but also even in terms of all the aspects of the sun itself, which is as far as a perfect geometrical platonic sphere as one could imagine, something we now know thanks to the incredible data gathered since the space age beginnings. In sum, we know for a fact that, even if it has a fascinating array of persistent regularities, the solar system is unique and unrepeatable compared to the rest of the universe, and each moment of the solar system is unique and unrepeatable compared to any moment in the past or in the future. So, pondering on such indisputable facts, how are we going to think about the atomic scale? Well, one must necessarily assume one of two things: 1) That this observed quality of the universe of uniqueness and non-repeatability continues to be true at any deeper scales (a consequence of assuming a boundless universe). 2) That this observed quality of the universe changes at a given deeper unobservant scale (a consequence of assuming a finite universe that implies an hypothetical fundamental and irreducible simplicity at some deeper scale, a simplicity not observed in any other scale that we can observe). I think that Ockham said something about these situations! In any case, we can go through the empirical way: everything that we have measured at the atomic scales or smaller is constantly waving, i.e. in permanent flux. Any physical wave requires a deeper wave-conducting medium with deeper complexity (e.g. compressions and rarefactions) to enact the waving. In terms of such worldview, each and every electron is different and unique, as all of the protons. That said, all electrons have crucial similarities as attested in the very precise regularities that they demonstrate. In a more general way, in a boundless universe, all things have characteristics that make them similar to all other things as well as characteristics that make them dissimilar to all other things. Think about a huge field with 100.000 tuning forks, all of slightly different sizes, shapes, and materials, but all tuned to 440 Hz. You very carefully measure the sizes, shapes and composition of each one and find out that they are all completely different. But then you hit them and force all of them to vibrate, and you measure that the fundamental frequency is always 440 Hz. They are absolutely identical! The truth, of course, is that those 100.000 units are neither completely different nor absolutely identical. All portions of the universe exist in a similarity-dissimilarity continuum. And that applies to protons and electrons as well. You must always remember that experimental physicists do not measure the momentum of the electron (as if they were a "classical particle"), they measure wavelength and frequency, two basic wave properties. Tuning forks are very educational. Cheers!

# Scientists unveil new form of matter: time crystals

Edo Kael <edwinkaal00@gmail.com> Mon, Jan 29, 2018 at 7:40 AM
To: Jim Weninger <jwen1@yahoo.com>
Cc: "dj@argos.vu" <dj@argos.vu>, Juan Calsiano <juancalsiano@gmail.com>
 Jim, I cannot attest to planets and such and fall back myself to the explanation Wal Thornhill has for a "hollow earth". In my mind i consider it an option due to the electric effect, meaning IF that is shown to be the case, i would go for it, but would still want some proof. The reason is that despite the fact that the atom is "hollow' that is only true to a certain extent. The Carbon is hollow like and since the elements are more or less made up of those one could argue that is has room.  However the atom is more fractal in nature and does try to gather all the mass / matter in the smallest sphere as possible and does this in the densest packing manner. The fact that Carbon is hollow has to do with the fact that the individual protons cannot fall further into the center because they support each other in a static and equilibrium situation. This in my view also implies that the atom and in particular the nucleus resist absorption of energy... I have said my  goodbye's to QM and anything it tries to tell us. That means i do not adhere to the theory, i do pay close attention and consider that good science, the isotopic data for example, mass number, proton / electron numbers, melting points, ionization energy levels, spin, valence value etc etc. One might argue that this is also QM, but i would say that is can be done without QM.... and has been at first for sure when no one heard of QM and we still did physics and chemistry.  If the mass or charge is concentrated into a hollow shell of radius=1, the inverse square law works at infinity, but fails spectaculary at radius= 1. Inside r=1 there is no field/force. Well that is how i see the proton and even the electron, having a radius / being a sphere, there are no dots i believe. Could this conclusion at radius one have something to do with the decay of the neutron? into an electron proton pair? I am unsure as to why you reach that conclusion (fails at r=1) Edo

### Jim Weninger

7:09 PM

 to dj, Edo, Juan
Sorry if the last post was again cryptic, but I'll share my viewpoint in a little more detail, and as always,  I'm looking  for objections before I go too far out with ill conceived ideas:
We've talked before about ideas of a hollow Sun and Earth, compared to the mainstream idea of a Sun or Earth which increase in density towards center.  Also, I am arguing that the atom is a nearly exact replication of the solar system, just on another scale.  (by the way, the arrangement of mass in Edo's model of the nucleus also does NOT give us a concentration of mass at the center of the nucleus)
So here is the question (on each scale):  How could we know if solar system objects, like Sun and Earth, are hollow?  Or, how could we know if atomic scale objects (in this article, it is the proton), are hollow?  That is how could we tell if the mass of the sun (or a proton), were located at the center of the object, compared to the periphery?  Comparing nearby orbits to farther out orbits, that is how.
Whether we are talking planetary orbits around the sun, or electron orbits around a proton, if we move out to a large radius, it does not matter where the mass is located.  We can treat a planet as if it is attracted to the sun's center , or an electron as if it is attracted to a protons center.  But, if we close in on either object, we see the problem.
I would like you guys to draw this for yourselves, because it WILL explain the muon vs electron orbits.
And tell us the mass distribution in a proton.  Or on the solar system scale, the mass distribution of the sun.
In even simpler terms (just so you can see what I'm saying), if mass or charge  is concentrated at a point, the inverse square law works all the way from radius =infinity , to radius = 0.    If the mass or charge is concentrated into a hollow shell of radius=1, the inverse square law works at infinity, but fails spectaculary at radius= 1. Inside r=1 there is no field/force.
This IS the source of the proton radius problem.  The proton, just like the sun, IS (relatively) hollow.     The nucleus too, is again relatively hollow, but Edo must already know this.
Jim
On Saturday, January 27, 2018, 6:15:46 PM MST, Jim Weninger <jwen1@yahoo.com> wrote:
Edo,
Just wandering through a bunch of stuff - and finding this idea interesting in regards to why the electron may maintain it's identity when bound so closely with the proton and visa versa of course.
Also a Sympathetic Vibratory Model keeps "Ringing Down" in my head:
Extrapolate this as r decreases to zero - Harmonically resonate the frequencies "back down" and consider what "White Light" may perhaps be:

🙂
/dj

Steric Repulsion

### Sterically Stabilized Dispersion

For sterically stabilized dispersions, the resulting energy-distance curve often shows a shallow minimum, Vmin, at a particle-particle separation distance h comparable to twice the adsorbed layer thickness delta. For a given material, the depth of this minimum depends on the particle size R and adsorbed layer thickness delta.

Hence Vmin decreases with increase in $\frac{\delta }{R}$, as illustrated in the figure above. This is because as we increase the layer thickness, the van der Waals attraction weakness so the superposition of attraction and repulsion will have a smaller minimum. For very small steric layers, $V_{\min }$ may become deep enough to cause weak flocculation, resulting in a weak attractive gel.

On the other hand, if the layer thickness is too large, the viscosity is also increased due to repulsion. This is due to the much higher effective volume fraction $\Phi _{eff}$ of the dispersion compared with the core volume fraction. We can calculate the effective volume fraction of particles plus dispersant layer by geometry and we see that it depends on the thickness of that adsorbed layer, as illustrated in the figure below.

The effective volume fraction increases with relative increase in the dispersant layer thickness. Even at 10% volume fraction we can soon reach maximum packing ($\Phi =0.67$) with an adsorbed layer comparable to the particle radius. In this case, overlap of the steric layers will result in significant viscosity increases. Such considerations help to explain why the solids loading can be severely limited, especially with small particles. In practice, solids loading curves can be used to characterize the system and will take the form of those illustrated below:

A higher solids loading might be achieved with thinner adsorbed layers but may also lead to interparticle attraction, resulting in particle aggregation. Clearly a compromise is needed: choosing an appropriate steric stabilizer for the particle size of the pigment.

# Super Blue Blood Moon 2018:

During the early hours of Jan. 31, there will be a full moon, a total lunar eclipse, a blue moon and a supermoon. None of these things is all that unusual. What is rare is that they’re happening all together on one day.