Преглед на файлове

added conversion helpers for matlab
added examples for using the python wrappers in matlab


Former-commit-id: 4e4cadbbcf5e2865112da5c538fea6ee5ac6478b

Daniele Panozzo преди 9 години
родител
ревизия
6cfbe683d7

+ 0 - 59
python/matlab/CurvatureDirections.m

@@ -1,59 +0,0 @@
-V = py.igl.eigen.MatrixXd();
-F = py.igl.eigen.MatrixXi();
-py.igl.read_triangle_mesh('../tutorial/shared/fertility.off', V, F);
-
-% Alternative discrete mean curvature
-HN = py.igl.eigen.MatrixXd();
-L = py.igl.eigen.SparseMatrixd();
-M = py.igl.eigen.SparseMatrixd();
-Minv = py.igl.eigen.SparseMatrixd();
-
-
-py.igl.cotmatrix(V,F,L)
-py.igl.massmatrix(V,F,py.igl.MASSMATRIX_TYPE_VORONOI,M)
-
-py.igl.invert_diag(M,Minv)
-
-% Laplace-Beltrami of position
-HN = -Minv*(L*V)
-
-% Extract magnitude as mean curvature
-H = HN.rowwiseNorm()
-
-% Compute curvature directions via quadric fitting
-PD1 = py.igl.eigen.MatrixXd()
-PD2 = py.igl.eigen.MatrixXd()
-
-PV1 = py.igl.eigen.MatrixXd()
-PV2 = py.igl.eigen.MatrixXd()
-
-py.igl.principal_curvature(V,F,PD1,PD2,PV1,PV2)
-
-% Mean curvature
-H = 0.5*(PV1+PV2)
-
-viewer = py.igl.viewer.Viewer()
-viewer.data.set_mesh(V, F)
-
-% Compute pseudocolor
-C = py.igl.eigen.MatrixXd()
-py.igl.parula(H,true,C)
-
-viewer.data.set_colors(C)
-
-% Average edge length for sizing
-avg = py.igl.avg_edge_length(V,F)
-
-% Draw a blue segment parallel to the minimal curvature direction
-red = py.iglhelpers.p2e(py.numpy.array([[0.8,0.2,0.2]]))
-blue = py.iglhelpers.p2e(py.numpy.array([[0.2,0.2,0.8]]))
-
-viewer.data.add_edges(V + PD1*avg, V - PD1*avg, blue)
-
-% Draw a red segment parallel to the maximal curvature direction
-viewer.data.add_edges(V + PD2*avg, V - PD2*avg, red)
-
-% Hide wireframe
-viewer.core.show_lines = false
-
-viewer.launch()

+ 18 - 0
python/matlab/example1.m

@@ -0,0 +1,18 @@
+%% Launch the external viewer
+launch_viewer;
+
+%% Load a mesh in OFF format
+V = py.igl.eigen.MatrixXd();
+F = py.igl.eigen.MatrixXi();
+py.igl.readOFF('../tutorial/shared/beetle.off', V, F);
+
+%% Scale the x coordinate in matlab
+V = p2m(V);
+V(:,1) = V(:,1) * 2;
+V = m2p(V);
+
+%% Plot the mesh
+viewer = py.tcpviewer_single.TCPViewer();
+viewer.data.set_mesh(V, F);
+viewer.launch();
+

+ 60 - 0
python/matlab/example2.m

