Friday, January 10, 2025

Scaling in Computer Graphics...

Here's my experimentation with Scaling in Computer Graphics...


 Here's the Python code for experimentation of Scaling in freeCAD.

import FreeCAD as App
import FreeCADGui as Gui
from PySide2 import QtWidgets, QtCore
import Part

class ScalingApp(QtWidgets.QWidget):
    def __init__(self):
        super().__init__()
        self.setWindowTitle("Scaling Demonstration")
        self.setGeometry(100, 100, 300, 200)
       
        # Dictionary to store original shapes
        self.original_shapes = {}
       
        # Create UI elements
        layout = QtWidgets.QVBoxLayout()
       
        self.info_label = QtWidgets.QLabel("Select an object and set scaling factors:")
        layout.addWidget(self.info_label)
       
        self.scale_x_label = QtWidgets.QLabel("Scale Factor X:")
        layout.addWidget(self.scale_x_label)
        self.scale_x_input = QtWidgets.QLineEdit("1.0")
        layout.addWidget(self.scale_x_input)
       
        self.scale_y_label = QtWidgets.QLabel("Scale Factor Y:")
        layout.addWidget(self.scale_y_label)
        self.scale_y_input = QtWidgets.QLineEdit("1.0")
        layout.addWidget(self.scale_y_input)
       
        self.scale_z_label = QtWidgets.QLabel("Scale Factor Z:")
        layout.addWidget(self.scale_z_label)
        self.scale_z_input = QtWidgets.QLineEdit("1.0")
        layout.addWidget(self.scale_z_input)
       
        self.apply_button = QtWidgets.QPushButton("Apply Scaling")
        self.apply_button.clicked.connect(self.apply_scaling)
        layout.addWidget(self.apply_button)
       
        self.reset_button = QtWidgets.QPushButton("Reset Scaling")
        self.reset_button.clicked.connect(self.reset_scaling)
        layout.addWidget(self.reset_button)
       
        self.setLayout(layout)
   
    def apply_scaling(self):
        # Get selected object
        selected_objects = Gui.Selection.getSelection()
        if not selected_objects:
            QtWidgets.QMessageBox.warning(self, "Warning", "No object selected!")
            return
       
        obj = selected_objects[0]
       
        # Save the original shape if not already saved
        if obj.Name not in self.original_shapes:
            self.original_shapes[obj.Name] = obj.Shape.copy()
       
        # Get scaling factors
        try:
            scale_x = float(self.scale_x_input.text())
            scale_y = float(self.scale_y_input.text())
            scale_z = float(self.scale_z_input.text())
        except ValueError:
            QtWidgets.QMessageBox.warning(self, "Warning", "Invalid scaling factors!")
            return
       
        # Create scaling matrix
        scale_matrix = App.Matrix()
        scale_matrix.A11 = scale_x
        scale_matrix.A22 = scale_y
        scale_matrix.A33 = scale_z
       
        # Apply scaling transformation
        new_shape = obj.Shape.transformGeometry(scale_matrix)
       
        # Update the object's shape
        obj.Shape = new_shape
        obj.purgeTouched()  # Ensure updates are applied
        App.ActiveDocument.recompute()
       
        QtWidgets.QMessageBox.information(self, "Success", f"Scaling applied: X={scale_x}, Y={scale_y}, Z={scale_z}")
   
    def reset_scaling(self):
        # Get selected object
        selected_objects = Gui.Selection.getSelection()
        if not selected_objects:
            QtWidgets.QMessageBox.warning(self, "Warning", "No object selected!")
            return
       
        obj = selected_objects[0]
       
        # Check if the object has an original shape stored
        if obj.Name in self.original_shapes:
            obj.Shape = self.original_shapes[obj.Name]  # Restore the original shape
            obj.purgeTouched()
            App.ActiveDocument.recompute()
            QtWidgets.QMessageBox.information(self, "Reset", "Scaling reset to original state.")
        else:
            QtWidgets.QMessageBox.warning(self, "Warning", "No scaling history found for the selected object!")

# Function to create a sample object in the FreeCAD document
def create_sample_cube():
    doc = App.newDocument("ScalingApp")
    cube = doc.addObject("Part::Box", "SampleCube")
    cube.Length = 10
    cube.Width = 10
    cube.Height = 10
    App.ActiveDocument.recompute()
    Gui.SendMsgToActiveView("ViewFit")

# Run the application
if __name__ == "__main__":
    create_sample_cube()
    app = ScalingApp()
    app.show()

Scaling is a fundamental transformation in computer graphics that changes the size of an object. It can be uniform (same scaling factor for all directions) or non-uniform (different scaling factors for each direction).


1. Scaling Definition

Scaling modifies the dimensions of an object by multiplying its coordinates by scaling factors.

  • Uniform Scaling: The same scaling factor is applied to all axes.
  • Non-uniform Scaling: Different scaling factors are applied to each axis.

2. Scaling Formula

If a point P(x,y)P(x, y) is scaled, the resulting point P(x,y)P'(x', y') is computed as:

x=Sxxx' = S_x \cdot x y=Syyy' = S_y \cdot y

Where:

  • SxS_x: Scaling factor along the x-axis
  • SyS_y: Scaling factor along the y-axis

In 3D:

x=Sxx,y=Syy,z=Szzx' = S_x \cdot x, \quad y' = S_y \cdot y, \quad z' = S_z \cdot z

3. Homogeneous Coordinates for Scaling

To handle scaling using matrix operations, we represent points in homogeneous coordinates:

[xyz1]=[Sx0000Sy0000Sz00001][xyz1]\begin{bmatrix} x' \\ y' \\ z' \\ 1 \end{bmatrix} = \begin{bmatrix} S_x & 0 & 0 & 0 \\ 0 & S_y & 0 & 0 \\ 0 & 0 & S_z & 0 \\ 0 & 0 & 0 & 1 \end{bmatrix} \cdot \begin{bmatrix} x \\ y \\ z \\ 1 \end{bmatrix}

4. Types of Scaling

  1. Uniform Scaling:

    • The same factor is applied to all axes.
    • Maintains the object's shape.
    • Example: Enlarging or shrinking an object proportionally.
  2. Non-uniform Scaling:

    • Different factors are applied to each axis.
    • Can distort the object's shape.
    • Example: Stretching an object along one axis.
  3. Scaling with a Fixed Point:

    • Scaling typically operates about the origin. To scale about a different point Pf(xf,yf)P_f(x_f, y_f), the steps are:
      1. Translate the object so that PfP_f is at the origin.
      2. Apply the scaling transformation.
      3. Translate the object back to its original position.

5. Applications of Scaling

  • Resizing objects in 2D/3D scenes.
  • Zooming in and out.
  • Adjusting texture sizes in rendering.
  • Simulating growth or shrinkage in animations.

No comments: