Page 1 of 2

Resetting frame without affecting objects

Posted: Thu Nov 28, 2024 5:06 am
by RJD
Hi,

I was just wondering if it was possible to reset the frame of entity so that it coincides with the global (identity) frame, without affecting the entity's location/orientation in space. My use case is that I would like my entity's geometry (e.g. vertex coordinates) to always be defined globally, but I also have to perform transformations of my entity, like rotations and translation. I would like to perform these transformations, but then immediately reset its frame so that its frame is the global frame. My entity also has children which makes IGeometricObject_DG undesirable.

Thank you in advance!

Re: Resetting frame without affecting objects

Posted: Fri Nov 29, 2024 9:41 pm
by Prashant Kande
Hi RJD

Surface of an entity is defined relative to the local frame. This is because the object can be moved frequently like during animation. This means that the local frame is baked into the definition (parameters) of the surface.

So, if you need to change the local frame, changing the geometry (surface) is inevitable. It is not difficult. It takes only few lines to code. The Transform sample demoes this (select Local Frame in the Apply To group). See also Transformations thread.

The transformation can be generic. Like you can make move the local frame to make it any location/orientation. You can code a small loop to apply this for children as well.

This is a quick answer. I will write more on Monday.

Regards

Re: Resetting frame without affecting objects

Posted: Fri Nov 29, 2024 9:47 pm
by Prashant Kande
Another option: If you either make your entity a child of an empty one and add an empty child or use frame of a child you would have the second frame to move the object around. A family of Entities move together when either frame is moved.

Re: Resetting frame without affecting objects

Posted: Sun Dec 01, 2024 8:33 pm
by Prashant Kande
Just in case an educational primer for our dear newbie readers.

There are several types of transformations:

1. 3D Viewing pan, rotate, zoom. These do not change anything in the model. It is a change in the point of view. It is handler by the renderer and does not require any coding.

2. Moving entities relative to one another. This is accomplished by moving the local frame of the entity. It is quick and does not change the geometry (parameters of the surface)

3. Changing location and/or orientation the surface relative to the local frame. This requires redefinition of the surface. Selection of the local frame is a design decision. Changing its location is a revision of the design. Sometimes it is inevitable but should be considered as the last resort. For programmatically- generated objects a good way is to use some parameters for possible modifications in the construction function. This way changing the design is just re-executing the code with different parameters to get a new object.

A local frame is a kind of handle for the entity. Its location is important for rotations. For an example moving a box is a little awkward when it is not in the center.

Re: Resetting frame without affecting objects