@@ -0,0 +1,60 @@
+% Launch the external viewer
+launch_viewer;
+
+V = py.igl.eigen.MatrixXd();
+F = py.igl.eigen.MatrixXi();
+py.igl.read_triangle_mesh('../tutorial/shared/fertility.off', V, F);
+
+% Alternative discrete mean curvature
+HN = py.igl.eigen.MatrixXd();
+L = py.igl.eigen.SparseMatrixd();
+M = py.igl.eigen.SparseMatrixd();
+Minv = py.igl.eigen.SparseMatrixd();
+
+
+py.igl.cotmatrix(V,F,L);
+py.igl.massmatrix(V,F,py.igl.MASSMATRIX_TYPE_VORONOI,M);
+
+py.igl.invert_diag(M,Minv);
+
+% Laplace-Beltrami of position
+HN = -Minv*(L*V);
+
+% Extract magnitude as mean curvature
+H = HN.rowwiseNorm();
+
+% Compute curvature directions via quadric fitting
+PD1 = py.igl.eigen.MatrixXd();
+PD2 = py.igl.eigen.MatrixXd();
+
+PV1 = py.igl.eigen.MatrixXd();
+PV2 = py.igl.eigen.MatrixXd();
+
+py.igl.principal_curvature(V,F,PD1,PD2,PV1,PV2);
+
+% Mean curvature
+H = 0.5*(PV1+PV2);
+
+viewer = py.tcpviewer_single.TCPViewer();
+viewer.data.set_mesh(V, F);
+
+% Compute pseudocolor
+C = py.igl.eigen.MatrixXd();
+py.igl.parula(H,true,C);
+
+viewer.data.set_colors(C);
+
+% Average edge length for sizing
+avg = py.igl.avg_edge_length(V,F);
+
+% Draw a blue segment parallel to the minimal curvature direction
+red  = m2p([0.8,0.2,0.2]);
+blue = m2p([0.2,0.2,0.8]);
+
+viewer.data.add_edges(V + PD1*avg, V - PD1*avg, blue);
+
+% Draw a red segment parallel to the maximal curvature direction
+viewer.data.add_edges(V + PD2*avg, V - PD2*avg, red);
+
+% Plot
+viewer.launch()

+ 3 - 0
python/matlab/launch_viewer.m

@@ -0,0 +1,3 @@
+system('python tcpviewer_single.py&');
+
+pause(0.1) % Wait a bit for the viewer to start

+ 19 - 0
python/matlab/m2p.m

@@ -0,0 +1,19 @@
+% Converts a Matlab matrix to a python-wrapped Eigen Matrix
+function [ P ] = m2p( M )
+    if (isa(M, 'double'))
+        % Convert the matrix to a python 1D array
+        a = py.array.array('d',reshape(M,1,numel(M)));
+        % Then convert it to a eigen type
+        t = py.igl.eigen.MatrixXd(a.tolist());
+        % Finally reshape it back
+        P = t.MapMatrix(uint16(size(M,1)),uint16(size(M,2)));
+    elseif (isa(M, 'integer'))
+        % Convert the matrix to a python 1D array
+        a = py.array.array('i',reshape(M,1,numel(M)));
+        % Then convert it to a eigen type
+        t = py.igl.eigen.MatrixXi(a.tolist());
+        % Finally reshape it back
+        P = t.MapMatrix(uint16(size(M,1)),uint16(size(M,2)));
+    else
+        error('Unsupported numerical type.');
+    end

+ 17 - 0
python/matlab/p2m.m

@@ -0,0 +1,17 @@
+% Converts a python-wrapped Eigen Matrix to a Matlab matrix
+function [ M ] = p2m( P )
+    if py.repr(py.type(P)) == '<class ''igl.eigen.MatrixXd''>'
+        % Convert it to a python array first
+        t = py.array.array('d',P);
+        % Reshape it
+        M = reshape(double(t),P.rows(),P.cols());
+    elseif py.repr(py.type(P)) == '<class ''igl.eigen.MatrixXi''>'
+        % Convert it to a python array first
+        t = py.array.array('i',P);
+        % Reshape it
+        M = reshape(int32(t),P.rows(),P.cols());
+    else
+        error('Unsupported numerical type.');
+    end
+end
+

+ 0 - 12
python/matlab/t102DrawMesh.m

