class DMJ_FastMosaic(common.ulb:UserTransform) {
; Mosaic transformation.
; (Ported from dmj3.uxf:dmj3-FastMosaic)
public:
import "common.ulb"
; $define debug
func DMJ_FastMosaic(Generic pparent)
UserTransform.UserTransform(pparent)
; create objects
m_Formula = new @f_formula(this)
m_Transform = new @f_transform(this)
m_Points = new ComplexArray(@p_pointcount)
m_Closest = new DMJ_FastClosestPoint()
m_FoundIndices = new IntegerArray(3)
m_FoundDistances = new FloatArray(3)
m_FoundPoints = new ComplexArray(3)
; compute first point
complex zg = m_Formula.Init(0)
m_Transform.Init(0)
zg = m_Transform.Iterate(zg)
; compute remaining points
int j = 0
while (j < @p_pointcount)
m_Points.m_Elements[j] = zg
zg = m_Formula.Iterate(zg)
zg = m_Transform.Iterate(zg)
j = j + 1
endwhile
; prep point index
Array m_Dummy = 0
m_Closest.SetPointData(m_Points, m_Dummy)
endfunc
complex func Iterate(complex pz)
if (@p_edgewidth > 0)
$ifdef debug
int testx = 400
int testy = 400
$endif
; get an ordered list of close points
int k = m_Closest.GetClosestPointSet(pz, 3, m_FoundIndices, m_FoundDistances, m_FoundPoints)
$ifdef debug
if (#x == testx && #y == testy)
print("GetClosestPointSet results:")
print("1: ", m_FoundIndices.m_Elements[0], " ", m_FoundDistances.m_Elements[0], " ", m_FoundPoints.m_Elements[0])
print("2: ", m_FoundIndices.m_Elements[1], " ", m_FoundDistances.m_Elements[1], " ", m_FoundPoints.m_Elements[1])
print("3: ", m_FoundIndices.m_Elements[2], " ", m_FoundDistances.m_Elements[2], " ", m_FoundPoints.m_Elements[2])
endif
$endif
; get distances to closest and second-closest edge
complex q1 = (m_FoundPoints.m_Elements[1]-m_FoundPoints.m_Elements[0]) / \
cabs(m_FoundPoints.m_Elements[1]-m_FoundPoints.m_Elements[0])
complex q2 = (m_FoundPoints.m_Elements[2]-m_FoundPoints.m_Elements[0]) / \
cabs(m_FoundPoints.m_Elements[2]-m_FoundPoints.m_Elements[0])
float d1 = real((pz-(m_FoundPoints.m_Elements[1]+m_FoundPoints.m_Elements[0])*0.5) * conj(q1))
float d2 = real((pz-(m_FoundPoints.m_Elements[2]+m_FoundPoints.m_Elements[0])*0.5) * conj(q2))
; determine if this is an edge point or a tile point
bool isedge = abs(d1) < @p_edgewidth || abs(d2) < @p_edgewidth
; check for solid color use
if (@p_soliduse == 1)
if (!isedge)
m_Solid = true
endif
elseif (@p_soliduse == 2)
if (isedge)
m_Solid = true
endif
endif
if (!m_Solid)
if (@p_edgestretchmode > 0 && @p_edgestretch != 0.0 && isedge)
; apply edge stretching
float d = d2
complex q = q2
if (abs(d1) < @p_edgewidth && abs(d1) < abs(d2))
d = d1
q = q1
endif
if (@p_edgestretchmode == 2)
pz = pz - q * @p_edgestretch * d
elseif (@p_edgestretchmode == 1)
pz = pz + q * @p_edgestretch * (abs(d) - @p_edgewidth)
endif
else
; apply ordinary mosaic
complex c = m_FoundPoints.m_Elements[0]
pz = c + \
(@p_tileforcecenter - c) * @p_tileforce + \
(pz - c) * @p_tilestretch
endif
endif
return pz
else
int k = m_Closest.GetClosestPoint(pz)
complex c = m_Points.m_Elements[m_Closest.m_Order.m_Elements[k]]
pz = c + \
(@p_tileforcecenter - c) * @p_tileforce + \
(pz - c) * @p_tilestretch
return pz
endif
endfunc
protected:
Formula m_Formula
Transform m_Transform
ComplexArray m_Points
DMJ_FastClosestPoint m_Closest
IntegerArray m_FoundIndices
FloatArray m_FoundDistances
ComplexArray m_FoundPoints
default:
title = "Mosaic"
int param v_dmj_fastmosaic
caption = "Version (DMJ_FastMosaic)"
default = 101
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_dmj_fastmosaic < 100
endparam
heading
caption = "Point Creation"
endheading
int param p_pointcount
caption = "Tile Count"
default = 1000
hint = "Sets the number of mosaic tiles. More tiles will take longer to compute but will allow smaller tiles."
endparam
Formula param f_formula
caption = "Point Creator"
default = DMJ_FormulaGenerators
hint = "This selects the formula you will use to create the points that are used as the centers of the mosaic tiles. If you use a random formula (the default) the tiles will be distributed evenly. You can use other formulas to produce different groupings of tiles."
endparam
UserTransform param f_transform
caption = "Point Transform"
default = NullTransform
hint = "After points have been generated, you may choose to have them transformed in some way before being used."
endparam
heading
caption = "Edge & Tile Effects"
endheading
float param p_edgewidth
caption = "Edge Width"
default = 0.0
min = 0.0
hint = "Sets the width of any edges. Note that if you set this value to 0.0, all edge effects are disabled."
endparam
int param p_soliduse
caption = "Solid Color Use"
default = 0
enum = "none" "tiles" "edges"
visible = @p_edgewidth > 0.0
hint = "Sets which areas will be flagged for solid colors. Note that using solid colors will disable some edge and tile effects."
endparam
int param p_edgestretchmode
caption = "Edge Stretching"
default = 0
enum = "none" "from inside" "from outside"
visible = @p_edgewidth > 0.0 && @p_soliduse != 2
hint = "Chooses how edge stretching should be used. This will allow the edge to be 'stretched' from either the inside edge (nearest the tile center) or the outside edge (between the tiles)."
endparam
float param p_edgestretch
caption = " Stretch Amount"
default = 0.0
visible = @p_edgewidth > 0.0 && @p_soliduse != 2 && @p_edgestretchmode > 0
hint = "Sets the amount of stretching the edge will have. Use 0.0 for no effect and 1.0 for full effect (other values may provide interesting results)."
endparam
float param p_tilestretch
caption = "Tile Scale"
default = 0.0
visible = @p_soliduse != 1
hint = "Sets tile scale, the zoom applied relative to the tile focus point. Use a value of 0.0 to get solid tiles (all tile points map to the focus point). Use a value of 1.0 to leave tiles unchanged (useful if you have enabled edge effects). Use other values for different effects."
endparam
float param p_tileforce
caption = "Tile Shift"
default = 0.0
visible = @p_soliduse != 1
hint = "Forces tiles to appear centered at a different location, rather than each tile's focus point. Use a value of 0.0 to disable this effect; use a value of 1.0 for full effect (all tiles appear centered at the designated point). Use values in between to partially apply the effect."
endparam
complex param p_tileforcecenter
caption = " Shift Point"
default = (0,0)
visible = @p_soliduse != 1 && @p_tileforce != 0.0
hint = "This is the point all tiles will be shifted towards."
endparam
}