public static Vector3 GetRandomWorldPosistionInBoundaryClosest(GameObject element, GameObject container, GameObject target)
    {
        DatasetObjectInfo elementInfo    = element.GetComponent <DatasetObjectInfo>();
        DatasetObjectInfo containterInfo = container.GetComponent <DatasetObjectInfo>();
        DatasetObjectInfo targetInfo     = target.GetComponent <DatasetObjectInfo>();
        var elementSize  = elementInfo.GetBoundarySize();
        var containerMin = containterInfo.GetMinBoundaryPoint();
        var containerMax = containterInfo.GetMaxBoundaryPoint();

        Vector3 transformedCenterOffset = element.transform.TransformDirection(elementInfo.center);
        Vector3 currentElementPosition  = element.transform.position;

        float x = Random.Range(containerMin.x + elementSize.x / 2f - transformedCenterOffset.x, containerMax.x - elementSize.x / 2f - transformedCenterOffset.x);
        float y = Random.Range(containerMin.y + elementSize.y / 2f - transformedCenterOffset.y, containerMax.y - elementSize.y / 2f - transformedCenterOffset.y);
        float z = Random.Range(containerMin.z + elementSize.z / 2f - transformedCenterOffset.z, containerMax.z - elementSize.z / 2f - transformedCenterOffset.z);

        if (-(containerMin.y + elementSize.y / 2f - transformedCenterOffset.y) + (containerMax.y - elementSize.y / 2f - transformedCenterOffset.y) < 0)
        {
            y = containerMin.y + elementSize.y / 2f - transformedCenterOffset.y;
        }

        Vector3 endPoint = target.transform.TransformPoint(targetInfo.testPoints[Random.Range(0, targetInfo.testPoints.Count)]);
        float   t        = 0f;

        float p = 0f, k = 1f, s;

        for (int i = 0; i < 10; i++)//Bin search
        {
            s = (p + k) / 2f;
            element.transform.position = Vector3.Lerp(new Vector3(x, y, z), endPoint, s);
            if (!BoundaryIsColliding(element, target) && IsInside(element, container))
            {
                p = s;
                t = s;
            }
            else
            {
                k = s;
                t = p;
            }
        }
        float offset = Settings.config.datasetOptions.closestMaxDistanceOffset;

        float dt = 1f / (new Vector3(x, y, z) - endPoint).magnitude * offset * Random.value;

        element.transform.position = Vector3.Lerp(new Vector3(x, y, z), endPoint, t - dt);
        if (!BoundaryIsColliding(element, target) && IsInside(element, container))
        {
            element.transform.position = currentElementPosition;
            return(Vector3.Lerp(new Vector3(x, y, z), endPoint, t - dt));
        }
        else
        {
            element.transform.position = currentElementPosition;
            return(Vector3.Lerp(new Vector3(x, y, z), endPoint, t));
        }
    }
    public static bool AreColliding(GameObject elementA, GameObject elementB)
    {//TODO CHECK
        DatasetObjectInfo infoA = elementA.GetComponent <DatasetObjectInfo>();
        DatasetObjectInfo infoB = elementB.GetComponent <DatasetObjectInfo>();

        Vector3 aMin = infoA.GetMinBoundaryPoint();
        Vector3 aMax = infoA.GetMaxBoundaryPoint();
        Vector3 bMin = infoB.GetMinBoundaryPoint();
        Vector3 bMax = infoB.GetMaxBoundaryPoint();

        return((aMin.x <= bMax.x && aMax.x >= bMin.x) &&
               (aMin.y <= bMax.y && aMax.y >= bMin.y) &&
               (aMin.z <= bMax.z && aMax.z >= bMin.z));
    }
    public static Vector3 GetRandomWorldPosistionInBoundary(GameObject element, GameObject container)
    {
        DatasetObjectInfo elementInfo    = element.GetComponent <DatasetObjectInfo>();
        DatasetObjectInfo containterInfo = container.GetComponent <DatasetObjectInfo>();
        var elementSize  = elementInfo.GetBoundarySize();
        var containerMin = containterInfo.GetMinBoundaryPoint();
        var containerMax = containterInfo.GetMaxBoundaryPoint();

        Vector3 transformedCenterOffset = element.transform.TransformDirection(elementInfo.center);
        float   x = Random.Range(containerMin.x + elementSize.x / 2f - transformedCenterOffset.x, containerMax.x - elementSize.x / 2f - transformedCenterOffset.x);
        float   y = Random.Range(containerMin.y + elementSize.y / 2f - transformedCenterOffset.y, containerMax.y - elementSize.y / 2f - transformedCenterOffset.y);
        float   z = Random.Range(containerMin.z + elementSize.z / 2f - transformedCenterOffset.z, containerMax.z - elementSize.z / 2f - transformedCenterOffset.z);

        if (-(containerMin.y + elementSize.y / 2f - transformedCenterOffset.y) + (containerMax.y - elementSize.y / 2f - transformedCenterOffset.y) < 0)
        {
            y = containerMin.y + elementSize.y / 2f - transformedCenterOffset.y;
        }
        return(new Vector3(x, y, z));
    }
    public static bool BoundaryIsColliding(GameObject boundaryObject, GameObject pointObject)
    {
        DatasetObjectInfo boundaryInfo = boundaryObject.GetComponent <DatasetObjectInfo>();
        DatasetObjectInfo pointInfo    = pointObject.GetComponent <DatasetObjectInfo>();
        Vector3           aMin         = boundaryInfo.GetMinBoundaryPoint();
        Vector3           aMax         = boundaryInfo.GetMaxBoundaryPoint();

        foreach (var pointRaw in pointInfo.testPoints)
        {
            var point = pointObject.transform.TransformPoint(pointRaw);
            if ((aMin.x <= point.x && aMax.x >= point.x) &&
                (aMin.y <= point.y && aMax.y >= point.y) &&
                (aMin.z <= point.z && aMax.z >= point.z))
            {
                return(true);
            }
        }
        return(false);
    }
    public static Vector3 GetRandomWorldPosistionInBoundary(GameObject element, GameObject container, GameObject target)
    {
        DatasetObjectInfo elementInfo    = element.GetComponent <DatasetObjectInfo>();
        DatasetObjectInfo containterInfo = container.GetComponent <DatasetObjectInfo>();
        var elementSize  = elementInfo.GetBoundarySize();
        var containerMin = containterInfo.GetMinBoundaryPoint();
        var containerMax = containterInfo.GetMaxBoundaryPoint();

        Vector3        transformedCenterOffset = element.transform.TransformDirection(elementInfo.center);
        List <Vector3> positions          = new List <Vector3>(10);
        List <float>   distancesToElement = new List <float>(positions.Count);

        for (int i = 0; i < positions.Capacity; i++)
        {
            float x = Random.Range(containerMin.x + elementSize.x / 2f - transformedCenterOffset.x, containerMax.x - elementSize.x / 2f - transformedCenterOffset.x);
            float y = Random.Range(containerMin.y + elementSize.y / 2f - transformedCenterOffset.y, containerMax.y - elementSize.y / 2f - transformedCenterOffset.y);
            float z = Random.Range(containerMin.z + elementSize.z / 2f - transformedCenterOffset.z, containerMax.z - elementSize.z / 2f - transformedCenterOffset.z);
            if (-(containerMin.y + elementSize.y / 2f - transformedCenterOffset.y) + (containerMax.y - elementSize.y / 2f - transformedCenterOffset.y) < 0)
            {
                y = containerMin.y + elementSize.y / 2f - transformedCenterOffset.y;
            }
            positions.Add(new Vector3(x, y, z));
            distancesToElement.Add((target.transform.position - positions[positions.Count - 1]).sqrMagnitude);
        }

        int   index            = -1;
        float smallestDistance = Mathf.Infinity;

        for (int i = 0; i < distancesToElement.Count; i++)
        {
            if (distancesToElement[i] < smallestDistance)
            {
                index            = i;
                smallestDistance = distancesToElement[i];
            }
        }

        return(positions[index]);
    }
    public static bool IsInside(GameObject element, GameObject container)
    {
        DatasetObjectInfo elementInfo    = element.GetComponent <DatasetObjectInfo>();
        DatasetObjectInfo containterInfo = container.GetComponent <DatasetObjectInfo>();
        var elementSize  = elementInfo.GetBoundarySize();
        var containerMin = containterInfo.GetMinBoundaryPoint();
        var containerMax = containterInfo.GetMaxBoundaryPoint();

        Vector3 transformedCenterOffset = element.transform.TransformDirection(elementInfo.center);
        Vector3 currentElementPosition  = element.transform.position;

        float x = element.transform.position.x;
        float y = element.transform.position.y;
        float z = element.transform.position.z;

        float minX = containerMin.x + elementSize.x / 2f - transformedCenterOffset.x;
        float maxX = containerMax.x - elementSize.x / 2f - transformedCenterOffset.x;
        float minY = containerMin.y + elementSize.y / 2f - transformedCenterOffset.y;
        float maxY = containerMax.y - elementSize.y / 2f - transformedCenterOffset.y;
        float minZ = containerMin.z + elementSize.z / 2f - transformedCenterOffset.z;
        float maxZ = containerMax.z - elementSize.z / 2f - transformedCenterOffset.z;

        return(x >= minX && x <= maxX && y >= minY && y <= maxY && z >= minZ && z <= maxZ);
    }