;+ ; 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