I have a set of 8 normal vectors in 3D space. I need to plot a cuboid with lateral wings from these vectors:
whereas vectors 4 to 6 are just the negatives (opposite sides) of the first three and the last two vectors are identical to the first one and make up the wings.
The goal is to plot this object with each surface having a different color so that I can count the pixels of each color afterward for different sets of normal vectors (i.e. determining the visibility of partially obstructed surfaces).
I have found the patch function which can plot polygons with individual colors and takes the coordinates of the vertices for input. However, I do know the dimension of each surface, but the coordinates of the vertices need to be somehow calculated for each set of normals vectors. Any suggestions on how to approach this task?
EDIT
I may have found a solution: I just noticed that view allows defined azimuth and elevation angles and thus "rotation" of the object. With the compution of azimuth and elevation from the normal vectors, the calculation of the vertices becomes unnecessary.
Related
Say we are creating a calibration lookup table for a device, shown in the plot below. The theta represents different phase values, and the r represents different magnitude values. The calibration setpoints are shown in blue circles, and are taken at every N degrees of phase and N values of magnitude. For every setpoint, we measure the actual device output and obtain the red coordinates, which describe the resulting phase and magnitude. Thus for every blue setpoint, we observe the device outputting red points.
The question now is, I want to set the device to a value of the green circle with orange ring. How do I calculate what the setpoint should be (green circle) to set the device to in order to obtain green/orange on the output?
The issue I am having is that for every 2D setpoint (mag, phase), the resultant data is 2D (mag, phase). In addition, magnitude and phase are not independent variables (fixing phase and changing only magnitude, the resulting phase output does change).
So what basic math/logic should I use to perform the necessary interpolation?
How about treating this like a registration problem. For example, you could use an affine transformation as the model between the measured and calibrated points? For each cell (i.e., the 4 blue points in your figure) compute a least squares estimate of the affine transformation between the blue and red points. Then for new points apply the corresponding transformation to get the green point you want. Here and here are some SO questions that discuss this. In addition, you might consider estimating and applying the transformation directly in magnitude/phase space.
I have some binary images that want to classify them base on shape of them in MATLAB. If they have circular or elliptical shape they belong to class one,if they have elliptical shape with dent in their boundary they belong to class two. I dont know how can I use this feature. Can any body help me with this?
You can use the eccentricity property in regionprops. From MATLAB documentation of eccentricity:
The eccentricity is the ratio of the distance between the foci of the ellipse and its major axis length. The value is between 0 and 1. (0 and 1 are degenerate cases. An ellipse whose eccentricity is 0 is actually a circle, while an ellipse whose eccentricity is 1 is a line segment.)
So as the value of eccentricity increases , the ellipse starts becoming flatter. Hence, at its maximum value = 1, it is a line segment.
To check if there is a dent in the ellipse, you can use check for convexity. Whenever there is a dent in an ellipse, it will be non-convex. In other words, if you try to fit a convex polygon, it won't be able to approximate the shape well enough. You can use convexArea property to check the same. From MATLAB documentation of convexArea:
Returns a p-by-2 matrix that specifies the smallest convex polygon that can contain the region. Each row of the matrix contains the x- and y-coordinates of one vertex of the polygon. Only supported for 2-D label matrices.
So you use bwlabel to create a 2-D label matrix from your binary image and then check the difference between the area of your binary image and the area of the fitted convex polygon. Measuring area could be as simple as counting pixels. You already know that the number pixels of your fitted convex polygon = p. Just take the absolute difference between p and the number of pixels in your original binary image. You should be able to easily set a threshold to classify into one of the two classes.
I think you can write the code for this. Hope this helps.
I am trying to plot a 3D volume in MATLAB. I am using the slice command.
a(:,:,1)=[1,2; 3,4];
a(:,:,2)=[5,6; 9,8];
figure;
slice (a,0,0,1);
hold on
slice (a,0,0,2);
The figure I get has just one square (pixel). I am expecting 4 squares. How do I plot this? What am I doing wrong?
Relevant part of documentation:
slice(V,sx,sy,sz) draws slices along the x, y, z directions in the volume V at the points in the vectors sx, sy, and sz. V is an m-by-n-by-p volume array containing data values at the default location X = 1:n, Y = 1:m, Z = 1:p. Each element in the vectors sx, sy, and sz defines a slice plane in the x-, y-, or z-axis direction.
So, your command slice (a,0,0,1); is asking Matlab to produce three slices of the cube [1,2]×[1,2]×[1,2] (colored according to the values of your a array), by the following planes
x=0 plane (shown as empty square since it's outside of the cube)
y=0 plane (same story)
z=1 plane (dark blue square).
You could have avoided the extraneous x=0 and y=0 slices with slice(a,[],[],1). Also,
slice(a,[],[],[1,2]) would give you top and bottom
slice(a,[],[1,2],[]) would give two vertical sides
slice(a,[1,2],[],[]) would give two other vertical sides
Or you could just get all six at once with slice(a,[1,2],[1,2],[1,2]). If you don't want, e.g., top and bottom slices, then slice(a,[1,2],[1,2],[]).
Note that the entries of a are not coordinates, they are understood as values of a function of three variables, and are represented by colors.
I have a list of triangles in 3D that form a surface (ie a triangulation). The structure is a deformed triangular lattice. I want to know the change in area of the deformed hexagons of the voronoi tessalation of the lattice with respect to the rest area of the undeformed lattice cells (ie with respect to a regular hexagon). In fact, I really want the sum of the squared change in area of the hexagonal unit cells associated with those triangles.
Background/Math details:
I'm approximating a curved elastic sheet by a triangular lattice. One way to tune the poisson ratio (elastic constant) of the sheet is by adding a 'volumetric' strain energy term to the energy. I'm trying to compute a 'volumetric' strain energy of a deformed, elastic, triangular lattice, defined as: U_volumetric = 1/2 T (e_v)^2, where e_v=deltaV/V is determined by the change in area of a voronoi cell with respect to its reference area, which is a known constant.
Reference: https://www.researchgate.net/publication/265853755_Finite_element_implementation_of_a_non-local_particle_method_for_elasticity_and_fracture_analysis
Want:
Sum[ (DeltaA/ A).^2 ] over all hexagonal cells.
My data is stored in the variables:
xyz = [ x1,y1,z1; x2,y2,z2; etc] %the vertices/particles in 3D
TRI = [ vertex0, vertex1, vertex2; etc] %
where vertex0 is the row of xyz for the particle sitting at vertex 0 of the first triangle.
NeighborList = [ p1n1, p1n2, p1n3, p1n4, p1n5,p1n6 ; p2n1...]
% where p1n1 is particle 1's first nearest neighbor as a row index for xyz. For example, xyz(NL(1,1),:) returns the xyz location of particle 1's first neighbor.
AreaTRI = [ areaTRI1; areaTRI2; etc]
I am writing this in MATLAB.
As of now, I am approximating the amount of area attributed to each vertex as 1/3 of the triangle's area, then summing over the 6 nearest neighbor triangles. But a voronoi cell area will NOT be exactly equal to Sum_(i=0,1,...5) 1/3* areaTRI_i, so this is a bad approximation. See the image in the link above, which I think makes this clearer.
You can do this using the DUALMESH-submission on the file exchange:
DUALMESH is a toolbox of mesh processing routines that allow the construction of "dual" meshes based on underlying simplicial triangulations. Support is provided for various planar and surface triangulation types, including non-Delaunay and non-manifold types.
Simply use the following commands to generate a vector areas of all the dual elements' areas. The ordering will correspond to the nodes xyz.
[cp,ce,pv,ev] = makedual2(xyz, TRI);
[~,areas(cp(:,1))] = geomdual2(cp,ce,pv,ev);
You might want to have a look at the boundary areas using:
trisurf(TRI, xyz(:,1), xyz(:,2), areas);
The dual cells of boundary nodes theoretically are unbounded and thus should have infinite area. This submission handles it differently however: Instead of an unbounded cell it will return the intersection of the unbounded cell with the original mesh.
Also mind that your question is not well defined if the mesh you are working with is not planar, as the dual mesh cells will be planar and won't scale the same way as the triangles. So this solution will probably only work correctly if your mesh is really 2D. (From what I can tell, the paper you mention is also only for the 2D-case.)
I have a matrix consisting of three rows: gene 1, gene 2, Distance.
I want to create a network where each gene is a node and the connecting line is scaled by the distance between the two genes.
How can I do this without using the bioinformatics or neural network toolboxes?
Thanks!
Some Information
It is almost impossible to draw a graph with edge length proportional to edge weight, atleast its very unlikely that the weights allow a graph to be drawn this way, most will be impossible...
See:
P. Eades and N. C. Wormald. Fixed edge-length graph drawing is
NP-hard. Discrete Applied Mathematics, 28(2):111–134, 1990]
or to quote:
"Drawing planar graphs with edge weights as standard node-link
diagram, where edge lengths are proportional to the edge weights, is
an NP-hard problem"
M. Nollenburg, R. Prutkin and I. Rutter, Edge-weighted contact
representations of planar
graphs.
Journal of Graph Algorithms and Applications, 17(4):441–473, 2013
Consider the simple example of the 3 vertices joined as such, in your data format:
[1,2,1;
1,3,1;
2,3,10;]
it's should be immediately obvious that such a graph is impossible to draw with edge length proportional to weight (with straight lines). As such alternatives in MATLAB include using color or line width to represent Weight.
Sorry for the length of this answer but to implement this is not trivial, the process used below for drawing the graph can also be found here (in debth), here (most simple) and in a similar problem here. However these do not address weighted graphs...
So on with implementing line width and color proportional to weight:
Code
Due to the length the code is available without description here
Firstly some test data, consisting of 30 edges randomly assigned between 20 vertices with random weights between 0 and 10.
clear
%% generate testing data
[X,Y] = ndgrid(1:20); testdata = [X(:) Y(:)]; %// all possible edges
data(data(:,1)==data(:,2),:)=[]; %// delete self loops
data=data(randperm(size(data,1),20),:); %// take random sample of edges
data(:,3)=rand(size(data,1),1)*10; %// assign random weights in range 0-10
First some processing of the data to get it into required format;
edges=data(:,1:2);
[Verticies,~,indEdges]=unique(edges); %// get labels & locations of vertices
indEdges=reshape(indEdges,[],2);
weights=data(:,3);
normalisedWeights=weights/max(weights); %// normalise weights (range 0-1)
numeEdge=numel(weights);
numVertex=numel(Verticies);
Now x and y coordinates for each vertex are created on a unit circle:
theta=linspace(0,2*pi,numVertex+1);
theta=theta(1:end-1);
[x,y]=pol2cart(theta,1); % create x,y coordinates for each vertex
As lines in MATLAB plots inherit their color from the axis color order we create a RGB array which corresponds to a colormap, with a entry for each line giving the RGB values for the color assigned to that weight.
The autumn colormap is simple to manually implement as R=1,B=0 for all values and G ranges from 0-1 linearly, so we can make the Cmap variable which is used as the axis color order as follows:
clear Cmap %// to avoid errors due to the way it is created
Cmap(:,2)=normalisedWeights;
Cmap(:,1)=1;
Cmap(:,3)=0;
Now we create a figure, set the colormap to autumn (for the color bar), put hold on so the plot command doesn't reset the color order, and apply the color order
figure
colormap('autumn')
hold on
set(gca,'colororder',Cmap) %// set axis colororder to Cmap
how we plot the edges using the edge indexes generated earlier at locations given by x & y. The handles of the lines (Hline) is stored for later use.
Hline=plot(x(indEdges).',y(indEdges).'); %// plot edges
Now we set the axis to square so the circle of points is displayed properly and turn the axis off to hide them (as they bear no relevance to the plotted graph). The axis color limits (Clim) is then set to match the range of weights and add a colorbar is added.
axis square off
set(gca,'Clim',[0 max(weights)])
colorbar
The final step for plotting the edges, setting the line width to be proportional to weight, The normalised weights are scaled to be in the range 0-5. The linewidths are then set to scalefactor*normalisedWeights..
scalefactor=5; %// scale factor (width of highest weight line)
set(hline, {'LineWidth'}, num2cell(normalisedWeights*scalefactor));
The vertices are now plotted at the x and y coordinates (as black squares here).
The axis limits are increased to allow vertex labels to fit. Finally the vertices are labelled with the values from the original matrix, the labels are placed on a slightly larger circle than the vertices
plot(x,y,'ks')
xlim([-1.1,1.1]) % expand axis to fix labels
ylim([-1.1,1.1])
text(x(:)*1.1, y(:)*1.1, num2str(Verticies),...
'FontSize',8,'HorizontalAlignment','center'); %// add Vertex labels
Results