Adding an angle / angle profile to openscad barbed object - openscad

I have a openscad object that I would like to add an angle / angled profile to the bottom of a barbed object all the way around.
Original (what's currently created):
What I would like: (have the bottom all the way around not be flat but at an angle / angle profile like 45,50,60...)
Code:
////////////////////////////////////////////////////////
// Created by Paul Tibble - 18/7/19 //
// https://www.thingiverse.com/Paul_Tibble/about //
// Please consider tipping, if you find this useful. //
////////////////////////////////////////////////////////
$fn = 100*1;
// Outer Diameter (bottom)
outer_diameter_1 = 15;
// Wall Thickness (bottom)
wall_thickness_1 = 2;
// Rib Thickness (bottom), set to Zero to remove
barb_size_1 = 0.5;
// Length (bottom)
length_1 = 15;
// Outer Diameter (top), should be smaller than or equal to Outer Diameter (bottom)
outer_diameter_2 = 12;
// Wall Thickness (top)
wall_thickness_2 = 1;
// Rib Thickness (top), set to Zero to remove
barb_size_2 = 0.5;
// Length (top)
length_2 = 15;
// Middle Diameter
mid_diameter = 17;
// Middle Length
mid_length = 5;
//do not change these
inner_diameter_1 = outer_diameter_1 - (wall_thickness_1*2);
inner_diameter_2 = outer_diameter_2 - (wall_thickness_2*2);
module create_profile() {
////////
// Middle
///////
polygon(points=[[inner_diameter_1/2,length_1],[mid_diameter/2,length_1],[mid_diameter/2,length_1+mid_length],[inner_diameter_2/2,length_1+mid_length]]);
//////
//length 1
/////
translate([inner_diameter_1/2,0,0])square([wall_thickness_1,length_1]);
//barb 1
translate([outer_diameter_1/2,0,0])polygon(points=[[0,0],[0,(length_1/5)],[barb_size_1,(length_1/5)]]);
//barb 2
translate([outer_diameter_1/2,length_1*0.25,0])polygon(points=[[0,0],[0,(length_1/5)],[barb_size_1,(length_1/5)]]);
//barb 3
translate([outer_diameter_1/2,length_1*0.5,0])polygon(points=[[0,0],[0,(length_1/5)],[barb_size_1,(length_1/5)]]);
//////
//length 2
/////
translate([inner_diameter_2/2,length_1+mid_length,0])square([wall_thickness_2,length_2]);
//rib 1
translate([outer_diameter_2/2,(length_1+mid_length+length_2),0])polygon(points=[[0,0],[0,-1*(length_2/5)],[barb_size_2,-1*(length_2/5)]]);
//rib 2
translate([outer_diameter_2/2,(length_1+mid_length+length_2)-length_2*0.25,0])polygon(points=[[0,0],[0,-1*(length_2/5)],[barb_size_2,-1*(length_2/5)]]);
//rib 3
translate([outer_diameter_2/2,(length_1+mid_length+length_2)-length_2*0.5,0])polygon(points=[[0,0],[0,-1*(length_2/5)],[barb_size_2,-1*(length_2/5)]]);
}
rotate_extrude(angle = 360, convexity = 10) create_profile();
//create_profile();

just move the inner upper point of the barb- resp. the inner lower point of the rib-polygons (the y-value of the second point). To do this calculate the z-delta by tangens of the desired angle.
The code can be simplified by creating modules for barbs and ribs and placing them in for loops, here the modified code:
$fn = 100*1;
// Outer Diameter (bottom)
outer_diameter_1 = 15;
// Wall Thickness (bottom)
wall_thickness_1 = 2;
// Rib Thickness (bottom), set to Zero to remove
barb_size_1 = 0.5;
// Length (bottom)
length_1 = 15;
// Outer Diameter (top), should be smaller than or equal to Outer Diameter (bottom)
outer_diameter_2 = 12;
// Wall Thickness (top)
wall_thickness_2 = 1;
// Rib Thickness (top), set to Zero to remove
barb_size_2 = 0.5;
// Length (top)
length_2 = 15;
// Middle Diameter
mid_diameter = 17;
// Middle Length
mid_length = 5;
// barb angle
ba = 30;
//do not change these
// delta z
// tan(ba) = dz1/barb_size_1
dz1 = barb_size_1*tan(ba);
dz2 = barb_size_2*tan(ba);
inner_diameter_1 = outer_diameter_1 - (wall_thickness_1*2);
inner_diameter_2 = outer_diameter_2 - (wall_thickness_2*2);
module barb(dz) {
polygon(points=[[0, 0],[0, (length_1/5 + dz)],[barb_size_1, (length_1/5)]]);
}
module rib(dz) {
polygon(points=[[0, 0],[0,-1*(length_2/5 + dz)],[barb_size_2,-1*(length_2/5)]]);
}
module create_profile() {
// Middle
polygon(points=[[inner_diameter_1/2,length_1],[mid_diameter/2,length_1],[mid_diameter/2,length_1+mid_length],[inner_diameter_2/2,length_1+mid_length]]);
//length 1
translate([inner_diameter_1/2,0,0])square([wall_thickness_1,length_1]);
//barbs
for (z = [0, 0.25, 0.5]) {
translate([outer_diameter_1/2, length_1*z, 0]) barb(dz1);
}
//length_2
translate([inner_diameter_2/2,length_1+mid_length,0])square([wall_thickness_2,length_2]);
//ribs
for (z = [0, 0.25, 0.5]) {
translate([outer_diameter_2/2,(length_1+mid_length+length_2)-length_2*z,0]) rib(dz2);
}
}
rotate_extrude(angle = 360, convexity = 10) create_profile();
//create_profile();
looks like this:

Here's something that the Openscad list helped me piece together that helps.
////////////////////////////////////////////////////////
// Created by Paul Tibble - 18/7/19 + Openscad group 2021 //
// https://www.thingiverse.com/Paul_Tibble/about //
// Please consider tipping, if you find this useful. //
////////////////////////////////////////////////////////
$fn = 100*1;
// Outer Diameter (bottom)
outer_diameter_1 = 15;
// Wall Thickness (bottom)
wall_thickness_1 = 2;
// Rib Thickness (bottom), set to Zero to remove
barb_size_1 = 0.5;
// Length (bottom)
length_1 = 15;
// Outer Diameter (top), should be smaller than or equal to Outer Diameter (bottom)
outer_diameter_2 = 12;
// Wall Thickness (top)
wall_thickness_2 = 1;
// Rib Thickness (top), set to Zero to remove
barb_size_2 = 0.5;
// Length (top)
length_2 = 15;
// Middle Diameter
mid_diameter = 17;
// Middle Length
mid_length = 5;
// Barb Angles (90 deg) makes it flat 20 to 30
barb_angle = 30; // adjust to get angle you want. 90 or 0 makes it flat rt
// Barb Angles (90 deg) makes it flat 20 to 30
mid_barb_angle = 30; // adjust to get angle you want. 90 or 0 makes it flat rt
barb_angle_tmp_1 = length_1 / barb_angle;
barb_angle_tmp_2 = length_2 / barb_angle;
mid_barb_angle_tmp_1 = mid_diameter / mid_barb_angle - (mid_diameter/2);
//do not change these
inner_diameter_1 = outer_diameter_1 - (wall_thickness_1*2);
inner_diameter_2 = outer_diameter_2 - (wall_thickness_2*2);
module create_profile() {
////////
// Middle
///////
polygon(points=[[inner_diameter_1/2,length_1+mid_barb_angle_tmp_1],[mid_diameter/2,length_1],[mid_diameter/2,length_1+mid_length],[inner_diameter_2/2,length_1+mid_length]]);
//////
//length 1
/////
translate([inner_diameter_1/2,0,0])square([wall_thickness_1,length_1]);
//barb 1
translate([outer_diameter_1/2,0,0])polygon(points=[[0,0],[0,(length_1/5+barb_angle_tmp_1)],[barb_size_1,(length_1/5)]]);
//barb 2
translate([outer_diameter_1/2,length_1*0.25,0])polygon(points=[[0,0],[0,(length_1/5+barb_angle_tmp_1)],[barb_size_1,(length_1/5)]]);
//barb 3
translate([outer_diameter_1/2,length_1*0.5,0])polygon(points=[[0,0],[0,(length_1/5+barb_angle_tmp_1)],[barb_size_1,(length_1/5)]]);
//////
//length 2
/////
translate([inner_diameter_2/2,length_1+mid_length,0])square([wall_thickness_2,length_2]);
//rib 1
translate([outer_diameter_2/2,(length_1+mid_length+length_2),0])polygon(points=[[0,0],[0,-1*(length_2/5+barb_angle_tmp_2)],[barb_size_2,-1*(length_2/5)]]);
//rib 2
translate([outer_diameter_2/2,(length_1+mid_length+length_2)-length_2*0.25,0])polygon(points=[[0,0],[0,-1*(length_2/5+barb_angle_tmp_2)],[barb_size_2,-1*(length_2/5)]]);
//rib 3
translate([outer_diameter_2/2,(length_1+mid_length+length_2)-length_2*0.5,0])polygon(points=[[0,0],[0,-1*(length_2/5+barb_angle_tmp_2)],[barb_size_2,-1*(length_2/5)]]);
}
rotate_extrude(angle = 360, convexity = 10) create_profile();
//create_profile();

Related

Processing 3 - PVector Path offset // inward/outward polygon offsetting

I've got a question that's driving me nuts! :) I've been working on it day and night now :) :)
What is my goal?
Say 2 outside. 2 inside. With Illustrator it is easy :)
My approach so far
Work clockwise. Get angle between P1 & P2
Use trigonometry to calculate the X & Y offset
Add the X & Y offset to P1 & P2. This is how I get the angle between P1 and P2:
float getAngle = (atan((P1.y-P2.y)/(P1.x-p2.x))) * (180/PI) ;
// ( COS(angle) = (adjacent side) / (hypotenuse) ) || 2 = 6 / 3
// ( COS(angle) * (hypotenuse) = (adjacent side) || 2 * 3 = 6
// ( SIN(angle) = (opposite side) / (hypotenuse) ) || 2 = 6 / 3
// ( SIN(angle) * (hypotenuse) = (opposite side) || 2 * 3 = 6
My Problem
I know how to offset the path. But only on 1 side. Always +x and -Y. So this is the result. Almost like just moving the path entirely. Instead of offsetting all around.:
It needs to stay outside the centre/original line.
What would I like from you?
Is there a logic/formula to do this?
Or is there a library that already has this??
I just cannot wrap my head around how I can keep the line offset outside the first/centre line.
Could you get away with scaling the vertices ?
void setup(){
size(400,400);
PVector[] originalPath = randomPath(7,100);
PVector[] insetPath = scalePoints(originalPath,0.75);
PVector[] outsetPath = scalePoints(originalPath,1.25);
background(255);
noFill();
translate(width * .5, height * .5);
stroke(0,192,0);
drawPath(originalPath);
stroke(192,0,0);
drawPath(insetPath);
stroke(0,0,192);
drawPath(outsetPath);
fill(0);
text("original path",originalPath[0].x,originalPath[0].y);
text("inset path",insetPath[1].x,insetPath[1].y);
text("outset path",outsetPath[2].x,outsetPath[2].y);
text("click\nto\nreset",0,0);
}
void drawPath(PVector[] pts){
beginShape();
for(PVector p : pts) vertex(p.x,p.y);
endShape(CLOSE);
}
PVector[] scalePoints(PVector[] pts,float scale){
int numPoints = pts.length;
PVector[] result = new PVector[numPoints];
for(int i = 0 ; i < numPoints; i++){
result[i] = pts[i].get();
result[i].mult(scale);
}
return result;
}
PVector[] randomPath(int numPoints,float r){
PVector[] result = new PVector[numPoints];
float ai = TWO_PI / numPoints;
for(int i = 0 ; i < numPoints; i++){
float radius = random(r-r*.25,r+r*.25);
result[i] = new PVector(cos(ai * i) * radius, sin(ai * i) * radius);
}
return result;
}
void mousePressed(){
setup();
}
void draw(){}

