common
Class Transform

Object
  extended by common:Generic
      extended by common:Transform
Direct Known Subclasses:
ClipShape, UserTransform, UtilityTransform

class 
Generic:Transform

Transform base class.

This is a generic transform class. Its purpose is to take an arbitrary point and transform it into some other point. This roughly corresponds to UF's native transformation formula type. The advantage to writing a transform as a class is that then it can be used in many other places. Transform classes also support the notion that a sequence may yield a "solid" point, just as UF's transformation formulas do.

If you are migrating an existing transformation formula to a Transform-derived class, the process is fairly straightforward. Look at your global: and transform: sections. Any variables that are shared between the two should be declared in your protected: class section. The code in your global: section goes into the constructor. The code in your transform: section goes into the Iterate() function. Use m_Solid in place of #solid and use pz in place of #pixel. Whenever possible, try to avoid using other built-in values like #width or #screenpixel as this will make your class behave oddly when not being used to transform an entire fractal.

As an extra optional step, you may look at what you've placed in your Iterate() function and decide to refactor it. With a transformation formula, the transform: section is used only once per pixel. However, a Transform object can be used for this AND used to transform an entire sequence of values (for example, the entire sequence of iterated values from a fractal formula). If there are some computations you perform for your transformation that will be exactly the same for each of the values in that sequence, you may move them to the Init() function; this will improve the performance of your formula. Any variables holding the results of these computations will need to be declared in your protected: section so that they will be available to the Iterate() function.

IMPORTANT NOTE: If your transform is intended to be a user-selected class, you should probably derive from the UserTransform class rather than directly from Transform. The Transform family also includes UtilityTransform and ClipShape, so objects looking to allow Transforms will normally require them to be in the UserTransform subclass.


Ultra Fractal Source

Toggle UF Source Code Display

 class Transform(Generic) {
   ; Transform base class.
   ; <p>
   ; This is a generic transform class. Its purpose is to take
   ; an arbitrary point and transform it into some other point.
   ; This roughly corresponds to UF's native transformation
   ; formula type. The advantage to writing a transform as a
   ; class is that then it can be used in many other places.
   ; Transform classes also support the notion that a sequence
   ; may yield a "solid" point, just as UF's transformation
   ; formulas do.
   ; <p>
   ; If you are migrating an existing transformation formula
   ; to a Transform-derived class, the process is fairly
   ; straightforward. Look at your global: and transform:
   ; sections. Any variables that are shared between the two
   ; should be declared in your protected: class section.
   ; The code in your global: section goes into the constructor.
   ; The code in your transform: section goes into the Iterate()
   ; function. Use m_Solid in place of #solid and use pz in
   ; place of #pixel. Whenever possible, try to avoid using
   ; other built-in values like #width or #screenpixel as this
   ; will make your class behave oddly when not being used to
   ; transform an entire fractal.
   ; <p>
   ; As an extra optional step, you may look at what you've
   ; placed in your Iterate() function and decide to refactor it.
   ; With a transformation formula, the transform: section is
   ; used only once per pixel. However, a Transform object can
   ; be used for this AND used to transform an entire sequence
   ; of values (for example, the entire sequence of iterated
   ; values from a fractal formula). If there are some computations
   ; you perform for your transformation that will be exactly the
   ; same for each of the values in that sequence, you may move
   ; them to the Init() function; this will improve the performance
   ; of your formula. Any variables holding the results of these
   ; computations will need to be declared in your protected:
   ; section so that they will be available to the Iterate()
   ; function.
   ; <p>
   ; IMPORTANT NOTE: If your transform is intended to be a
   ; user-selected class, you should probably derive from the
   ; UserTransform class rather than directly from Transform.
   ; The Transform family also includes UtilityTransform and
   ; ClipShape, so objects looking to allow Transforms will
   ; normally require them to be in the UserTransform subclass.
   
 public:
   ; Constructor
   ;
   ; @param pparent a reference to the object creating the new object; typically, 'this'
   func Transform(Generic pparent)
     Generic.Generic(pparent)
   endfunc
   
   ; Set up for a sequence of values
   ; <p>
   ; This function will be called at the beginning of each
   ; sequence of values (e.g. at the beginning of each fractal
   ; orbit). It will be called even if only one value is being
   ; transformed (e.g. a normal transformation formula). Use
   ; this to perform any setup that is exactly the same for
   ; each value in the sequence being transformed.
   ;
   ; @param pz the value representing the sequence; for a normal transformation formula use, this will be #pixel. In some cases this may differ from the first value passed to Iterate() if the calling code applies some other transformations.
   func Init(complex pz)
     ; As part of the base class functionality, we set up
     ; a simple iteration counter and a flag to indicate
     ; whether the sequence yields a solid color or not.
     ; If you would like to re-use this, you will need to
     ; call Transform.Init() in your derived class's Init()
     ; function if you provide an Init() function. (If you
     ; don't have an Init() function, UF will call the base
     ; class Transform.Init() automatically.)
     m_Iterations = 0
     m_Solid = false
   endfunc
 
   ; Transform a single point within a sequence
   ; <p>
   ; After a sequence has been set up with Init(), this function
   ; will be called once for each value in the sequence. Note
   ; that all values in the sequence must be processed in order
   ; (they cannot be processed out of order). If the sequence
   ; contains only one value, Init() will still be called and
   ; then Iterate() will be called just once.
   ;
   ; @param pz the complex value to be transformed
   ; @return the transformed value
   complex func Iterate(complex pz)
     ; Update the iteration count. As with Init(), if you
     ; provide your own Iterate() function, as you almost
     ; certainly will, you would need to call Transform.Iterate()
     ; to get this functionality. However, since you would not
     ; need the default transformation, it is better to call
     ; Transform.IterateSilent() instead to update this value.
     ; Even higher performance could be obtained by just
     ; updating the iteration count manually; however, if you
     ; do this and the base Transform class is updated, your
     ; code might not inherit the functionality because you
     ; are not calling the base class.
     m_Iterations = m_Iterations + 1
     return pz
   endfunc
 
   ; Update internal counters without transforming a point
   ; <p>
   ; For some Transform classes, the actual transformation being
   ; performed changes for each value in the sequence (e.g.
   ; TrapTransform, which can rotate each iteration by a different
   ; amount). In some cases the calling code may determine in
   ; advance that a particular point does not need to be transformed
   ; (perhaps because it is not being used) but it still needs to be
   ; accounted for. This function is used in place of Iterate() for
   ; those situations; the Transform should update any internal
   ; state that changes between iterations within a sequence. Since
   ; no value is being transformed, no parameters are passed and no
   ; return value is provided.
   func IterateSilent()
     ; Perform the same iteration-count update as Iterate(), but
     ; don't return a value. See the comments in Iterate() for
     ; more information on when to call this.
     m_Iterations = m_Iterations + 1
   endfunc
 
   ; Test whether a sequence is solid-colored or not.
   ; <p>
   ; This function takes the place of the #solid flag in a native
   ; UF transformation formula. Since this is an object which may be
   ; used in a context other than a transformation formula, #solid
   ; may not be available to us. Instead, Iterate() should set an
   ; internal flag m_Solid and the calling code should use IsSolid()
   ; to test the value of this flag. For some Transform classes this
   ; test may be very involved, which is why it is available as a
   ; function rather than simply giving the calling code access to
   ; the m_Solid variable directly.
   ;
   ; @return a Boolean flag indicating whether the sequence is solid-colored or not.
   bool func IsSolid()
     return m_Solid
   endfunc
   
 protected:
   int m_Iterations    ; count the number of iterations
   bool m_Solid      ; flag indicating whether last pixel was solid or not
 
 default:
   int param v_transform
     caption = "Version (Transform)"
     default = 100
     hint = "This version parameter is used to detect when a change has been made to the formula that is incompatible with the previous version. When that happens, this field will reflect the old version number to alert you to the fact that an alternate rendering is being used."
     visible = @v_transform < 100
   endparam
 }
 


