// Copyright (c) CNES 2008 // // This software is part of CelestLab, a CNES toolbox for Scilab // // This software is governed by the CeCILL license under French law and // abiding by the rules of distribution of free software. You can use, // modify and/ or redistribute the software under the terms of the CeCILL // license as circulated by CEA, CNRS and INRIA at the following URL // 'http://www.cecill.info'. //================================================================================== // Warning: the interface is now: CLx_stela_area(desc, typ, list) // list = list of rest of arguments. // for instance: CLx_stela_area(desc, "tumb", list(nbp, opts)); // The list is indicated by "{}" in the following lines. // // CLx_stela_area(desc, "tumb", { nbp [, opts] } ) // CLx_stela_area(desc, "spin", { direction, axis, nbp [, opts] } ) // CLx_stela_area(desc, "fix", { direction [, opts] } ) // CLx_stela_area(desc, "fixr", { direction, list(...) [, opts] } ) // // opts: structure containing the (optional) fields // - resol (integer) 1x1 - default = 10000 // - savePrefix (string) 1x1 - default = "": prefix for XML files (saving). "" => no file created // // direction: projection direction in body frame: 3xN or 3x1 // axis: rotation axis in body frame (spin): 3xN or 3x1 // nbp: (integer) number of projection planes: 1x1 // // list(...) : list of structures describing rotations of sub-parts: // id: (string) 1x1 // axis: 3xN or 3x1: rotation axis in body frame // ang: 1xN or 1x1: rotation angle // rcen: 3xN or 3x1: rotation center in sub-part frame (origin = sub-part ref position). Default is [0;0;0] // // Examples: // // desc = fullfile(CLx_setting_get("STELA_ROOT"), "examples/example_shap.xml"); // opts = struct("resol", 10000, "savePrefix", fullfile(TMPDIR, "tmpshap")); // opts = struct("resol", 20000); // // -- example 1 : no rotations of sub-parts // alpha = linspace(0, 2*%pi, 50); // direction = [cos(alpha); zeros(alpha); sin(alpha)]; // area = CLx_stela_area(desc, "fix", direction, opts); // // -- example 2 : with rotations of sub-parts // direction = [0;0;1]; // rotdesc = list(struct("id", "GS +Y1", "axis", [0;1;0], "ang", alpha)); // area = CLx_stela_area(desc, "fixr", direction, rotdesc, opts); // // -- example 3 : argument = object structure // alpha = linspace(0, 2*%pi, 50); // direction = [cos(alpha); zeros(alpha); sin(alpha)]; // obj = CLx_stela_areaLoad(desc); // area = CLx_stela_area(obj, "fix", direction, opts); // //================================================================================== function [area] = CLx_stela_area(desc, typ, lvarargin) // ----------------------------------- // tumbling mode // nbp: 1x1 // area: 1x1 // ----------------------------------- function [area] = area_tumb(jarea, nbp) // check type and size if (typeof(nbp) <> "constant" | size(nbp, "*") <> 1 | round(nbp) <> nbp | nbp < 1) CLx__error("Invalid size or type for input argument nbp"); end jinfo = jinvoke(jarea, "computeTumbling", nbp); status = jinvoke(jinfo, "getStatus", jvoid); if (status <> 0) msg = jinvoke(jinfo, "getMsg", jvoid); CLx__error(msg); end area = jinvoke(jarea, "getValue", jvoid); jremove(jinfo); endfunction // ----------------------------------- // spinning mode // d: 3xN or 3x1 // axis: 3xN or 3x1 // area: 1xN // ----------------------------------- function [area] = area_spin(jarea, d, axis, nbp) // check type and size N = max(size(d,2), size(axis,2)); if (typeof(d) <> "constant" | size(d, 1) <> 3 | (size(d, 2) <> 1 & size(d, 2) <> N)) CLx__error("Invalid size or type for input argument direction"); end if (typeof(axis) <> "constant" | size(axis, 1) <> 3 | (size(axis, 2) <> 1 & size(axis, 2) <> N)) CLx__error("Invalid size or type for input argument axis"); end if (typeof(nbp) <> "constant" | size(nbp, "*") <> 1 | round(nbp) <> nbp | nbp < 1) CLx__error("Invalid size or type for input argument nbp"); end if (size(d,2) < N); d = d * ones(1,N); end if (size(axis,2) < N); axis = axis * ones(1,N); end jinfo = jinvoke(jarea, "computeSpinning", d, axis, nbp); status = jinvoke(jinfo, "getStatus", jvoid); if (status <> 0) msg = jinvoke(jinfo, "getMsg", jvoid); CLx__error(msg); end area = jinvoke(jarea, "getValue", jvoid); jremove(jinfo); endfunction // ----------------------------------- // fixed direction // d: 3xN // area: 1xN // ----------------------------------- function [area] = area_fix(jarea, d) if (typeof(d) <> "constant" | size(d, 1) <> 3) CLx__error("Invalid size or type for input argument direction"); end jinfo = jinvoke(jarea, "computeFixedDir", d); status = jinvoke(jinfo, "getStatus", jvoid); if (status <> 0) msg = jinvoke(jinfo, "getMsg", jvoid); CLx__error(msg); end area = jinvoke(jarea, "getValue", jvoid); jremove(jinfo); endfunction // ----------------------------------- // fixed direction + rotation of sub-parts // d: 3xN or 3x1 // l: list(struct) - elements: size 1 or N // area: 1xN // ----------------------------------- function [area] = area_fix_rot(jarea, d, l) // max number of columns of fields function [N] = maxdim(s) N = 0; for name = matrix(fieldnames(s),1, -1) N = max(N, size(s(name),2)); end endfunction // check/adjust rotation structure function [s] = verif_struct(s, N) s = s; if (~isfield(s,"id")); CLx__error("Field id missing in structure"); end if (~isfield(s,"axis")); CLx__error("Field axis missing in structure"); end if (~isfield(s,"ang")); CLx__error("Field ang missing in structure"); end if (~isfield(s,"rcen")); s.rcen = [0;0;0]; end if (typeof(s.id) <> "string" | size(s.id,"*") <> 1 | .. typeof(s.axis) <> "constant" | size(s.axis, 1) <> 3 | (size(s.axis, 2) <> 1 & size(s.axis, 2) <> N) |.. typeof(s.ang) <> "constant" | size(s.ang, 1) <> 1 | (size(s.ang, 2) <> 1 & size(s.ang, 2) <> N) | .. typeof(s.rcen) <> "constant" | size(s.rcen, 1) <> 3 | (size(s.rcen, 2) <> 1 & size(s.rcen, 2) <> N)) CLx__error("Invalid rotation elements structure"); end if (size(s.axis,2) <> N); s.axis = s.axis * ones(1,N); end if (size(s.ang,2) <> N); s.ang = s.ang * ones(1,N); end if (size(s.rcen,2) <> N); s.rcen = s.rcen * ones(1,N); end endfunction // max dimension (columns) N = size(d, 2); for (k = 1:lstsize(l)) N = max(N, maxdim(l(k))); end if (typeof(d) <> "constant" | size(d, 1) <> 3 | (size(d, 2) <> 1 & size(d, 2) <> N)) CLx__error("Invalid size or type of input argument direction"); end if (typeof(l) <> "list") CLx__error("Invalid size or type of input argument list"); end if (size(d,2) <> N); d = d * ones(1,N); end // generate args (compact form) ids = []; axes = []; angs = []; rcens = []; for (k = 1:lstsize(l)) s = verif_struct(l(k), N); // vectors: size=N ids = [ids, s.id]; axes = [axes, s.axis]; angs = [angs, s.ang]; rcens = [rcens, s.rcen]; end jinfo = jinvoke(jarea, "computeFixedDirRot", d, ids, axes, angs, rcens); status = jinvoke(jinfo, "getStatus", jvoid); if (status <> 0) msg = jinvoke(jinfo, "getMsg", jvoid); CLx__error(msg); end area = jinvoke(jarea, "getValue", jvoid); jremove(jinfo); endfunction // Process arguments : // remove last element of varargin (opts) if structure and check contents // args = ret of arguments function [opts, args] = getopts(l) // default values opts = struct(); opts.resol = 10000; opts.savePrefix = ""; args = l; if (size(args) < 1); return; end if (typeof(args($)) <> "st"); return; end x = args($); args($) = null(); for name = matrix(fieldnames(x),1, -1) val = x(name); if (name == "resol") if (typeof(val) <> "constant" | size(val, "*") <> 1 | round(val) <> val | val < 1) CLx__error("Invalid size or type for option resol"); end elseif (name == "savePrefix") if (typeof(val) <> "string" | size(val, "*") <> 1) CLx__error("Invalid size or type for option savePrefix"); end val = stripblanks(val, %t); else CLx__error("Invalid option: " + name); end opts(name) = val; end endfunction // load a object function loadobj(jarea, obj) jimport fr.cnes.celestlab.celestlabx.area.AreaScene; // check fields ref_names = ["id", "shap", "dim", "z_axis", "x_axis", "orig"]; ref_types = ["string", "string", "constant", "constant", "constant", "constant"]; ref_nrows = [1, 1, 3, 3, 3, 3]; names = matrix(fieldnames(obj),1, -1); if (setdiff(names, ref_names) <> [] | setdiff(ref_names, names) <> []) CLx__error("Invalid field names"); end N = size(obj.id, 2); for (k = 1 : size(names,2)) name = names(k); if (typeof(obj(name)) <> ref_types(k)) CLx__error("Invalid type for field " + name); end if (size(obj(name),1) <> ref_nrows(k) | size(obj(name),2) <> N) CLx__error("Invalid size for field " + name); end end jareascene = jnewInstance(AreaScene); // initialize sub-parts (id, type, sizes) jinfo = jinvoke(jareascene, "setShapes", obj.id, obj.shap, obj.dim); status = jinvoke(jinfo, "getStatus", jvoid); if (status <> 0) msg = jinvoke(jinfo, "getMsg", jvoid); CLx__error(msg); end // initialize sub-parts' frames jinvoke(jareascene, "setShapeFrames", obj.z_axis, obj.x_axis, obj.orig); // sets the "scene" jinvoke(jarea, "setScene", jareascene); jremove(jareascene); endfunction // ----------------------------------- // MAIN // ----------------------------------- area = []; // Check STELA is available if (~CLx__stelaAvailable()) CLx__error("STELA is not available"); end // Get the area computation instance jimport fr.cnes.celestlab.celestlabx.area.Area; jimport fr.cnes.celestlab.celestlabx.area.AreaInfo; jarea = jnewInstance(Area); // check arguments number: nbargs = argn(2); // output if (nbargs <> 3) CLx__error("Invalid number of inputs arguments"); end if (typeof("typ") <> "string" | typeof("lvarargin") <> "string") CLx__error("Invalid input arguments"); end // Load descriptor if (typeof(desc) == "string") // XML file jinfo = jinvoke(jarea, "load", desc); status = jinvoke(jinfo, "getStatus", jvoid); if (status <> 0) msg = jinvoke(jinfo, "getMsg", jvoid); CLx__error(msg); end elseif (typeof(desc) == "st") // Object structure loadobj(jarea, desc); else CLx__error("Invalid descriptor type"); end // check options [opts, args] = getopts(lvarargin); // resolution jinvoke(jarea, "setResolution", opts.resol); // save prefix jinvoke(jarea, "setSavePrefix", opts.savePrefix); nbargs = size(args); if (typ == "tumb") if (nbargs == 1) // args = nbp area = area_tumb(jarea, args(1)); else Cx__error("Invalid number of input arguments"); end elseif (typ == "spin") if (nbargs == 3) // args = dir, axis, nbp area = area_spin(jarea, args(1), args(2), args(3)); else CLx__error("Invalid number of input arguments"); end elseif (typ == "fix") if (nbargs == 1) // args = dir area = area_fix(jarea, args(1)); else CLx__error("Invalid number of input arguments"); end elseif (typ == "fixr") if (nbargs == 2) // args = dir, list area = area_fix_rot(jarea, args(1), args(2)); else CLx__error("Invalid number of input arguments"); end else CLx__error("Invalid argument"); end // Note: statement not reached if errors occurred ! // (but simpler this way) // NOTE : jremove : necessary ? jremove(jarea); endfunction