I want to create many rectangles. This should be done automatically. How can I do this without typing thousands of values in my code? Is there an solution?
In my code I wrote every single coordinate point (4 points of each rectangle) manually in my vector "V".
Also how to connect them. "F"
And the value of each rectangle. "C"
My code is
clc
clear all
figure;
V = [0,0;1,0;1,1;0,1;5,5;10,5;10,10;5,10;2,2;4,2;4,4;2,4];
F = [1,2,3,4;5,6,7,8;9,10,11,12];%Dieser Vektor sagt mir in welcher Reihenfolge die Punkte
C = [50;24;99];
patch('Faces',F,'Vertices',V,'FaceVertexCData',C,'FaceColor','flat','EdgeColor','none') %Befehl fürs "zeichnen"
colormap(parula)
colorbar
You can use the following function to create a random rectangle, by randomly generating an (x, y) position for the bottom left corner, and randomly generating a width and height -
function rect = createRandomRectangle(maxX, maxY, minHeight, maxHeight, minWidth, maxWidth)
bottom = maxY * rand;
left = maxX * rand;
height = minHeight + rand * (maxHeight - minHeight);
width = minWidth + rand * (maxWidth - minWidth);
rect = [
left, bottom
left, bottom + height
left + width, bottom + height
left + width, bottom
];
end
Then you just need to take care of creating your V, F, C matrices (by calling createRandomRectangle in a loop) and plotting them.
Related
I have created a synthetic image that consists of a circle at the centre of a box with the code below.
%# Create a logical image of a circle with image size specified as follows:
imageSizeY = 400;
imageSizeX = 300;
[ygv, xgv] = meshgrid(1:imageSizeY, 1:imageSizeX);
%# Next create a logical mask for the circle with specified radius and center
centerY = imageSizeY/2;
centerX = imageSizeX/2;
radius = 100;
Img = double( (ygv - centerY).^2 + (xgv - centerX).^2 <= radius.^2 );
%# change image labels from double to numeric
for ii = 1:numel(Img)
if Img(ii) == 0
Img(ii) = 2; %change label from 0 to 2
end
end
%# plot image
RI = imref2d(size(Img),[0 size(Img, 2)],[0 size(Img, 1)]);
figure, imshow(Img, RI, [], 'InitialMagnification','fit');
Now, i need to create a rectangular mask (with label == 3, and row/col dimensions: 1 by imageSizeX) across the image from top to bottom and at known angles with the edges of the circle (see attached figure). Also, how can i make the rectangle thicker than 1 by imageSizeX?. As another option, I would love to try having the rectangle stop at say column 350. Lastly, any ideas how I can improve on the resolution? I mean is it possible to keep the image size the same while increasing/decreasing the resolution.
I have no idea how to go about this. Please i need any help/advice/suggestions that i can get. Many thanks!.
You can use the cos function to find the x coordinate with the correct angle phi.
First notice that the angle between the radius that intersects the vertex of phi has angle with the x-axis given by:
and the x coordinate of that vertex is given by
so the mask simply needs to set that row to 3.
Example:
phi = 45; % Desired angle in degrees
width = 350; % Desired width in pixels
height = 50; % Desired height of bar in pixels
theta = pi-phi*pi/180; % The radius angle
x = centerX + round(radius*cos(theta)); % Find the nearest row
x0 = max(1, x-height); % Find where to start the bar
Img(x0:x,1:width)=3;
The resulting image looks like:
Note that the max function is used to deal with the case where the bar thickness would extend beyond the top of the image.
Regarding resolution, the image resolution is determined by the size of the matrix you create. In your example that is (400,300). If you want higher resolution simply increase those numbers. However, if you would like to link the resolution to a higher DPI (Dots per Inch) so there are more pixels in each physical inch you can use the "Export Setup" window in the figure File menu.
Shown here:
The Problem
I'm trying to figure out a way to get at which point in the content node the scroll pane's viewport is centered on.
To elaborate on the picture above, the big rectangle is the content (let's say a large image), and the small rectangle is the portion that is shown by the scroll pane. I'm trying to find x and y which would be coordinates from the top left of the content.
What I've Tried
My first thought was to use the getViewportBounds() method of the scroll pane and use its minX and maxX properties to determine the center x point:
Bounds b = scrollPane.getViewportBounds();
double centerX = (b.getMinX() + b.getMaxX()) / 2;
double centerY = (b.getMinY() + b.getMaxY()) / 2;
However, this doesn't work because these numbers are negative and don't seem to accurately describe the x and y I'm looking for anyways.
My next thought was to use the scroll pane's hValue and vValue to get the top left corner of the viewport relative to the content:
Bounds b = scrollPane.getViewportBounds();
double centerX = scrollPane.getHvalue() + b.getWidth() / 2;
double centerY = scrollPane.getVvalue() + b.getHeight() / 2;
This didn't work either though as the hValue and vValue seem to be way too large (when scrolled in only a few pixels, I'm getting numbers like 1600).
My Questions
I seem to have a fundamental misunderstanding of how the viewport works with a scroll pane.
What am I doing wrong here? Can someone explain where these numbers come from? How do I find x and y like in the picture above?
Let (x, y) be the be coordinates of the top, left point shown in the viewport. You can write this as
((contentWidth - viewportWidth) * hValueRel, (contentHeight - viewportHeight) * vValueRel)
vValueRel = vValue / vMax
hValueRel = hValue / hMax
This means assuming hmin and vmin remain 0 you can keep a circle in the center of like this:
// update circle position to be centered in the viewport
private void update() {
Bounds viewportBounds = scrollPane.getViewportBounds();
Bounds contentBounds = content.getBoundsInLocal();
double hRel = scrollPane.getHvalue() / scrollPane.getHmax();
double vRel = scrollPane.getVvalue() / scrollPane.getVmax();
double x = Math.max(0, (contentBounds.getWidth() - viewportBounds.getWidth()) * hRel) + viewportBounds.getWidth() / 2;
double y = Math.max(0, (contentBounds.getHeight() - viewportBounds.getHeight()) * vRel) + viewportBounds.getHeight() / 2;
Point2D localCoordinates = content.parentToLocal(x, y);
circle.setCenterX(localCoordinates.getX());
circle.setCenterY(localCoordinates.getY());
}
private Circle circle;
private Pane content;
private ScrollPane scrollPane;
#Override
public void start(Stage primaryStage) {
// create ui
circle = new Circle(10);
content = new Pane(circle);
content.setPrefSize(4000, 4000);
scrollPane = new ScrollPane(content);
Scene scene = new Scene(scrollPane, 400, 400);
// add listener to properties that may change
InvalidationListener l = o -> update();
content.layoutBoundsProperty().addListener(l);
scrollPane.viewportBoundsProperty().addListener(l);
scrollPane.hvalueProperty().addListener(l);
scrollPane.vvalueProperty().addListener(l);
scrollPane.hmaxProperty().addListener(l);
scrollPane.vmaxProperty().addListener(l);
scrollPane.hminProperty().addListener(l);
scrollPane.vminProperty().addListener(l);
primaryStage.setScene(scene);
primaryStage.show();
}
I felt confused to crop an image along any angle, i.e. pi/4, how can I make it?
The following example demonstrates how to crop rotated bounding box.
The example doesn't show how to select the bounding box, and the angle (user interface is excluded).
For keeping the example simple, the bounding box parameters are: center, size and angle (instead of 4 corners).
Center is kept in place, when rotating.
Size is the width and height of destination crop area (size after rotation).
In case you need to calculate corners transformation, you can use rotation matrix: https://en.wikipedia.org/wiki/Rotation_matrix
Code sample:
%Bounding box parameters: center, width, height and angle.
%Center is selected, because center is kept the same when rotating.
center_x = 256; %Center column index (applied center is 256.5)
center_y = 192; %Center row index (applied center is 192.5)
width = 300; %Number of columns of destination (cropped) area (even integer)
height = 200; %Number of rows of destination (cropped) area (even integer)
phi = 120; %Rotation angle in degrees
%Read sample image.
I = imread('peppers.png');
%Add center cross, for verifying center is kept.
I(center_y-1:center_y, center_x-30:center_x+30, :) = 255;
I(center_y-30:center_y+30, center_x-1:center_x, :) = 255;
%Rotate the entire input image, dimensions of J will be the same as I.
J = imrotate(I, phi, 'bicubic', 'crop');
%Crop rectangular are with size width by height around center_x, center_y from J.
C = J(center_y-height/2+1:center_y+height/2, center_x-width/2+1:center_x+width/2, :);
%Display result:
figure;imshow(C);
Result:
I'm trying to create a dataset of raw volumetric data consisting of geometrical shapes. The point is to use volume ray casting to project them in 2D but first I want to create the volume manually.
The geometry is consisting of one cylinder that is in the middle of the volume, along the Z axis and 2 smaller cylinders that are around the first one, deriving from rotations around the axes.
Here is my function so far:
function cyl= createCylinders(a, b, c, rad1, h1, rad2, h2)
% a : data width
% b : data height
% c : data depth
% rad1: radius of the big center cylinder
% rad2: radius of the smaller cylinders
% h1: height of the big center cylinder
% h2: height of the smaller cylinders
[Y X Z] =meshgrid(1:a,1:b,1:c); %matlab saves in a different order so X must be Y
centerX = a/2;
centerY = b/2;
centerZ = c/2;
theta = 0; %around y
fi = pi/4; %around x
% First cylinder
cyl = zeros(a,b,c);
% create for infinite height
R = sqrt((X-centerX).^2 + (Y-centerY).^2);
startZ = ceil(c/2) - floor(h1/2);
endZ = startZ + h1 - 1;
% then trim it to height = h1
temp = zeros(a,b,h1);
temp( R(:,:,startZ:endZ)<rad1 ) = 255;
cyl(:,:,startZ:endZ) = temp;
% Second cylinder
cyl2 = zeros(a,b,c);
A = (X-centerX)*cos(theta) + (Y-centerY)*sin(theta)*sin(fi) + (Z-centerZ)*cos(fi)*sin(theta);
B = (Y-centerY)*cos(fi) - (Z-centerZ)*sin(fi);
% create again for infinite height
R2 = sqrt(A.^2+B.^2);
cyl2(R2<rad2) = 255;
%then use 2 planes to trim outside of the limits
N = [ cos(fi)*sin(theta) -sin(fi) cos(fi)*cos(theta) ];
P = (rad2).*N + [ centerX centerY centerZ];
T = (X-P(1))*N(1) + (Y-P(2))*N(2) + (Z-P(3))*N(3);
cyl2(T<0) = 0;
P = (rad2+h2).*N + [ centerX centerY centerZ];
T = (X-P(1))*N(1) + (Y-P(2))*N(2) + (Z-P(3))*N(3);
cyl2(T>0) = 0;
% Third cylinder
% ...
cyl = cyl + cyl2;
cyl = uint8(round(cyl));
% ...
The concept is that the first cylinder is created and then "cut" according to the z-axis value, to define its height. The other cylinder is created using the relation A2 + B 2 = R2 where A and B are rotated accordingly using the rotation matrices only around x and y axes, using Ry(θ)Rx(φ) as described here.
Until now everything seems to be working, because I have implemented code (tested that it works well) to display the projection and the cylinders seem to have correct rotation when they are not "trimmed" from infinite height.
I calculate N which is the vector [0 0 1] aka z-axis rotated in the same way as the cylinder. Then I find two points P of the same distances that I want the cylinder's edges to be and calculate the plane equations T according to that points and normal vector. Lastly, I trim according to that equality. Or at least that's what I think I'm doing, because after the trimming I usually don't get anything (every value is zero). Or, the best thing I could get when I was experimenting was cylinders trimmed, but the planes of the top and bottom where not oriented well.
I would appreciate any help or corrections at my code, because I've been looking at the geometry equations and I can't find where the mistake is.
Edit:
This is a quick screenshot of the object I'm trying to create. NOTE that the cylinders are opaque in the volume data, all the inside is considered as homogeneous material.
I think instead of:
T = (X-P(1))*N(1) + (Y-P(2))*N(2) + (Z-P(3))*N(3);
you should try the following at both places:
T = (X-P(1)) + (Y-P(2)) + (Z-P(3));
Multiplying by N is to account for the direction of the axis of the 2nd cylinder which you have already done just above that step.
I'm trying to draw a circle on an image in MATLAB with given X,Y coordinates and radius. Here's the chuck of code of method that draws multiple circles for me -
function circle( Xs, Ys, Rs, LineWidth, LineColor)
radius = Rs;
centerX = Xs;
centerY = Ys;
for i=1:length(centerX)
rectangle('Position',[centerX(i), centerY(i), radius(i), radius(i)],...
'Curvature',[1,1],...
'LineWidth',LineWidth,...
'LineStyle','-',...
'EdgeColor',LineColor);
end
end
But whenever I see the circles in an image, I see that the circles are a little bit misplaced from the given coordinates (for example, they moved a little bit right/down). How do I fix this problem?
What you are drawing is actually a rectangle. But you have a curvature defined, which makes it look like a circle. The circle is then defined by a bounding box with the coordinates of the rectangle. The Position of the rectangle is the upper left corner (or in a regular plot the lower left corner) and what you called the radius is actually the width and height of that bounding box.
This is what I mean:
>> figure, imshow(I)
>> rectangle('Position',[100,100,120,120],'Curvature',[1,1])
>> rectangle('Position',[100,100,120,120],'Curvature',[0,0],'EdgeColor','r')
>> axis on
This code will produce a circle and a rectangle both in the same position defined by the same rectangle coordinates in the upper left corner. The red one is the bounding box I am speaking of.
Edit: If you don't want to use the rectangle function you could maybe do the following:
>> figure,imshow(I)
>> hold on
>> plot(centerX+radius*sin(0:0.1:2*pi),centerY+radius*cos(0:0.1:2*pi))
Try the following:
function circle( Xs, Ys, Rs, LineWidth, LineColor)
radius = Rs;
centerX = Xs;
centerY = Ys;
xStart = centerX - radius;
yStart = centerY - radius;
for i=1:length(centerX)
rectangle('Position',[xStart(i) , yStart(i) , radius(i), radius(i)],...
'Curvature',[1,1],...
'LineWidth',LineWidth,...
'LineStyle','-',...
'EdgeColor',LineColor);
end
end
I hope this will work.
By subtracting the radius from the center points we can get the starting point(Top left corner) of the rectangle with curvature [1,1], that is nothing but the circle.