How to make a hollow cylinder in SketchUp using the Ruby API - ruby

What I need to accomplish is basically a cylinder whose walls have zero thickness. Now if you need to understand better what I mean by this, imagine manually drawing a circle, then using the pushpull tool to make it a cylinder, after which you delete the top and bottom faces. At first, I used the method suggested in this post:
Punching a hole through a cylinder using Sketchup Ruby API
where the outer and inner radii had a difference of about 1e-02 meters, but now I realize it actually has to be an infinitesimal thickness, one where no matter how far you zoom-in, all you see is a line.
I went about trying to accomplish this with the following basic snippet of code:
entities = Sketchup.active_model.active_entities
circle = entities.add_circle(Geom::Point3d.new(0,0,0), Geom::Vector3d.new(0,0,1), 20)
face = entities.add_face(circle)
face.pushpull(-10, true)
# now from here, it can be either pushpulled downwards by the same amount (10 in this case
# leaving only a bottom face)
# or the entity 'face' can be erased (leaving only a top face) as in the following
entities.erase_entities(face)
so my question is, how do I remove both faces so as to leave only the cylinder?
Thank you.

I found the answer, the solution is to do both. That is, pushpull inwards the same amount, then delete the face with: entities.erase_entities(face).
entities = Sketchup.active_model.active_entities
circle = entities.add_circle(Geom::Point3d.new(0,0,0), Geom::Vector3d.new(0,0,1), 20)
face = entities.add_face(circle)
face.pushpull(-10, true)
face.pushpull(10, true)
entities.erase_entities(face)

Related

Draw a curve in the segmented image using matlab