Move y axis labels to left side of heatmap.2

I would like to move the y-axis labels to the left side of heatmap.2. (This is similar, but not the same, as the question regarding moving the axis on heatmap)
While I am able to move the axis by editing line 290 of the heatmap.2 function, it the values then overwrite the actual heatmap.
if (is.null(srtRow) && is.null(colRow)) {
axis(4, iy, labels = labRow, las = 2, line = -0.5 + offsetRow,
tick = 0, cex.axis = cexRow, hadj = adjRow[1], padj = adjRow[2])
}
else {
if (is.null(srtRow) || is.numeric(srtRow)) {
xpd.orig <- par("xpd")
par(xpd = NA)
ypos <- axis(4, iy, labels = rep("", nr), las = 2, #change
line = -0.5, tick = 0)
text(x = par("usr")[2] + (1 + offsetRow) * strwidth("M"),
y = ypos, labels = labRow, adj = adjRow, cex = cexRow,
srt = srtRow, col = colRow)
par(xpd = xpd.orig)
}
I tried moving the location of the heatmap.2 by mucking about with the lwid and lhei options, but the overwrite problem persisted.
Thank you
Eric

OpenGL ES 2.0 perspective projection -> cube is rectangular

[SOLVED - See answer in bottom]
I'm trying to draw a cube with perspective, using OpenGL ES 2.0 on iOS (iPhone), but it's appearing as a rectangular shape.
From what I've gathered searching the web it seems to be related to the viewport / projection matrix, but I can't seem to put the finger on the actual cause.
If I set the viewport to a square measure (width == height) it draws perfectly well (a cube), but if I set it correctly (width = screen_width, height = screen_height) then the cube is drawn as a rectangular shape.
Should setting the Projection matrix accordingly with the Viewport make the cube stay a cube?!
My code (please let me know if more info is needed):
Render method:
// viewportSize is SCREEN_WIDTH and SCREEN_HEIGHT
// viewportLowerLeft is 0.0 and 0.0
ivec2 size = this->viewportSize;
ivec2 lowerLeft = this->viewportLowerLeft;
glViewport(lowerLeft.x, lowerLeft.y, size.x, size.y); // if I put size.x, size.x it draws well
mat4 projectionMatrix = mat4::FOVFrustum(45.0, 0.1, 100.0, size.x / size.y);
glUniformMatrix4fv(uniforms.Projection, 1, 0, projectionMatrix.Pointer());
Matrix operations:
static Matrix4<T> Frustum(T left, T right, T bottom, T top, T near, T far)
{
T a = 2 * near / (right - left);
T b = 2 * near / (top - bottom);
T c = (right + left) / (right - left);
T d = (top + bottom) / (top - bottom);
T e = - (far + near) / (far - near);
T f = -2 * far * near / (far - near);
Matrix4 m;
m.x.x = a; m.x.y = 0; m.x.z = 0; m.x.w = 0;
m.y.x = 0; m.y.y = b; m.y.z = 0; m.y.w = 0;
m.z.x = c; m.z.y = d; m.z.z = e; m.z.w = -1;
m.w.x = 0; m.w.y = 0; m.w.z = f; m.w.w = 1;
return m;
}
static Matrix4<T> FOVFrustum(T fieldOfView, T near, T far, T aspectRatio)
{
T size = near * tanf(DEGREES_TO_RADIANS(fieldOfView) / 2.0);
return Frustum(-size, size, -size / aspectRatio, size / aspectRatio, near, far);
}
If you haven't figured this out already, change:
return Frustum(-size, size, -size / aspectRatio, size / aspectRatio, near, far);
to
return Frustum(-size / aspectRatio, size / aspectRatio, -size, size,, near, far);
and it should draw correctly.
(or simply change the ratio from size.x/size.y to size.y/size.x)
Ok I found out the problem, size.x and size.y are int, so the division returns an int.
1.0 * size.x / size.y
Solves the problem.
facepalm

How to implement Weber contrast of an image in matlab/octave?

I would like to get per-pixel local contrast of an image, and I guess Weber contrast is a plausible formula for that. Question is, how to get it in matlab assuming we just use neighboring pixels (ex, 5x5) for Ib?
To calculate local contrast we need a luminance image, and local background luminance.
Assuming we already have a luminance image, the local background luminance for a particular pixel can be calculated by taking the average over all pixels in the local region.
We can collect a set of such local background regions (one per pixel in the original image) by repeatedly shifting the image by 0:(n-1) pixelsin both horizontal and vertical directions.
The following demo function illustrates the basic idea:
function weberContrastDemo
imgWidthPixels = 1024;
imgHeightPixels = 1024;
localBackgroundSizePixels = 5; % square patch
luminance = randn( imgHeightPixels, imgWidthPixels );
luminance( 496:528, 496:528 ) = 20;
background = localMeanFilter( luminance, localBackgroundSizePixels );
weberContrast = ( luminance - background );% ./ background;
imagesc( weberContrast );
title( 'Weber Contrast' );
colormap(gray);
end
function filteredImg = localMeanFilter( img, regionSizePixels )
offsetImages = getOffsetImages( img, regionSizePixels );
filteredImg = mean( offsetImages, 3 );
end
function buffer = getOffsetImages( img, regionSizePixels )
% GETOFFSETIMAGES
imgSize = size( img );
imgHeight = imgSize( 1 );
imgWidth = imgSize( 2 );
minDelta = 0;
maxDelta = (regionSizePixels-1);
bufferWidth = imgWidth + maxDelta;
bufferHeight = imgHeight + maxDelta;
bufferDepth = regionSizePixels .^ 2;
bufferSize = [ bufferHeight bufferWidth bufferDepth ];
buffer = zeros( bufferSize );
iSample = 0;
for deltaX = minDelta:maxDelta
iStartX = 1 + deltaX;
iEndX = imgWidth + deltaX;
idxX = iStartX:iEndX;
for deltaY = minDelta:maxDelta
iSample = iSample + 1;
iStartY = 1 + deltaY;
iEndY = imgHeight + deltaY;
idxY = iStartY:iEndY;
buffer( idxY, idxX, iSample ) = img;
end
end
iMin = ceil(regionSizePixels/2);
iMax = iMin + (imgWidth-1);
buffer = buffer( iMin:iMax, iMin:iMax, : );
end % GETOFFSETIMAGES
For a real psychophysical experiment we would want to convert parameters from radians or steradians to pixels, and would need to calibrate the display or image capture device so the luminance measure is accurate.

Ray Tracing question, how to map screen coordinates to world coordinates?

I was studying Ray Tracing on http://www.devmaster.net/articles/raytracing_series/part1.php when I came across this piece of code:
void Engine::InitRender()
{
// set first line to draw to
m_CurrLine = 20;
// set pixel buffer address of first pixel
m_PPos = 20 * m_Width;
// screen plane in world space coordinates
m_WX1 = -4, m_WX2 = 4, m_WY1 = m_SY = 3, m_WY2 = -3;
// calculate deltas for interpolation
m_DX = (m_WX2 - m_WX1) / m_Width;
m_DY = (m_WY2 - m_WY1) / m_Height;
m_SY += 20 * m_DY;
// allocate space to store pointers to primitives for previous line
m_LastRow = new Primitive*[m_Width];
memset( m_LastRow, 0, m_Width * 4 );
}
I'm quite confused on how the author map screen coordinates to world coordinates...
Can anyone please tell me how the author derived these lines?
Or tell me how one would map screen coordinates to world coordinates?
// screen plane in world space coordinates
m_WX1 = -4, m_WX2 = 4, m_WY1 = m_SY = 3, m_WY2 = -3;
Thank you in advance!
EDIT: Here is relevant code from raytracer.cpp:
// render scene
vector3 o( 0, 0, -5 );
// initialize timer
int msecs = GetTickCount();
// reset last found primitive pointer
Primitive* lastprim = 0;
// render remaining lines
for(int y = m_CurrLine; y < (m_Height - 20); y++)
{
m_SX = m_WX1;
// render pixels for current line
for ( int x = 0; x < m_Width; x++ )
{
// fire primary ray
Color acc( 0, 0, 0 );
vector3 dir = vector3( m_SX, m_SY, 0 ) - o;
NORMALIZE( dir );
Ray r( o, dir );
float dist;
Primitive* prim = Raytrace( r, acc, 1, 1.0f, dist );
int red = (int)(acc.r * 256);
int green = (int)(acc.g * 256);
int blue = (int)(acc.b * 256);
if (red > 255) red = 255;
if (green > 255) green = 255;
if (blue > 255) blue = 255;
m_Dest[m_PPos++] = (red << 16) + (green << 8) + blue;
m_SX += m_DX;
}
m_SY += m_DY;
// see if we've been working to long already
if ((GetTickCount() - msecs) > 100)
{
// return control to windows so the screen gets updated
m_CurrLine = y + 1;
return false;
}
}
return true;
Therefore the camera is at (0,0,-5) and the screen onto which the world is being projected has top-left corner (-4,3,0) and bottom-right corner (4,-3,0).