class DMJ_ClipShapeCircle(common.ulb:ClipShape) {
; Circular clipping shape.
public:
import "common.ulb"
func DMJ_ClipShapeCircle(Generic pparent)
ClipShape.ClipShape(pparent)
complex c ; computed center of circle
complex s ; working point
float d = 0.0
float a = m_Aspect
if (@p_circletype == 0) ; bounding box method
c = (@p_circleupperleft + @p_circlelowerright) * 0.5
if (abs(real(@p_circleupperleft)-real(@p_circlelowerright)) > abs(imag(@p_circleupperleft)-imag(@p_circlelowerright)))
d = sqr(abs(imag(@p_circleupperleft)-imag(@p_circlelowerright)) * 0.5)
else
d = sqr(abs(real(@p_circleupperleft)-real(@p_circlelowerright)) * 0.5)
endif
s = c + sqrt(d)
elseif (@p_circletype == 1) ; center and edge method
c = @p_circlecenter
s = @p_circleedge
s = real(s-c)*a + flip(imag(s-c)) + c ; correct for aspect distortion, centered on c
d = |s - c|
elseif (@p_circletype == 2) ; opposite edges method
c = (@p_circleedge1 + @p_circleedge2) * 0.5
s = @p_circleedge1
s = real(s-c)*a + flip(imag(s-c)) + c ; correct for aspect distortion, centered on c
d = |s - c|
elseif (@p_circletype == 3) ; three edge points method
; from mathworld.wolfram.com
float ca = real(@p_circleedge1)*(imag(@p_circleedge2)*1-imag(@p_circleedge3)*1) - \
imag(@p_circleedge1)*(real(@p_circleedge2)*1-real(@p_circleedge3)*1) + \
1*(real(@p_circleedge2)*imag(@p_circleedge3)-real(@p_circleedge3)*imag(@p_circleedge2))
float cd = -( (|@p_circleedge1|)*(imag(@p_circleedge2)*1-imag(@p_circleedge3)*1) - \
imag(@p_circleedge1)*((|@p_circleedge2|)*1-(|@p_circleedge3|)*1) + \
1*((|@p_circleedge2|)*imag(@p_circleedge3)-(|@p_circleedge3|)*imag(@p_circleedge2)) )
float ce = (|@p_circleedge1|)*(real(@p_circleedge2)*1-real(@p_circleedge3)*1) - \
real(@p_circleedge1)*((|@p_circleedge2|)*1-(|@p_circleedge3|)*1) + \
1*((|@p_circleedge2|)*real(@p_circleedge3)-(|@p_circleedge3|)*real(@p_circleedge2))
float cf = -( (|@p_circleedge1|)*(real(@p_circleedge2)*imag(@p_circleedge3)-real(@p_circleedge3)*imag(@p_circleedge2)) - \
real(@p_circleedge1)*((|@p_circleedge2|)*imag(@p_circleedge3)-(|@p_circleedge3|)*imag(@p_circleedge2)) + \
imag(@p_circleedge1)*((|@p_circleedge2|)*real(@p_circleedge3)-(|@p_circleedge3|)*real(@p_circleedge2)) )
c = -cd / (2*ca) + flip( -ce / (2*ca) )
d = (sqr(cd)+sqr(ce)) / (4*sqr(ca)) - cf/ca
s = c + sqrt(d)
endif
; save results of circle definition
m_Center = c
m_Edge = s
m_Radius = sqrt(d)
m_RadiusSquared = sqr(m_Radius + @p_expansion)
endfunc
complex func Iterate(complex pz)
complex c = m_Center ; computed center of circle
complex p = pz ; working point (generally, pixel/z)
complex s = m_Edge ; computed edge point of the circle
float d = m_RadiusSquared ; computed radius squared, including expansion
float a = m_Aspect
p = real(p-c)*a + flip(imag(p-c)) + c ; correct for aspect distortion, centered on c
if (|c-p| <= d)
m_Solid = true
endif
return pz
endfunc
func SetHandles(Handles phandles)
ClipShape.SetHandles(phandles)
int handletype = 1 ; assume we're using square handles
float allowrotation = 0.0 ; assume we're zeroing out rotations
if (@p_expansion != 0) ; we've expanded the edge
handletype = 6 ; use double-arrow handles for edge points
allowrotation = 1.0 ; allow the handles to rotate
endif
if (@p_circletype == 0)
m_Handles.SetHandleCount(3,4,0,0)
m_Handles.SetHandlePoint(-1,3,-22028,0,m_Center,0)
m_Handles.SetHandlePoint(-1,1,-1262,0,@p_circleupperleft,0)
m_Handles.SetHandlePoint(-1,1,-908,0,@p_circlelowerright,0)
complex ur = real(@p_circlelowerright) + flip(imag(@p_circleupperleft))
complex ll = real(@p_circleupperleft) + flip(imag(@p_circlelowerright))
m_Handles.SetHandleLine(-1,2,false,@p_circleupperleft,ur)
m_Handles.SetHandleLine(-1,2,true,ur,@p_circlelowerright)
m_Handles.SetHandleLine(-1,2,true,@p_circlelowerright,ll)
m_Handles.SetHandleLine(-1,2,true,ll,@p_circleupperleft)
elseif (@p_circletype == 1)
m_Handles.SetHandleCount(2,0,0,0)
m_Handles.SetHandlePoint(-1,3,-22028,0,m_Center,0)
m_Handles.SetHandlePoint(-1,handletype,-983095,0,@p_circleedge,allowrotation*atan2(@p_circleedge-@p_circlecenter)*180/#pi)
elseif (@p_circletype == 2)
m_Handles.SetHandleCount(3,0,0,0)
m_Handles.SetHandlePoint(-1,3,-22028,0,m_Center,0)
m_Handles.SetHandlePoint(-1,handletype,1,0,@p_circleedge1,allowrotation*atan2(@p_circleedge1-m_Center)*180/#pi)
m_Handles.SetHandlePoint(-1,handletype,2,0,@p_circleedge2,allowrotation*atan2(@p_circleedge2-m_Center)*180/#pi)
elseif (@p_circletype == 3)
m_Handles.SetHandleCount(4,0,0,0)
m_Handles.SetHandlePoint(-1,3,-22028,0,m_Center,0)
m_Handles.SetHandlePoint(-1,handletype,1,0,@p_circleedge1,allowrotation*atan2(@p_circleedge1-m_Center)*180/#pi)
m_Handles.SetHandlePoint(-1,handletype,2,0,@p_circleedge2,allowrotation*atan2(@p_circleedge2-m_Center)*180/#pi)
m_Handles.SetHandlePoint(-1,handletype,3,0,@p_circleedge3,allowrotation*atan2(@p_circleedge3-m_Center)*180/#pi)
endif
if (@p_expansion != 0)
m_Handles.SetHandleCount(-1,-1,1,-1)
m_Handles.SetHandleCircle(-1,3,m_Center,m_Radius)
endif
endfunc
protected:
complex m_Center
complex m_Edge
float m_Radius
float m_RadiusSquared
default:
title = "Circle"
int param v_dmj_clipshapecircle
caption = "Version (DMJ_ClipShapeCircle)"
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_dmj_clipshapecircle < 100
endparam
float param p_expansion
caption = "Expansion"
default = 0.0
hint = "Sets the amount the shape will be expanded. Positive values will increase the size of the shape, negative values will decrease the size of the shape."
endparam
int param p_circletype
caption = "Define Circle By"
default = 2
enum = "bounding box" "center and edge" "opposite edges" "three edge points"
hint = "Choose how you want to define where the circle is. Different methods are useful in different circumstances."
endparam
complex param p_circleupperleft
caption = "Box Upper Left"
default = #center - 1/#magn + flip(1/#magn)
visible = (@p_circletype == 0)
hint = "Sets the upper left corner of the bounding box that the circle fits in. Note that if your image is rotated, and you're not using screen-relative clipping, the bounding box for your circle will be rotated along with the image. In that case, you may find 'center and edge' easier to use."
endparam
complex param p_circlelowerright
caption = "Box Lower Right"
default = #center + 1/#magn - flip(1/#magn)
visible = (@p_circletype == 0)
hint = "Sets the upper left corner of the bounding box that the circle fits in. Note that if your image is rotated, and you're not using screen-relative clipping, the bounding box for your circle will be rotated along with the image. In that case, you may find 'center and edge' easier to use."
endparam
complex param p_circlecenter
caption = "Circle Center"
default = #center
visible = (@p_circletype == 1)
hint = "Sets the center of the circle. If you're not sure exactly where the center should go, you may find 'opposite edges' easier to use."
endparam
complex param p_circleedge
caption = "Circle Edge"
default = #center + 1/#magn
visible = (@p_circletype == 1)
hint = "Sets the edge of the circle. If you need the edge to line up with something else in the image, you may find 'bounding box' easier to use."
endparam
complex param p_circleedge1
caption = "Circle Edge 1"
default = #center - 1/#magn
visible = (@p_circletype == 2 || @p_circletype == 3)
hint = "Sets one of the edge points of the circle."
endparam
complex param p_circleedge2
caption = "Circle Edge 2"
default = #center + 1/#magn
visible = (@p_circletype == 2 || @p_circletype == 3)
hint = "Sets one of the edge points of the circle."
endparam
complex param p_circleedge3
caption = "Circle Edge 3"
default = #center + flip(1/#magn)
visible = (@p_circletype == 3)
hint = "Sets one of the edge points of the circle."
endparam
}