;+
; Set properties of the ellipsoid.
;
; @keyword pos {in}{optional}{type=fltarr(3)} A three-element vector, [x, y, z],
; specifying the position of the center of the ellipsoid, measured in
; data units
; @keyword radius {in}{optional}{type=fltarr(3)} a floating point number
; representing the radius of the ellipsoid (measured in data units)
; in the x-, y-, and z-directions
; @keyword density {in}{optional}{type=float} A floating point number
; representing the density at which the vertices should be
; generated along the surface of the orb
; @keyword parent {in}{optional} not used, included only for compatibility to
; Orb class
; @keyword _extra {in}{optional}{type=keywords} keywords to
; IDLgrModel::setProperty or IDLgrPolygon::setProperty
;-
pro mggrellipsoid::setProperty, pos=pos, radius=radius, density=density, parent=parent, $
_extra=e
compile_opt strictarr
on_error, 2
; Pass along extraneous keywords to the superclass and/or to the
; polygon used to represent the orb.
self->IDLgrModel::setProperty, _extra=e
self.oPoly->setProperty, _extra=e
self.pos = n_elements(pos) eq 3 ? pos : self.pos
case n_elements(radius) of
0 :
1 : self.radius = fltarr(3) + radius
3 : self.radius = radius
else : message, 'RADIUS must be 1- or 3-elements array'
endcase
self.density = n_elements(density) eq 1 ? density : self.density
; Rebuild the polygon according to keyword settings.
self->buildPoly
end
;+
; Get properties of the ellipsoid.
;
; @keyword pos {out}{optional}{type=fltarr(3)} set to a named variable to get
; a three-element vector, [x, y, z], specifying the position of the
; center of the ellipsoid, measured in data units
; @keyword radius {out}{optional}{type=fltarr(3)} set to a named variable to get
; a floating point number representing the radius of the ellipsoid
; (measured in data units) in the x-, y-, and z-directions
; @keyword density {out}{optional}{type=float} set to a named variable to get a
; floating point number representing the density at which the vertices
; should be generated along the surface of the orb
; @keyword pobj {out}{optional}{type=object} set to a named variable to get a
; IDLgrPolygon reference for the ellipsoid verts and conn
; @keyword _ref_extra {out}{optional}{type=keywords} keywords to
; IDLgrPolygon::getProperty or IDLgrModel::getProperty
;-
pro mggrellipsoid::getProperty, pos=pos, radius=radius, density=density,$
pobj=pobj, _ref_extra=re
compile_opt strictarr
; Retrieve extra properties from polygon first, then model
; so that the model settings (for common keywords) will prevail.
self.oPoly->getProperty, _extra=re
self->IDLgrModel::getProperty, _extra=re
pos = self.pos
radius = self.radius
density = self.density
pobj = self.oPoly
end
;+
; Prints position, radius, and density of the ellipsoid for debugging purposes.
;-
pro mggrellipsoid::print
compile_opt strictarr
print, self.pos
print, self.radius
print, self.density
end
;+
; Sets the vertex and connectivity arrays for the polygon used to
; represent the orb.
;-
pro mggrellipsoid::buildPoly
compile_opt strictarr
; Number of rows and columns of vertices is based upon the density
; property.
nrows = long(20.0 * self.density)
ncols = long(20.0 * self.density)
if (nrows lt 2) then nrows = 2
if (ncols lt 2) then ncols = 2
; Create the vertex list and the connectivity array.
nverts = nrows * ncols + 2
nconn = (ncols * (nrows - 1) * 5) + (2 * ncols * 4)
conn = lonarr(ncols * (nrows - 1) * 5 + 2 * ncols * 4)
verts = fltarr(3, nverts)
if (self.texture ne 0) then tex = fltarr(2, nverts)
; Fill in the vertices.
i = 0L
j = 0L
k = 0L
tzinc = !pi / float(nrows + 1)
tz = !pi / 2.0 - tzinc
for k = 0, nrows - 1 do begin
t = 0
if (self.texture ne 0) then begin
tinc = 2.0 * !pi / float(ncols - 1)
endif else begin
tinc = 2.0 * !pi / float(ncols)
endelse
for j = 0, ncols - 1 do begin
verts[0, i] = self.radius[0] * cos(tz) * cos(t) + self.pos[0]
verts[1, i] = self.radius[1] * cos(tz) * sin(t) + self.pos[1]
verts[2, i] = self.radius[2] * sin(tz) + self.pos[2]
if (self.texture ne 0) then begin
tex[0, i] = t / (2.0 * !pi)
tex[1, i] = (tz + (!pi / 2.0)) / !pi
endif
t += tinc
++i
endfor
tz -= tzinc
endfor
top = i
verts[0, i] = self.pos[0]
verts[1, i] = self.pos[1]
verts[2, i] = self.radius[2] + self.pos[2]
++i
bot = i
verts[0, i] = self.pos[0]
verts[1, i] = self.pos[1]
verts[2, i] = - self.radius[2] + self.pos[2]
if (self.texture ne 0) then begin
tex[0, i] = 0.5
tex[1, i] = 0.0
tex[0, i - 1] = 0.5
tex[1, i - 1] = 1.0
endif
; Fill in the connectivity array.
i = 0
for k = 0, nrows - 2 do begin
for j = 0, ncols - 1 do begin
conn[i] = 4
conn[i + 4] = k * ncols + j
w = k * ncols + j + 1L
if (j eq (ncols-1)) then w = k * ncols
conn[i + 3] = w
w = k * ncols + j + 1L + ncols
if (j eq (ncols - 1)) then w = k * ncols + ncols
conn[i + 2] = w
conn[i + 1] = k * ncols + j + ncols
i += 5L
if ((self.texture ne 0) and (j eq (ncols - 1))) then i -= 5L
endfor
endfor
for j = 0, ncols - 1 do begin
conn[i] = 3
conn[i + 3] = top
conn[i + 2] = j + 1L
if (j eq (ncols - 1)) then conn[i + 2] = 0
conn[i + 1] = j
i += 4L
if ((self.texture ne 0) and (j eq (ncols - 1))) then i -= 4L
endfor
for j=0, ncols - 1 do begin
conn[i] = 3
conn[i + 3] = bot
conn[i + 2] = j + (nrows - 1L) * ncols
conn[i + 1] = j + (nrows - 1L) * ncols + 1L
if (j eq (ncols - 1)) then conn[i + 1] = (nrows - 1L) * ncols
i += 4L
if ((self.texture ne 0) and (j eq (ncols - 1))) then i -= 4L
endfor
self.oPoly->setProperty, data=verts, polygons=conn
if (self.texture ne 0) then self.oPoly->setProperty, texture_coord=tex
end
;+
; Free resources.
;-
pro mggrellipsoid::cleanup
compile_opt strictarr
; Cleanup the polygon object used to represent the orb.
obj_destroy, self.oPoly
; Cleanup the superclass.
self->IDLgrModel::cleanup
end
;+
; Initialize ellipsoid.
;
; @returns 1 for success, 0 for failure
;
; @keyword pos {in}{optional}{type=fltarr(3)}{default=[0.0, 0.0, 0.0]} A
; three-element vector, [x, y, z], specifying the position of the
; center of the ellipsoid, measured in data units
; @keyword radius {in}{optional}{type=fltarr(3)}{default=[1.0, 1.0, 1.0]
; floating point numbers representing the radius of the ellipsoid
; (measured in data units) in the x-, y-, and z-directions
; @keyword density {in}{optional}{type=float}{default=1.0} A floating point
; number representing the density at which the vertices should be
; generated along the surface of the orb
; @keyword tex_coords {in}{optional}{type=boolean) set this keyword to a nonzero
; value if texture map coordinates are to be generated for the orb
; @keyword _extra {in}{optional}{type=keywords} keywords to IDLgrModel::init
;-
function mggrellipsoid::init, pos=pos, radius=radius, density=density, $
tex_coords=texCoords, _extra=e
compile_opt strictarr
on_error, 2
if (self->IDLgrModel::init(_extra=e) ne 1) then return, 0
self.pos = n_elements(pos) eq 3 ? pos : [0.0, 0.0, 0.0]
case n_elements(radius) of
0 : self.radius = fltarr(3) + 1.0
1 : self.radius = fltarr(3) + radius
3 : self.radius = radius
else : message, 'RADIUS must be 1- or 3-elements array'
endcase
self.density = n_elements(density) eq 1 ? density : 1.0
self.texture = n_elements(texCoords) eq 1 ? texCoords : 0
; Initialize the polygon object that will be used to represent
; the orb.
self.oPoly = obj_new('IDLgrPolygon', shading=1, /reject, _extra=e)
self->add, self.oPoly
; Build the polygon vertices and connectivity based on property settings.
self->buildPoly
return, 1
end
;+
; Define member variables.
;
; @field pos position of the center of the ellipsoid
; @field radius floating point numbers representing the radius of the ellipsoid
; (measured in data units) in the x-, y-, and z-directions
; @field density value representing the density at which the vertices should be
; generated along the surface of the orb
; @field texture boolean for whether texture coordinates are needed for the
; ellipsoid
; @field oPoly IDLgrPolygon object containing verts and conn of the ellipsoid
;-
pro mggrellipsoid__define
struct = { MGgrEllipsoid, $
inherits IDLgrModel, $
pos : [0.0, 0.0, 0.0], $
radius : fltarr(3), $
density : 0.0, $
texture : 0, $
oPoly : obj_new() $
}
end