Posted: Mon Dec 02, 2024 6:46 am
by RJD
Ah I see. Thank you, that is very helpful to know! Would it be possible then to calculate the Frame that transforms the local frame of the entity to the global frame, apply it to the local frame, and then apply the inverse frame to the entity (as IGeometricObject_DG)? If so, do you think you could point me in the right direction with a code snippet (in C#)? I've been playing around with the various the methods that return IFrame_DG but I'm not getting the results I'm after.

Re: Resetting frame without affecting objects

Posted: Mon Dec 02, 2024 6:41 pm
by Prashant Kande
Sure. Sorry, I should have mentioned that we are making some checks and tests before adding code snippets here.
Thank you for a great question

Re: Resetting frame without affecting objects

Posted: Tue Dec 03, 2024 10:11 am
by Prashant Kande
Please download today's 5549 update.

We have added two new cases to InterfaceTests.IEntityTest. See the Samples\NET\C#\Tests\InterfaceTests\ project. To run make sure the top IEntityTest is selected on the left and click either TranslateLocalFrame or MoveLocalFrame at the bottom in Cases list.

TranslateLocalFrame() is pretty simple.

Code: Select all

public void TranslateLocalFrame()
{
    IEntity_DG entity = m_iStdShape.Box(2, 4, 6);
    // By default the local frame is at a corner of the box and coinsides with the global frame

    // Add a child
    IEntity_DG entityChild = m_iStdShape.Rectangle(3, 4);
    IFrame_DG frameChild = entityChild.GetLocation();
    frameChild.Translate(3, 0, 0);                // Move away from the box

    //Uncomment this return to see the initial configuration
    //return;

    IGeometricObject_DG geomObj = entity.As<IGeometricObject_DG>();

    // The new location of the local frame at the center of the box
    VectDg v = new VectDg(-1, -2, -3);
    geomObj.Translate(v);

    // Apply the same to the child
    frameChild.Translate(v);

    entity.AddChild(entityChild);

    //Uncomment this return to see the result of geometry modification
    //return;

    // Move the frame in opposite direction so that the object stays at the same location
    v.SwapDirection();
    IFrame_DG frame = entity.GetLocation();
    frame.Translate(v);

    Display(entity);
}
One can do a single rotation this way also.

MoveLocalFrame() demoes using a general movement/transform of the local frame:

Code: Select all

public void MoveLocalFrame()
{
    IFrame_DG transform = m_gen.Create<IFrame_DG>();

    IEntity_DG entity = MoveGeometry(transform);

    //Comment out the next call to see the result of geometry modification

    // Move the whole entity back so that the box stays in the same place
    RestoreGeometryLocation(entity, transform);

    Display(entity);
}

public IEntity_DG MoveGeometry(IFrame_DG transform)
{
    IEntity_DG entity = m_iStdShape.Box(2, 4, 6);
    // By default the local frame is at a corner of the box and coinsides with the global frame

    // Add a child
    IEntity_DG entityChild = m_iStdShape.Rectangle(3, 4);
    IFrame_DG frameChild = entityChild.GetLocation();
    frameChild.Translate(3, 0, 0);                // Move away from the box

    //Uncomment this to see the initial configuration
    // entity.AddChild(entityChild);  return entity;

    IGeometricObject_DG geomObj = entity.As<IGeometricObject_DG>();

    IFrame_DG frame = entity.GetLocation();

    transform.Rotate(0.25 * Math.PI, 0);
    transform.Rotate(0.25 * Math.PI, 2);
    transform.Translate(-1, -2, -3);

    geomObj.Transform(transform);

    IFrame_DG frameChildNew = transform.ToGlobal(frameChild);
    frameChild.Copy(frameChildNew);

    entity.AddChild(entityChild);

    return entity;
}

public void RestoreGeometryLocation(IEntity_DG entity, IFrame_DG transform)
{
    transform.Invert(); // This modifies transform. We do not need it anymore

    IFrame_DG frame = entity.GetLocation();
    IFrame_DG framedNew = transform.ToGlobal(frame);
    frame.Copy(framedNew);
}
Movement of local frame is not really correct description of what is going on. It is rather modification of geometry which appears like the local frame has been moved. I hope to write a bit more about that tomorrow.

I recommend looking at the TranslateLocalFrame() first. Then trying commending out Translate() and one Rotate() in the definition of transform in MoveGeometry(). It will be clearer what is going on. Also try uncommenting the suggested returns to see what was before the operation.

Notice that entity.AddChild(entityChild); in MoveGeometry() is at the end after all movements have been done. This is to make sure the two entities can be moved independently.

In your code for moving children of all levels you can detach each from its parent with something like:

Code: Select all

IEntityArray_DG flatList = entity.GetChildArray(true);	//bool includeDescendents)
foreach(IEntity_DG child in flatList)
{
	entity.RemoveEntity(child);
	// do the movement here	
	entity.AddChild(child);	// Add it back
}

Re: Resetting frame without affecting objects

Posted: Tue Dec 03, 2024 6:34 pm
by Prashant Kande
Similarly to usual frame movement the second rotation in
transform.Rotate(0.25 * Math.PI, 0);
transform.Rotate(0.25 * Math.PI, 2);
transform.Translate(-1, -2, -3);
of MoveGeometry() applies rotation relative to the current orientation of the frame achieved after the first rotation, not the initial orientation.

Re: Resetting frame without affecting objects

Posted: Tue Dec 03, 2024 7:09 pm
by Prashant Kande
Again, why do we need to modify the geometry?

Geometry itself is not aware of any frames. It is just a collection of coordinates, curves, surfaces. Say, if the object is a single point as a point set, then the geometry will have only three coordinates like (1,0,0) stored. Translation with IGeometricObject_DG.Translate(0,1,0) would only change the stored coordinates to (1,1,0). A rotation with IGeometricObject_DG.Rotate(0.5*MAth.PI, 0,0,1) would change the coordinates to (0, 1, 0).

When the object is an edge, this would change coordinates of the two end vertices and the curve to make sure it still connects them. When the object is a face, the change is applied to all edges, vertices and the surface, etc.

When other parts on the software, including the renderer, see the geometry definition they assume that all coordinates are relative to the local frame of the entity. So, they do IFrame_DG.ToGlobal(point) to get the actual global coordinates.

That is why modification of geometry is inevitable for moving the local frame.

Moving the local frame is a bit of cheating. It consists of wo steps: A) Changing the geometry so it is defined relative to the new position. B) Moving the obtained entity so that the object appear in the same place on the screen.

The main job is the step A), of course. After it is done, relative positions of the surface and the local frame is already changed. Step A) results in the object moved on the screen and the local frame remains in the same place.

The step B) is needed to achieve what is expected: The object (surface) should remain steady, but the local frame should move to the new location. Step B) is rather cosmetic. It moves the whole entity in the opposite direction to align the surface with its old position on the screen.

In the MoveLocalFrame() code A) step is done in the MoveGeometry(transform); call. RestoreGeometryLocation(entity, transform); is the step B).

As you see, the overall operation is rather complex and computationally heavy. For large meshes it might involve transforming millions of vertices.

Re: Resetting frame without affecting objects

Posted: Tue Dec 03, 2024 7:23 pm
by Prashant Kande
The above code assumes that descendants represent parts of a solid assembly, so the different surfaces have to remain aligned in the same way.

Notice that the child entity is moved as a whole without modifying relative position of its local frame. If you need to move local frame for descendants also, it is probably better to do it in separate steps after the parent has been handled.