<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40"><head><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=us-ascii"><meta name=Generator content="Microsoft Word 15 (filtered medium)"><style><!--
/* Font Definitions */
@font-face
        {font-family:Wingdings;
        panose-1:5 0 0 0 0 0 0 0 0 0;}
@font-face
        {font-family:"Cambria Math";
        panose-1:2 4 5 3 5 4 6 3 2 4;}
@font-face
        {font-family:Calibri;
        panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoPlainText, li.MsoPlainText, div.MsoPlainText
        {mso-style-priority:99;
        mso-style-link:"Plain Text Char";
        margin:0in;
        font-size:11.0pt;
        font-family:"Calibri",sans-serif;}
span.PlainTextChar
        {mso-style-name:"Plain Text Char";
        mso-style-priority:99;
        mso-style-link:"Plain Text";
        font-family:"Calibri",sans-serif;}
.MsoChpDefault
        {mso-style-type:export-only;
        font-family:"Calibri",sans-serif;}
@page WordSection1
        {size:8.5in 11.0in;
        margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
        {page:WordSection1;}
/* List Definitions */
@list l0
        {mso-list-id:505438371;
        mso-list-type:hybrid;
        mso-list-template-ids:841226268 750165118 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l0:level1
        {mso-level-start-at:0;
        mso-level-number-format:bullet;
        mso-level-text:\F0B7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;
        mso-fareast-font-family:Calibri;
        mso-bidi-font-family:"Times New Roman";}
@list l0:level2
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l0:level3
        {mso-level-number-format:bullet;
        mso-level-text:\F0A7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l0:level4
        {mso-level-number-format:bullet;
        mso-level-text:\F0B7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l0:level5
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l0:level6
        {mso-level-number-format:bullet;
        mso-level-text:\F0A7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l0:level7
        {mso-level-number-format:bullet;
        mso-level-text:\F0B7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l0:level8
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l0:level9
        {mso-level-number-format:bullet;
        mso-level-text:\F0A7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l1
        {mso-list-id:1536119629;
        mso-list-type:hybrid;
        mso-list-template-ids:-762048082 67698689 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l1:level1
        {mso-level-number-format:bullet;
        mso-level-text:\F0B7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l1:level2
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l1:level3
        {mso-level-number-format:bullet;
        mso-level-text:\F0A7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l1:level4
        {mso-level-number-format:bullet;
        mso-level-text:\F0B7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l1:level5
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l1:level6
        {mso-level-number-format:bullet;
        mso-level-text:\F0A7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l1:level7
        {mso-level-number-format:bullet;
        mso-level-text:\F0B7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l1:level8
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l1:level9
        {mso-level-number-format:bullet;
        mso-level-text:\F0A7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l2
        {mso-list-id:2032023977;
        mso-list-type:hybrid;
        mso-list-template-ids:965490198 750165118 67698691 67698693 67698689 67698691 67698693 67698689 67698691 67698693;}
@list l2:level1
        {mso-level-start-at:0;
        mso-level-number-format:bullet;
        mso-level-text:\F0B7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;
        mso-fareast-font-family:Calibri;
        mso-bidi-font-family:"Times New Roman";}
@list l2:level2
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l2:level3
        {mso-level-number-format:bullet;
        mso-level-text:\F0A7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l2:level4
        {mso-level-number-format:bullet;
        mso-level-text:\F0B7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l2:level5
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l2:level6
        {mso-level-number-format:bullet;
        mso-level-text:\F0A7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
@list l2:level7
        {mso-level-number-format:bullet;
        mso-level-text:\F0B7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Symbol;}
@list l2:level8
        {mso-level-number-format:bullet;
        mso-level-text:o;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:"Courier New";}
@list l2:level9
        {mso-level-number-format:bullet;
        mso-level-text:\F0A7;
        mso-level-tab-stop:none;
        mso-level-number-position:left;
        text-indent:-.25in;
        font-family:Wingdings;}
ol
        {margin-bottom:0in;}
ul
        {margin-bottom:0in;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]--></head><body lang=EN-US link="#0563C1" vlink="#954F72" style='word-wrap:break-word'><div class=WordSection1><p class=MsoPlainText>Based on the elegant list-comprehension expressions in the following two lines<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><ul style='margin-top:0in' type=disc><li class=MsoPlainText style='mso-list:l2 level1 lfo2'><span style='font-family:"Courier New"'>coord = Coordinate( point = [ tuple(pt) for pt in point_coordinates] ),<o:p></o:p></span></li></ul><p class=MsoPlainText><span style='font-family:"Courier New"'><o:p> </o:p></span></p><ul style='margin-top:0in' type=disc><li class=MsoPlainText style='mso-list:l2 level1 lfo2'><span style='font-family:"Courier New"'>color = Color( color = [tuple(c) for c in point_colors])<o:p></o:p></span></li></ul><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>These types of expressions could certainly be added to MFVec3f, MFColor, etc. which would continue flexibility of current duck typing across full diversity of X3D field types.<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>Presumably the key precondition for applying them will be  proper detection of type, e.g.<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><ul style='margin-top:0in' type=disc><li class=MsoPlainText style='mso-list:l2 level1 lfo2'><span style='font-family:"Courier New"'>if isinstance(value, np.array) # and further checking that elements of arrays are tuples<o:p></o:p></span></li></ul><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>I will eventually be able to fumble around and get something hacked together, putting it into the fieldtype value setter. (Or keep them as a separate utility if numpy dependency needs to be avoided.)<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>If you can help with type checking to avoid numpy GIGO problems, please toss me an example.  Presumably if we can get numpy working then we can support other lists of tuples as well.<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>FWIW, example target excerpted from package x3d.py follows.  (The triple-hash ### blocks were form used prior to latest refactoring, they’ll get deleted once confirmed that all functionality is handled in new code.)<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>===========================<o:p></o:p></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>class MFVec3f(_X3DArrayField):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    """<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    Field type MFVec3f is an array of SFVec3f values. Individual singleton SFVec3f array values are optionally separated by commas in XML syntax.<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    """<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'># […snip…]<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    @property # getter - - - - - - - - - -<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    def value(self):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        """ Provide typed value of this field instance. """<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        return self.__value<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    @value.setter<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    def value(self, value):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        """ The value setter only allows correctly typed values. """<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        if isinstance(value,SFVec3f):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>            value = value.value # dereference<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        elif value is None:<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>            value = MFVec3f.DEFAULT_VALUE()<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>            # if _DEBUG: print('...DEBUG... set value to MFVec3f.DEFAULT_VALUE()=' + str(MFVec3f.DEFAULT_VALUE()))<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        elif isinstance(value, list):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>            for each in value: # check that elements are not tuples<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                if isinstance(each, tuple):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                    break<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>            else: # no tuples found, create 3-tuples<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                value = [(x, y, z) for x, y, z in value]<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###     elif not isinstance(value, list) and isValidSFVec3f(value):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###         print(' upcast to MF type', value)<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###         value = MFVec3f(SFVec3f(value))<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        elif isinstance(value, list):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>            if not value is None and not (isinstance(value,list) and len(value) == 0):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                _newValue = []<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                for each in value:<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                    _newValue.append(SFVec3f(each).value)<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                # if _DEBUG: print('...DEBUG... assign list, value=' + str(value), ', type=' + str(type(value)), ', _newValue=' + str(_newValue),flush=True)<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                value = _newValue<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        elif isinstance(value, str):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>            value = [ float(value) ]<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        self.__value = value<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'># and<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    def append(self, value=None):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        """ Add to existing value list, first ensuring that a correctly typed value is applied. """<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        if  not value is None:<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>            # if _DEBUG: print('...DEBUG... append to list, value=' + str(self.__value), ', type=' + str(type(self.__value)), ', value=' + str(value),flush=True)<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>            if isinstance(value,SFVec3f):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                self.__value.append(value.value) # dereference<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>            elif not isinstance(value,list) and not isinstance(value,MFVec3f):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                self.__value.append(SFVec3f(value).value) # checks validity<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>            elif (isinstance(value,list) and len(value) > 0) or isinstance(value,MFVec3f):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                for each in value:<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                    self.__value.append(SFVec3f(each).value) # checks validity<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>            elif isinstance(value,str):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                self.__value.append(SFVec3f(value).value) # checks validity<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###     if  not value is None:<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###         if isValidSFVec3f(value):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###             if isinstance(value, SFVec3f):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###                 value = SFVec3f(value).value # dereference value from base type<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###             self.__value.append(value)<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###         elif isValidMFVec3f(value):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###             for each in value:<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###                 while isinstance(each, list) and len(each) == 1:<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###                     each = each[0] # dereference<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###                 if isinstance(each, SFVec3f):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###                     each = each.value # dereference<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###                 self.__value.append(each)<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###         else:<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ###             assertValidMFVec3f(value) # report type failure<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    def __bool__(self):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        if not isinstance(self.__value,list):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'><o:p> </o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>            print('*** x3d.py internal error, MFVec3f self.__value type=' + str(type(self.__value)) + ' is not a list', flush=True)<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        return len(self.__value) > 0<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'># […snip…]<o:p></o:p></span></p><p class=MsoPlainText>===========================<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>all the best, Don<o:p></o:p></p><p class=MsoPlainText>-- <o:p></o:p></p><p class=MsoPlainText>Don Brutzman  Naval Postgraduate School, Code USW/Br        brutzman@nps.edu<o:p></o:p></p><p class=MsoPlainText>Watkins 270,  MOVES Institute, Monterey CA 93943-5000 USA    +1.831.656.2149<o:p></o:p></p><p class=MsoPlainText>X3D graphics, virtual worlds, Navy robotics https:// faculty.nps.edu/brutzman<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>-----Original Message-----<br>From: Brutzman, Donald (Don) (CIV) <brutzman@nps.edu> <br>Sent: Sunday, February 27, 2022 7:42 AM<br>To: vmarchetti@kshell.com<br>Cc: X3D Public Mailing List (x3d-public@web3d.org) <x3d-public@web3d.org>; Hans Moritz Guenther <hgunther@mit.edu>; Brutzman, Donald (Don) (CIV) <brutzman@nps.edu><br>Subject: RE: example python code using numpy library</p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>[cc: Moritz]<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>Looks like our enterprise mail server (configured by Microsoft in a cloud)<o:p></o:p></p><p class=MsoPlainText>scrubs all .py attachments.<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>I was able to retrieve your example by going to the Web3D-archived version<o:p></o:p></p><p class=MsoPlainText>at<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>* <a href="http://web3d.org/pipermail/x3d-public_web3d.org/2022-February/016818.html"><span style='color:windowtext;text-decoration:none'>http://web3d.org/pipermail/x3d-public_web3d.org/2022-February/016818.html</span></a><o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>and then saving attachment.bin as NumpyExample.py<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>Thank you Vince, looks interesting.  Am also copying source here in case<o:p></o:p></p><p class=MsoPlainText>anyone has further retrieval difficulties.<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>NumpyExample.py<o:p></o:p></p><p class=MsoPlainText>======================================<o:p></o:p></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>"""<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>Script to demonstrate setting the values of the coordinates, colors (by<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>vertex), and index arrays defining<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>an IndexedTriangleSet from data values in numpy arrays.<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>Tested Feb 24 2022 with x3d version 4.0.51   installed with pip<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>Vince Marchetti 24 Feb 2022<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>license : <a href="https://creativecommons.org/licenses/by/4.0/"><span style='color:windowtext;text-decoration:none'>https://creativecommons.org/licenses/by/4.0/</span></a><o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>"""<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>from x3d.x3d import *<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>import numpy as np<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>def colored_tetrahedron( radius ):<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    """<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    returns (3,) tuple of numpy arrays<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    points_coordinate : a (N,3) array of vertex coordinates<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    points_colors : (N,3) array of colors<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    face_indices : (K,3) array of integer indices into points_* arrays<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    <o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    where N = number of vertices in mesh (N=4 for this tetrahedron)<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>          K = number of triangle faces in mesh (K=5 for tetrahedron)<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>          <o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    defines a mesh for a tetrahedron inscribed in sphere of with radius<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>specified by argument<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    centered at origin<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    """<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    point_coordinates = np.array([<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        ( 0.000,  1.000,   0.000),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        (-0.816, -0.344,   0.471),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        ( 0.816, -0.344,   0.471),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        ( 0.000, -0.344,  -0.942),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ]) * radius<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    <o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    point_colors = np.array([<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        (1.00,1.00,0.40),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        (0.70,0.40,1.00),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        (0.00,0.80,0.00),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        (1.00,0.80,0.90),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ])<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    face_indices = np.array([<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        (0,1,2),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        (0,2,3),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        (0,3,1),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>        (3,2,1)<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ])<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    <o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    return point_coordinates,point_colors,face_indices<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    <o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    <o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>point_coordinates,point_colors,face_indices = colored_tetrahedron( 2.0 )<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>newModel=X3D(profile='Immersive',version='3.3',<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>  head=head(<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    children=[<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    meta(content='NumpyExample.x3d',name='title'),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    meta(content='example of using Numpy library to generate coordinate<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>geometry and color',name='description'),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    meta(content='24 Feb 2022',name='created'),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    meta(content='Vince Marchetti',name='creator'),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'> <o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>meta(content='https://www.web3d.org/x3d/content/examples/license.html',name=<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>'license')<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>  ]),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>  Scene=Scene(<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    <o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    children=[<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    WorldInfo(title='NumpyExample.x3d'),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    Viewpoint(DEF='ViewUpClose', description='Initial Viewpoint'),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    Shape(geometry=IndexedTriangleSet(<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                # following code converts rank-2 numpy array of integers<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>into a python list for setting value of index field<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                index = list( face_indices.flatten() ),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                <o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                # following code converts rank-2 numpy array of float values<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>into a Python list of Python tuples of floats<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                # to set x3d values of type MFVec3f and MFColor<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                coord = Coordinate( point = [ tuple(pt) for pt in<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>point_coordinates] ),<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                color = Color( color = [tuple(c) for c in point_colors])<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>                )<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>          )<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>    ])<o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>) <o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>newModelXML= newModel.XML() <o:p></o:p></span></p><p class=MsoPlainText><span style='font-size:10.0pt;font-family:"Courier New"'>print(newModelXML)<o:p></o:p></span></p><p class=MsoPlainText>======================================<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>all the best, Don<o:p></o:p></p><p class=MsoPlainText>-- <o:p></o:p></p><p class=MsoPlainText><span style='font-family:"Courier New"'>Don Brutzman  Naval Postgraduate School, Code USW/Br        <a href="mailto:brutzman@nps.edu"><span style='color:windowtext;text-decoration:none'>brutzman@nps.edu</span></a><o:p></o:p></span></p><p class=MsoPlainText><span style='font-family:"Courier New"'>Watkins 270,  MOVES Institute, Monterey CA 93943-5000 USA    +1.831.656.2149<o:p></o:p></span></p><p class=MsoPlainText><span style='font-family:"Courier New"'>X3D graphics, virtual worlds, Navy robotics <a href="https://faculty.nps.edu/brutzman"><span style='color:windowtext;text-decoration:none'>https://faculty.nps.edu/brutzman</span></a><o:p></o:p></span></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>-----Original Message-----<o:p></o:p></p><p class=MsoPlainText>From: <a href="mailto:vmarchetti@kshell.com"><span style='color:windowtext;text-decoration:none'>vmarchetti@kshell.com</span></a> <<a href="mailto:vmarchetti@kshell.com"><span style='color:windowtext;text-decoration:none'>vmarchetti@kshell.com</span></a>> <o:p></o:p></p><p class=MsoPlainText>Sent: Friday, February 25, 2022 3:50 AM<o:p></o:p></p><p class=MsoPlainText>To: X3D-Public <<a href="mailto:x3d-public@web3d.org"><span style='color:windowtext;text-decoration:none'>x3d-public@web3d.org</span></a>>; Brutzman, Donald (Don) (CIV)<o:p></o:p></p><p class=MsoPlainText><<a href="mailto:brutzman@nps.edu"><span style='color:windowtext;text-decoration:none'>brutzman@nps.edu</span></a>><o:p></o:p></p><p class=MsoPlainText>Subject: example python code using numpy library<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>Attached is a Python script that defines the coordinates, colors, and face<o:p></o:p></p><p class=MsoPlainText>indices for a tetrahedron as numpy rank-2 arrays, then converts those values<o:p></o:p></p><p class=MsoPlainText>in order to initialize the field values for an x3d IndexedTriangleSet node.<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>This may serve as a demonstration example for using numpy together with the x3d package.<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>This script runs with the pip installation of x3d and was tested at version 4.0.51<o:p></o:p></p><p class=MsoPlainText><o:p> </o:p></p><p class=MsoPlainText>Vince Marchetti<o:p></o:p></p></div></body></html>