I have a segmented image as shown here
i want to fit a curve along the top pixels of the segmented image(show as red curve) and i want to find the top point along the curve show in blue. I have already worked on basic idea like traversing through the top to bottom and collecting the top point along each column. i want to know is there any easy solution for this problem like directly taking out the boundary pixels and find the top point.I am using MATLAB for this problem
%download the image
img = logical(imread('http://i.stack.imgur.com/or2iX.png'));
%for some reason it appeared RGB with big solid borders.
%to monochrome
img = img(:,:,1);
%remove borders
img = img(~all(img,2), ~all(img,1));
%split into columns
cimg = num2cell(img,1);
%find first nonzero element per column
ridx = cellfun(#(x) find(x,1,'first'), cimg);
figure, imshow(img)
hold on
%image dim1 is Y, dim2 is X
plot(1:size(img,2),ridx-1,'r','linewidth',2)
%find top point
[yval, xval] = min(ridx);
If you want a smoother curve, try polyfit/polyval
#EDIT
If we want the line to have break at gaps between connected components, we should change the code to something like
bord_idx = sub2ind(size(img), ridx, 1:size(img,2));
regs=regionprops(bwlabel(img),'pixelidxlist');
regs_idx = struct2cell(regs);
split_step = cellfun(#(x) sum(ismember(bord_idx,x)), regs_idx);
split_step = split_step(split_step>0);
split_yvals = mat2cell(ridx',split_val);
split_xvals = mat2cell([1:size(img,2)]',split_val);
figure, imshow(img)
hold on
for k = 1:length(split_step),
plot(split_xvals{k}, split_yvals{k}, 'r', 'linewidth', 2),
end
However, the result is not ideal if one region is positioned over the other. If the "shadowed" points are needed, you should try bwtraceboundary or convexhull and find where the border turns down
As far as "simplest matlab solution" by which I think you mean built in matlab functions: imclose()->edge()->bwboundaries()->findpeaks()'on each boundary'->'filter results based on width and magnitude of peaks'. *you will need to tune all the parameters in these functions, I am just listing what would get you there if appropriately applied.
As far as processing speed is concerned, I think I would have done exactly what you did, basically collecting the top edge from a top down column search and then looking for the point of highest inflection. As soon as you start doing processing of any type, you start doing several operations per pixel which will quickly become more expensive than your initial search (just requires that your image and target are simple enough)
That being said, here are some ideas that may help:
1:If you run a sufficiently heavy closing (dilate->erode), that should fill in all that garbage at the bottom.
2: If you know that your point of interest is not at left or right of picture (boundaries), you could take the right and left edge points and calculate a slope to be applied as an offset to flatten the whole image.
3: If your image always has the large dark linear region below the peak as seen here, you could locate those edges with houghlines looking for verticals and then search only the columns between them.
4: If speed is a concern, you could do a more sophisticated search pattern than left to right, as your peak has a pretty good distribution around it which could help with faster localization of maxima.

MATLAB, algorithm for free surface detection in bubbly flow

I am trying to figure out an algorithm for detecting the free surface from a PIV image (see attached). The major problem is that in the flow under consideration gas bubbles are injected into the fluid, these rise up due to buoyancy and tend to sit on top of the surface. I don't want these to be mistaken for the free surface (actually want the '2nd' edge underneath them) - I'm struggling to figure out how to include that in the algorithm.
Ideally, I want an array of x and y values representing coordinates of the free surface (like a continuous, smooth curve).
My initial approach was to scan the picture left to right, one column at a time, find an edge, move to the next column etc... That works somewhat ok, but fails as soon as the bubbles appear and my 'edge' splits in two. So I am wondering if there is some more sophisticated way of going about it.
If anybody have any expertise in the area of image processing/edge detection, any advice would be greatly appreciated.
Typical PIV image
Desired outcome
I think you can actually solve the problem by using morphologic methods.
A = imread('./MATLAB/ZBhAM.jpg');
figure;
subplot 131;
imshow(A)
subplot 132;
B = double(A(:,:,1));
B = B/255;
B = im2bw(B, 0.1);
imshow(B);
subplot 133;
st = strel('diamond', 5);
B = imerode(B, st);
B = imdilate(B, st);
B = imshow(B);
This gives the following result:
As you can see this approach is not perfect mostly because I picked a random value for the threshold in im2bw, if you use an adaptive threshold for the different column of your images you should have something better.
Try to work on your lighting otherwise.

Field of view/ convexity map

On a shape from a logical image, I am trying to extract the field of view from any point inside the shape on matlab :
I tried something involving to test each line going through the point but it is really really long.(I hope to do it for each points of the shape or at least each point of it's contour wich is quite a few times)
I think a faster method would be working iteratively by the expansion of a disk from the considered point but I am not sure how to do it.
How can I find this field of view in an efficient way?
Any ideas or solution would be appreciated, thanks.
Here is a possible approach (the principle behind the function I wrote, available on Matlab Central):
I created this test image and an arbitrary point of view:
testscene=zeros(500);
testscene(80:120,80:120)=1;
testscene(200:250,400:450)=1;
testscene(380:450,200:270)=1;
viewpoint=[250, 300];
imsize=size(testscene); % checks the size of the image
It looks like this (the circle marks the view point I chose):
The next line computes the longest distance to the edge of the image from the viewpoint:
maxdist=max([norm(viewpoint), norm(viewpoint-[1 imsize(2)]), norm(viewpoint-[imsize(1) 1]), norm(viewpoint-imsize)]);
angles=1:360; % use smaller increment to increase resolution
Then generate a set of points uniformly distributed around the viewpoint.:
endpoints=bsxfun(#plus, maxdist*[cosd(angles)' sind(angles)'], viewpoint);
for k=1:numel(angles)
[CX,CY,C] = improfile(testscene,[viewpoint(1), endpoints(k,1)],[viewpoint(2), endpoints(k,2)]);
idx=find(C);
intersec(k,:)=[CX(idx(1)), CY(idx(1))];
end
What this does is drawing lines from the view point to each directions specified in the array angles and look for the position of the intersection with an obstacle or the edge of the image.
This should help visualizing the process:
Finally, let's use the built-in roipoly function to create a binary mask from a set of coordinates:
FieldofView = roipoly(testscene,intersec(:,1),intersec(:,2));
Here is how it looks like (obstacles in white, visible field in gray, viewpoint in red):

Drawing a radius in D3

Apologies if this is painfully simple, I have tried searching for a solution.
In D3, I can perform an arc by defining this:
var ringBannerCcwArc = d3.svg.arc()
.innerRadius(420)
.outerRadius(470)
.startAngle(0)
.endAngle(function(t) {return t * -1 * 2 * Math.PI / 6; });
and then defining it in the DOM here:
labels.append("path")
.attr("id", "ring-banner");
And then at the appropriate time I can do:
labels.transition.select("#ring-banner").style("fill", "red")
.attrTween("d", function() { return ringBannerCcwArc });
And that will produce a red coloured arcing "label" starting at 0 and stopping at whatever
t * -1 * 2 * Math.PI / 6
produces as an angle (yes, 60 degress, but I intend for it to be a variable result).
What I would like to do is simply create a line that extends outward from this banner on the radius of the "endAngle" (so that I can build a dynamically driven display).
Something like this image:
My goal is to dynamically attach data to this and employ the amazingness of D3 to it. So once I understand how to draw the above solution, I would then like to know the resulting coordinates of the end line (x2,y2). The line itself can be a set length (say, 50) but how would I determine it's position so that I could attach a final area to it?
Something like this image:
Again, I apologize if this seems obvious. Thanks for any help.
EDIT:
The original question was regarding my use of D3 - creating a ringBannerArc - and then wanting to tap into the coordinate system. So, as the two respondents state, it is a basic trig problem but that's not really the question.
In the end, the answer is that d3 does not do what I was asking. But it can easily perform the solution. If, like me, you are struggling with implementing d3 and understanding it's very unique (and extremely powerful) approach to data visualization then you might find these links helpful. Thanks to the guys over at the d3 Google Group.
Helpful contributors:
Ian Johnson:
First you want to know how to draw a line from one point to another. That's the end result you want and if you can't do it for arbitrary lines you can't do it for the line you want. so lets start there:
http://tributary.io/inlet/4229462/ The second part is calculating the point on the circle you want to draw. But before you do that, you should set things up so you can verify easily where that point is. so lets draw the overall circle, and then draw a point we can use:
http://tributary.io/inlet/4229477/ Now lets try to place that point at some point on the circle based on an input radius using trig:
http://tributary.io/inlet/4229496/ once we can control that point, we come full circle ;) and move the line http://tributary.io/inlet/4229500/
Chris Viau: Wrapped it up in a nice helper function: http://jsfiddle.net/christopheviau/YPAYz/ Suggested a great book for beginners written by Scott Murray: http://ofps.oreilly.com/titles/9781449339739/index.html
Scott Murray: Makes a wonderful reference to a white paper written by the d3 authors - for those of us who like to understand the nuts and bolts: http://vis.stanford.edu/files/2011-D3-InfoVis.pdf
This is essentially a basic trigonometry question.
For a circle, if the angles start from vertical and go clockwise, and your coordinates are normal screen coordinates,
x = cx + sin(angle) * r
y = cy + cos(angle) * r
From these, you can then compute either line simply.
First you want to know how to draw a line from one point to another. That's the end result you want and if you can't do it for arbitrary lines you can't do it for the line you want.
The second part is calculating the point on the circle you want to draw. But before you do that, you should set things up so you can verify easily where that point is. so lets draw the overall circle, and then draw a point we can use:
http://tributary.io/inlet/4229477/
Now lets try to place that point at some point on the circle based on an input radius using trig, once we can control that point, we come full circle ;) and move the line
http://tributary.io/inlet/4229500/

How to add collision detection in a 2D car game in XNA?

Right, I'm making a 2d car racing game. So far I've got the car moving etc (with a little help of course) and was wondering how do I go about adding collision detection in XNA. I've taken a bumper part (from the whole track), and made it as a separate .png file. And I was thinking of adding a collision detection box around it (so if 'car' hits 'bumper' move back by so and so). How do I add collison detection to the bumper, and integrate it with the car? Thank you!
Try this tutorial: http://create.msdn.com/en-US/education/catalog/tutorial/collision_2d_perpixel
Source code for the tutorial is in Downloads, under the two (ugly) blue boxes.
It seems this would be a lot easier if the cars were always straight--not rotated. If they were rotated you wouldn't be able to use rectangles to help.
If you do, then you could instead have the bumper included in car.png.
Then you could use the coordinates of the car and add certain values to get the length and width of the region for the bumper.
You can then do
Rectangle bumperBoundingBox = new Rectangle
(
(int)X_COORDINATE_OF_CAR,
(int)Y_COORDINATE_OF_CAR,
(int)X_COORDINATE_OF_CAR + WIDTH_OF_BUMPER,
(int)Y_COORDINATE_OF_CAR + HEIGHT_OF_BUMPER
);
Rectangle otherCarBoundingBox = new Rectangle( \* x, y, ... *\ );
bool carIsTouchingBumper = otherCarBoundingBox.Intersects(bumperBoundingBox);
This may not be perfectly perfect, as in the parameters for rectangle might be in a different order or something like that. But once you have it, you can use carIsTouchingBumper and do stuff.
If you want the bumper to be a separate image, you could do the same thing as above, except use the coordinates of the bumper instead. Also you would have to make the bumper follow the car.

Resources