Keeping randomized points within parent container

Hello, I’m hoping someone can solve a problem I am working through. Suppose I create a series of randomized point with the following function:

private static IPoint CreatePoint()
{
    // Create randomized point around a circle w/ a bias towards the center
    double r = rdm.NextDouble();
    double theta = rdm.NextDouble() * Math.PI;
    double phi = rdm.NextDouble() * 2.0 * Math.PI;
    double cosTheta = Math.Cos(theta);
    double sinPhi = Math.Sin(phi);
    double cosPhi = Math.Cos(phi);

    double x = r * cosPhi;
    double y = r * sinPhi * cosTheta;

    return new Point(x, y);
}

The function itself is run through a loop n-times and after refusing any overlapping points, each point is stored in an array. Later, in a controller (but really view??) class, I run this, which creates n-amount of circle images at the points previously chosen (multiplied by a scale size):

void Start()
    {
        // Create the Star System and the Jump Gate connection icons for the galaxy map
        for (int i=0; i<galaxy.StarSystems.Length; i++)
        {
            StarSystem star = galaxy.StarSystems[i];
            Vector3 systemPos = new Vector3((float)star.Location.X * scale, (float)star.Location.Y * scale, 0);
            CreateCircleSprite(systemPos, i, star.StarType);

            // jumpgate stuff, whatever...
        }

        FitParentContainer(mapContainer);
    }

The CreateCircleSprite and FitParentContainer are as below:

private GameObject CreateCircleSprite(Vector3 anchoredPos, int index, StarType type)
    {
    GameObject circleGameObj = new GameObject("system", typeof(Image));
    circleGameObj.transform.SetParent(mapContainer);

    // Texture added in shader to create glow effect. See Materials folder
    Image circleImage = circleGameObj.GetComponent<Image>();
    circleImage.material = circleSpriteMaterials[(int)type];

    RectTransform rectTransform = circleGameObj.GetComponent<RectTransform>();
    rectTransform.anchoredPosition3D = anchoredPos;
    rectTransform.sizeDelta = new Vector3(starSystemRadius, starSystemRadius, 0);
       
    rectTransform.anchorMin = new Vector2(0.5f, 0.5f);
    rectTransform.anchorMax = new Vector2(0.5f, 0.5f);

    rectTransform.localScale = new Vector3(1, 1, 1);

    MapSystemIcon systemIcon = circleGameObj.AddComponent<MapSystemIcon>();
    systemIcon.ID = index;
    systemIcon.OnClick += SystemIcon_OnClick;

    return circleGameObj;
}

public void FitParentContainer(RectTransform container)
{
    RectTransform children = container.transform.GetComponentInChildren<RectTransform>();

    float minX, maxX, minY, maxY;
    minX = maxX = container.localPosition.x;
    minY = maxY = container.localPosition.y;

    foreach(RectTransform child in children)
    {
        if (child.name == "system")
        {    
            float tempMinX = child.localPosition.x ;
            float tempMaxX = child.localPosition.x;
            float tempMinY = child.localPosition.y;
            float tempMaxY = child.localPosition.y;

            if (tempMinX < minX) { minX = tempMinX; }
            if (tempMaxX > maxX) { maxX = tempMaxX; }
            if (tempMinY < minY) { minY = tempMinY; }
            if (tempMaxY > maxY) { maxY = tempMaxY; }

        }
    }

    container.sizeDelta = new Vector2(maxX - minX, maxY - minY);
}

What I have noticed is that sometimes I have circle images that fall outside the bounds of the parent container, which is very annoying because the parent container is in a masked scroll view which effectively cuts the view of the circles that fall outside the parent container.

To me, this shouldn’t happen because the FitParentContainer calculates the width and height of the parent by getting the subtracting the rightmost position from the leftmost, and similarly with the topmost and bottom-most positions.

If it helps, the parent container min/max anchors are 0.5, and same with the pivot.

Does anyone know why there are some circles that fall outside the bounds of the parent container and know how to keep all child circles within the parent?

Many thanks

I suspect the issue has to do with manipulating RectTransform properties directly and ending up with the wrong calculation output.

RectTransforms are Really Hard™ to work with!

Check out this example huge sheet of code necessary JUST to move the anchors to the corners of a RectTransform, something I would intuit would be one line of code:

http://forum.unity3d.com/threads/script-simple-script-that-automatically-adjust-anchor-to-gui-object-size-rect-transform.269690/

Perhaps that code can guide you as to how the calculations can go wrong. I would strip your dataset down to like 1 or 2 circles, even if you have to hand-generate them with the sizes you need to trigger the problem, and reason through the actual values. It’s hairy.

While this new Vector2(maxX - minX, maxY - minY); does give you the overall size of the area, it does not take into account the center of your object.

I barely used the 2d system, but what I’ve read is that sizeDelta is the relative size to the original size. Imagine you have some points far to the left but none far to the right. So the min max you calculate will represent the AABB of those points. Though the center of that AABB probably does not represent the actual center. While your rect has the right size, it’s probably offset, so on one side you have some empty space while on the opposite side things are outside the rect.

As I said, I barely used RectTransforms. Though I know it has several unintuitive relationships and behaviours you have to get used to ^^. I don’t have the time to disect this now ^^. Also the UI system can get extremely complex depending on the various anchors and sizes involved. Setting certain properties will actually make other recalculate.

After playing around a bit, I understand that the issue is setting the anchors of the children. The question then, is if the location of the children are randomized, how do I calculate the child anchors after calculating the width/height of the parent?