@@ -1,12 +0,0 @@
-% Load a mesh in OFF format
-V = py.igl.eigen.MatrixXd();
-F = py.igl.eigen.MatrixXi();
-py.igl.readOFF('../tutorial/shared/beetle.off', V, F);
-
-V
-
-% Plot the mesh
-viewer = py.tcpviewer.TCPViewer()
-viewer.data.set_mesh(V, F)
-viewer.launch()
-

+ 19 - 0
python/py_vector.cpp

@@ -47,6 +47,25 @@ py::class_<Type> bind_eigen_2(py::module &m, const char *name,
 
           return;
         })
+        .def("__init__", [](Type &m, std::vector<Scalar>& b) {
+          if (b.size() == 0)
+          {
+            new (&m) Type(0, 0);
+            return;
+          }
+
+          // Size checks
+          unsigned rows = b.size();
+          unsigned cols = 1;
+
+          new (&m) Type(rows, cols);
+
+          m.resize(rows,cols);
+          for (unsigned i=0;i<rows;++i)
+            m(i,0) = b[i];
+
+          return;
+        })
         .def("__init__", [](Type &m, py::buffer b) {
             py::buffer_info info = b.request();
             if (info.format != py::format_descriptor<Scalar>::value())

+ 57 - 22
python/tcpviewer.py

@@ -1,45 +1,80 @@
 import socket
-import multiprocessing
+import threading
 import igl
 import array
+import time
 
 HOST = 'localhost'                 # Symbolic name meaning all available interfaces
 PORT = 50008              # Arbitrary non-privileged port
 
-def worker(data):
-    viewer = igl.viewer.Viewer()
-    temp = list(data)
-    viewer.deserialize(temp)
-    viewer.launch(True,False)
-    return
-
-class TCPViewer(igl.viewer.Viewer):
-    def launch(self):
-        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        s.connect((HOST, PORT))
-        a = array.array('u',self.serialize())
-        s.sendall(a)
-        s.close()
+def worker(viewer,lock,s):
 
-if __name__ == "__main__": # The main script is a server
-    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-    s.bind((HOST, PORT))
-    s.listen(1)
     print("TCP iglviewer server listening on port " + str(PORT))
     try:
         while True:
             conn, addr = s.accept()
+            lock.acquire()
             slist = []
             while True:
-                buf = conn.recv(4096)
+                buf = conn.recv(10000000)
                 if not buf:
                     break
                 slist.append(buf.decode('unicode_internal','ignore'))
             conn.close()
 
             data = ''.join(slist)
+            temp = list(data)
+
+            isempty = viewer.data.V.rows() == 0
+            viewer.data.deserialize(temp)
+            if isempty and viewer.data.V.rows() != 0:
+                viewer.core.align_camera_center(viewer.data.V,viewer.data.F)
+
+            lock.release()
 
-            t = multiprocessing.Process(target=worker, args=(data,))
-            t.start()
     except:
         s.close()
+    return
+
+class TCPViewer(igl.viewer.Viewer):
+    def launch(self):
+        try:
+            s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+            s.connect((HOST, PORT))
+            a = array.array('u',self.data.serialize())
+            s.sendall(a)
+            s.close()
+        except:
+            print("Failed to open socket, is tcpviewer running?")
+
+if __name__ == "__main__": # The main script is a server
+
+    ## Try to open the socket first
+    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
+    try:
+        s.bind((HOST, PORT))
+    except:
+        print("Failed to bind, port already used.")
+        exit(1)
+    s.listen(1)
+
+    viewer = igl.viewer.Viewer()
+
+    lock = threading.Lock()
+    t = threading.Thread(target=worker, args=(viewer,lock,s,))
+    t.setDaemon(True)
+    t.start()
+
+    viewer.core.is_animating = True
+    # viewer.data.dirty = int(0x03FF)
+
+    viewer.launch_init(True,False)
+    done = False
+    while not done:
+        lock.acquire()
+        done = not viewer.launch_rendering(False)
+        lock.release()
+
+        time.sleep(0.000001) # DO NOT REMOVE ME
+
+    viewer.launch_shut()

+ 0 - 69
python/tcpviewer_single.py

@@ -1,69 +0,0 @@
-import socket
-import threading
-import igl
-import array
-import time
-
-HOST = 'localhost'                 # Symbolic name meaning all available interfaces
-PORT = 50008              # Arbitrary non-privileged port
-
-def worker(viewer,lock):
-    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-    s.bind((HOST, PORT))
-    s.listen(1)
-    print("TCP iglviewer server listening on port " + str(PORT))
-    try:
-        while True:
-            conn, addr = s.accept()
-            lock.acquire()
-            slist = []
-            while True:
-                buf = conn.recv(4096)
-                if not buf:
-                    break
-                slist.append(buf.decode('unicode_internal','ignore'))
-            conn.close()
-
-            data = ''.join(slist)
-            temp = list(data)
-
-            isempty = viewer.data.V.rows() == 0
-            viewer.data.deserialize(temp)
-            if isempty and viewer.data.V.rows() != 0:
-                viewer.core.align_camera_center(viewer.data.V,viewer.data.F)
-
-            lock.release()
-
-    except:
-        s.close()
-    return
-
-class TCPViewer(igl.viewer.Viewer):
-    def launch(self):
-        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
-        s.connect((HOST, PORT))
-        a = array.array('u',self.data.serialize())
-        s.sendall(a)
-        s.close()
-
-if __name__ == "__main__": # The main script is a server
-    viewer = igl.viewer.Viewer()
-
-    lock = threading.Lock()
-    t = threading.Thread(target=worker, args=(viewer,lock,))
-    t.setDaemon(True)
-    t.start()
-
-    viewer.core.is_animating = True
-    # viewer.data.dirty = int(0x03FF)
-
-    viewer.launch_init(True,False)
-    done = False
-    while not done:
-        lock.acquire()
-        done = not viewer.launch_rendering(False)
-        lock.release()
-
-        time.sleep(0.000001) # DO NOT REMOVE ME
-
-    viewer.launch_shut()

+ 0 - 24
python/tutorial/102_DrawMeshTCP.py

@@ -1,24 +0,0 @@
-import igl
-import tcpviewer
-import time
-
-# Load a mesh in OFF format
-V = igl.eigen.MatrixXd()
-F = igl.eigen.MatrixXi()
-time1 = time.time()
-# igl.read_triangle_mesh("../tutorial/shared/armadillo.obj", V, F)
-igl.readOFF("../tutorial/shared/beetle.off", V, F)
-time2 = time.time()
-
-
-print('Loading mesh (%d vertices) %0.3f ms' % (V.rows(),(time2-time1)*1000.0))
-
-
-# Plot the mesh
-viewer = tcpviewer.TCPViewer()
-viewer.data.set_mesh(V, F)
-viewer.core.align_camera_center(V,F)
-viewer.launch()
-time3 = time.time()
-
-print('Sending to TCP viewer took %0.3f ms' % ((time3-time2)*1000.0))

+ 27 - 0
python/tutorial/102_DrawMesh_TCP.py

@@ -0,0 +1,27 @@
+## This is a test application for the TCPViewer
+
+# Add the igl library to the modules search path
+import sys, os
+sys.path.insert(0, os.getcwd() + "/../")
+
+import os
+import time
+
+# Launch the tcp viewer
+os.system("python ../tcpviewer.py&")
+
+# Wait for it to set up the socket
+time.sleep(1)
+
+import igl
+import tcpviewer
+
+# Read a mesh
+V = igl.eigen.MatrixXd()
+F = igl.eigen.MatrixXi()
+igl.readOFF('../../tutorial/shared/beetle.off', V, F)
+
+# Send it to the viewer
+viewer = tcpviewer.TCPViewer()
+viewer.data.set_mesh(V, F)
+viewer.launch()