Constructor Summary
Transform()
           
Transform(Generic pparent)
          Constructor
 
Method Summary
 void Init(complex pz)
          Set up for a sequence of values
 boolean IsSolid()
          Test whether a sequence is solid-colored or not.
 complex Iterate(complex pz)
          Transform a single point within a sequence
 void IterateSilent()
          Update internal counters without transforming a point
 
Methods inherited from class common:Generic
GetParent
 
Methods inherited from class Object
 

Constructor Detail

Transform

public Transform(Generic pparent)
Constructor

Parameters:
pparent - a reference to the object creating the new object; typically, 'this'

Transform

public Transform()
Method Detail

Init

public void Init(complex pz)
Set up for a sequence of values

This function will be called at the beginning of each sequence of values (e.g. at the beginning of each fractal orbit). It will be called even if only one value is being transformed (e.g. a normal transformation formula). Use this to perform any setup that is exactly the same for each value in the sequence being transformed.

Parameters:
pz - the value representing the sequence; for a normal transformation formula use, this will be #pixel. In some cases this may differ from the first value passed to Iterate() if the calling code applies some other transformations.

Iterate

public complex Iterate(complex pz)
Transform a single point within a sequence

After a sequence has been set up with Init(), this function will be called once for each value in the sequence. Note that all values in the sequence must be processed in order (they cannot be processed out of order). If the sequence contains only one value, Init() will still be called and then Iterate() will be called just once.

Parameters:
pz - the complex value to be transformed
Returns:
the transformed value

IterateSilent

public void IterateSilent()
Update internal counters without transforming a point

For some Transform classes, the actual transformation being performed changes for each value in the sequence (e.g. TrapTransform, which can rotate each iteration by a different amount). In some cases the calling code may determine in advance that a particular point does not need to be transformed (perhaps because it is not being used) but it still needs to be accounted for. This function is used in place of Iterate() for those situations; the Transform should update any internal state that changes between iterations within a sequence. Since no value is being transformed, no parameters are passed and no return value is provided.


IsSolid

public boolean IsSolid()
Test whether a sequence is solid-colored or not.

This function takes the place of the #solid flag in a native UF transformation formula. Since this is an object which may be used in a context other than a transformation formula, #solid may not be available to us. Instead, Iterate() should set an internal flag m_Solid and the calling code should use IsSolid() to test the value of this flag. For some Transform classes this test may be very involved, which is why it is available as a function rather than simply giving the calling code access to the m_Solid variable directly.

Returns:
a Boolean flag indicating whether the sequence is solid-colored or not.