i am programming voxelizing algorithm in unity.
and now it turns out that i need some fansy intersection checking between cube and polygon.
actually i have a code here.
public static bool Intersects(Triangle tri, Bounds aabb)
{
float p0, p1, p2, r;
Vector3 extents = aabb.max - aabb.center;
Vector3 v0 = tri.a - aabb.center,
v1 = tri.b - aabb.center,
v2 = tri.c - aabb.center;
Vector3 f0 = v1 - v0,
f1 = v2 - v1,
f2 = v0 - v2;
Vector3 a00 = new Vector3(0, -f0.z, f0.y),
a01 = new Vector3(0, -f1.z, f1.y),
a02 = new Vector3(0, -f2.z, f2.y),
a10 = new Vector3(f0.z, 0, -f0.x),
a11 = new Vector3(f1.z, 0, -f1.x),
a12 = new Vector3(f2.z, 0, -f2.x),
a20 = new Vector3(-f0.y, f0.x, 0),
a21 = new Vector3(-f1.y, f1.x, 0),
a22 = new Vector3(-f2.y, f2.x, 0);
// Test axis a00
p0 = Vector3.Dot(v0, a00);
p1 = Vector3.Dot(v1, a00);
p2 = Vector3.Dot(v2, a00);
r = extents.y * Mathf.Abs(f0.z) + extents.z * Mathf.Abs(f0.y);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
{
return false;
}
// Test axis a01
p0 = Vector3.Dot(v0, a01);
p1 = Vector3.Dot(v1, a01);
p2 = Vector3.Dot(v2, a01);
r = extents.y * Mathf.Abs(f1.z) + extents.z * Mathf.Abs(f1.y);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
{
return false;
}
// Test axis a02
p0 = Vector3.Dot(v0, a02);
p1 = Vector3.Dot(v1, a02);
p2 = Vector3.Dot(v2, a02);
r = extents.y * Mathf.Abs(f2.z) + extents.z * Mathf.Abs(f2.y);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
{
return false;
}
// Test axis a10
p0 = Vector3.Dot(v0, a10);
p1 = Vector3.Dot(v1, a10);
p2 = Vector3.Dot(v2, a10);
r = extents.x * Mathf.Abs(f0.z) + extents.z * Mathf.Abs(f0.x);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
{
return false;
}
// Test axis a11
p0 = Vector3.Dot(v0, a11);
p1 = Vector3.Dot(v1, a11);
p2 = Vector3.Dot(v2, a11);
r = extents.x * Mathf.Abs(f1.z) + extents.z * Mathf.Abs(f1.x);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
{
return false;
}
// Test axis a12
p0 = Vector3.Dot(v0, a12);
p1 = Vector3.Dot(v1, a12);
p2 = Vector3.Dot(v2, a12);
r = extents.x * Mathf.Abs(f2.z) + extents.z * Mathf.Abs(f2.x);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
{
return false;
}
// Test axis a20
p0 = Vector3.Dot(v0, a20);
p1 = Vector3.Dot(v1, a20);
p2 = Vector3.Dot(v2, a20);
r = extents.x * Mathf.Abs(f0.y) + extents.y * Mathf.Abs(f0.x);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
{
return false;
}
// Test axis a21
p0 = Vector3.Dot(v0, a21);
p1 = Vector3.Dot(v1, a21);
p2 = Vector3.Dot(v2, a21);
r = extents.x * Mathf.Abs(f1.y) + extents.y * Mathf.Abs(f1.x);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
{
return false;
}
// Test axis a22
p0 = Vector3.Dot(v0, a22);
p1 = Vector3.Dot(v1, a22);
p2 = Vector3.Dot(v2, a22);
r = extents.x * Mathf.Abs(f2.y) + extents.y * Mathf.Abs(f2.x);
if (Mathf.Max(-Mathf.Max(p0, p1, p2), Mathf.Min(p0, p1, p2)) > r)
{
return false;
}
if (Mathf.Max(v0.x, v1.x, v2.x) < -extents.x || Mathf.Min(v0.x, v1.x, v2.x) > extents.x)
{
return false;
}
if (Mathf.Max(v0.y, v1.y, v2.y) < -extents.y || Mathf.Min(v0.y, v1.y, v2.y) > extents.y)
{
return false;
}
if (Mathf.Max(v0.z, v1.z, v2.z) < -extents.z || Mathf.Min(v0.z, v1.z, v2.z) > extents.z)
{
return false;
}
var normal = Vector3.Cross(f1, f0).normalized;
var pl = new Plane(normal, Vector3.Dot(normal, tri.a));
return Intersects(pl, aabb);
}
public static bool Intersects(Plane pl, Bounds aabb)
{
Vector3 center = aabb.center;
var extents = aabb.max - center;
var r = extents.x * Mathf.Abs(pl.normal.x) + extents.y * Mathf.Abs(pl.normal.y) + extents.z * Mathf.Abs(pl.normal.z);
var s = Vector3.Dot(pl.normal, center) - pl.distance;
return Mathf.Abs(s) <= r;
}
but it is just very hard to understand the process and why it works...
so it would be very appreciated if there's short explaining on this code or another short algorithm.
cheers
Related
Hello I try to appear a plot in R with step 0.1 inside the space [0-89] and I do not know how.
The code is :
c1 = 1500
c2 = 1600
c3 = 1850
p1 = 1000
p2 = 1300
p3 = 1500
h = 100
f = 500
w = 2 *pi * f
k2 = w / c2
i = complex( real = 0, imaginary = 1 )
th1 = ( 0:89 )
th1 = th1 * pi / 180
th2 = asin( pmin(pmax((c2 / c1) * sin (th1),-1.0),1.0) )
th3 = asin(pmin(pmax(( c3 / c2) * sin (th2),-1.0),1.0) )
R12 = (p2 * c2 * cos(th1) - p1 * c1 * cos(th2) ) / (p2 * c2 * cos(th1) + p1 * c1 * cos (th2))
R23 = (p3 * c3 * cos(th2) - p2 * c2 * cos(th3)) / (p3 * c3 * cos(th2) + p2 * c2 * cos (th3))
phi2 = k2 * h * cos(th2)
R13 = (R12 + R23 * exp(2 * i * phi2 ))/ ( 1+ R12 * R23 * exp(2 * i* phi2))
y=abs(R13)
th1=th1*180/pi
plot(th1 , y, type = "l", xlab="Angle of Incidence (Deg)", ylab="|R13|")
axis(side=1, at=seq(0, 100, by=10))
axis(side=2, at=seq(0, 1, by=0.1))
The plot that I take is :
I did it in matlab and the command is t = 0:0.1:89. So if I use this step 0.1 I have a plot like this:
Can you help me on how can I make this work and in R ?
In your code th1 = ( 0:89 ) generates a sequence with a step of 1. If you change that line with th1 = seq(0,89, 0.05), the step will now be 0.05 instead of 1.
Can you please tell me that is there any other way to plot data with duplication in more better way than this one ? The duplication is not clear in this plot.
library(ggplot2)
p <- ggplot(output, aes(output$Longitudes, output$Latitudes))
p + geom_text(aes(x = jitter(output$Longitudes), y =
jitter(output$Latitudes)),check_overlap = FALSE, size =5)
p + geom_point(position = "jitter")
The purpose of showing the duplication on a particular point is to show the occurrences.
To visualize duplicate points you can:
Add jitter (eg., use geom_jitter)
Lower alpha (eg., alpha = 0.1)
Decrease size of points (eg., size = 1)
Change shape of points (eg., shape = 21)
Code:
# Generate data
df <- reshape2::melt(data.frame(A = rep(0, 1e3), B = rep(1, 1e3)))
# Plot data
library(ggplot2)
ggplot(df, aes(variable, value)) +
geom_jitter(alpha = 0.5, size = 2, shape = 21) +
theme_classic()
Plot:
This is actually one of my biggest gripes about ggplot.
So much so that I wrote my own solution (other than jitter / alpha).
Solution
Essentially it is a new "position" called position_bunch, which distributes the points at each unique (X,Y) according to a pattern. It can be used like:
g = ggplot(...) +
geom_point(
position = position_bunch(
shape = 'hex',
width = .7,
sort = TRUE,
)
)
yielding stuff like:
Implementation
position_bunch = function(shape='hex',width=0.5,sort=1) {
if (shape == 'hex') {
n.layer.fun = n.layer.hex
delta.fun = delta.hex
}
if (shape == 'square') {
n.layer.fun = n.layer.square
delta.fun = delta.square
}
if (shape == 'spiral') {
n.layer.fun = n.layer.spiral
delta.fun = delta.spiral
}
if (sort) {
sort.fun = sorting.fun
} else {
sort.fun = identity
}
cols = c('x','y')
return(ggproto('PositionBunch',Position,
required_aes = cols,
compute_layer = function(self,data,params,layout) {
select = function(x,y) {
return((data$x==x) & (data$y==y))
}
u = unique(data[,cols])
n = mapply(function(x,y) {sum(select(x,y))},u$x,u$y)
l.max = n.layer.fun(max(n))
delta = sort.fun(delta.fun(l.max),1)
for (i in 1:nrow(u)) {
rows = select(u$x[i],u$y[i])
delta.i = sort.fun(delta[1:sum(rows),cols],sort) * (width/2/l.max)
data[rows,cols] = data[rows,cols] + delta.i
}
return(data)
})
)
}
sorting.fun = function(delta,dir) {
distance = apply(delta,1,function(d){sum(d^2)})
return(delta[order(distance,decreasing=(dir==-1)),])
}
# -----------------------------------------------------------------------------
# hex
n.layer.hex = function(n) {
return(floor(1+(-3+sqrt(9+12*(n-1)))/6))
}
delta.hex = function(layers) {
yv = sqrt(3)/2; yh = 0; xv = 0.5; xh = 1;
rep.steps = function(steps,layer,dim) {
steps = rep(steps,each=layer)
steps[1] = steps[1] + xv*(dim=='x') - yv*(dim=='y')
return(steps)
}
dx = 0; dy = 0;
for (layer in 1:layers) {
dx = c(dx,rep.steps(c(+xv,-xv,-xh,-xv,+xv,+xh),layer,dim='x'))
dy = c(dy,rep.steps(c(+yv,+yv, yh,-yv,-yv, yh),layer,dim='y'))
}
return(data.frame(x=cumsum(dx),y=cumsum(dy)))
}
# -----------------------------------------------------------------------------
# square
n.layer.square = function(n) {
return(floor(1+(-2+sqrt(4+8*(n-1)))/4))
}
delta.square = function(layers) {
yv = 1; yh = 0; xv = 0; xh = 1;
rep.steps = function(steps,layer,dim) {
steps = rep(steps,each=2*layer)
steps[1] = steps[1] + xh*(dim=='x') - yv*(dim=='y')
return(steps)
}
dx = 0; dy = 0;
for (layer in 1:layers) {
dx = c(dx,rep.steps(c( xv,-xh, xv,+xh),layer,dim='x'))
dy = c(dy,rep.steps(c(+yv, yh,-yv, yh),layer,dim='y'))
}
return(data.frame(x=cumsum(dx),y=cumsum(dy)))
}
# -----------------------------------------------------------------------------
# spiral
f.spiral = pi*(1+sqrt(5))
n.layer.spiral = function(n) {
return(ceiling(n/f.spiral))
}
delta.spiral = function(layers){
i = 0:ceiling(layers*f.spiral)
r = layers/2*sqrt(i/layers)
t = pi*(1+sqrt(5))*i
dx = r * cos(t)
dy = r * sin(t)
return(data.frame(x=cumsum(dx),y=cumsum(dy)))
}
Test Code
library('ggplot2')
library('gridExtra')
library('viridis')
source('ggpositions.r')
set.seed(1234)
g.list = list()
for (N in c(10,100,500)){
data = data.frame(
x = factor(floor(runif(N,1,3+1)),labels=c('A','B','C')),
y = factor(floor(runif(N,1,3+1))),
z = rev(sort(runif(N,1,N)))
)
for (shape in c('hex','square','spiral')){
g = ggplot(data,aes(x=x,y=y,color=z)) +
geom_point(position=position_bunch(
shape = shape,
width = .7,
),size=sqrt(2)/log10(N)) +
scale_color_viridis() +
xlab(NULL) + ylab(NULL) +
theme(legend.position='none')
g.list[[length(g.list)+1]] = g
}
}
G = do.call(arrangeGrob,g.list)
ggsave('test.png',G)
Notes
It's a work in progress -- feedback welcome!
I've only tested it with geom_point using aes(x= ,y= ) so far
Point sizes are hard to scale reliably, so you may have to tinker manually
After cleaning & testing, I plan to upload to the ggplot2 extensions library
I'm trying to get the scatterplot3d package of R to render within a Beaker Notebook, but cannot get it to work. I can run the code without error, but the graphic is not displayed. Setting the scatterplot3d output to a variable and printing the variables gets:
input:
data(iris)
test <- scatterplot3d(iris[,1:3])
test
output:
$xyz.convert
function (x, y = NULL, z = NULL)
{
xyz <- xyz.coords(x, y, z)
if (angle > 2) {
temp <- xyz$x
xyz$x <- xyz$y
xyz$y <- temp
}
y <- (xyz$y - y.add)/y.scal
return(list(x = xyz$x/x.scal + yx.f * y, y = xyz$z/z.scal +
yz.f * y))
}
<environment: 0x00000000048f8830>
$points3d
function (x, y = NULL, z = NULL, type = "p", ...)
{
xyz <- xyz.coords(x, y, z)
if (angle > 2) {
temp <- xyz$x
xyz$x <- xyz$y
xyz$y <- temp
}
y2 <- (xyz$y - y.add)/y.scal
x <- xyz$x/x.scal + yx.f * y2
y <- xyz$z/z.scal + yz.f * y2
mem.par <- par(mar = mar, usr = usr)
on.exit(par(mem.par))
if (type == "h") {
y2 <- z.min + yz.f * y2
segments(x, y, x, y2, ...)
points(x, y, type = "p", ...)
}
else points(x, y, type = type, ...)
}
<environment: 0x00000000048f8830>
$plane3d
function (Intercept, x.coef = NULL, y.coef = NULL, lty = "dashed",
lty.box = NULL, ...)
{
if (!is.atomic(Intercept) && !is.null(coef(Intercept)))
Intercept <- coef(Intercept)
if (is.null(lty.box))
lty.box <- lty
if (is.null(x.coef) && length(Intercept) == 3) {
x.coef <- Intercept[if (angle > 2)
3
else 2]
y.coef <- Intercept[if (angle > 2)
2
else 3]
Intercept <- Intercept[1]
}
mem.par <- par(mar = mar, usr = usr)
on.exit(par(mem.par))
x <- x.min:x.max
ltya <- c(lty.box, rep(lty, length(x) - 2), lty.box)
x.coef <- x.coef * x.scal
z1 <- (Intercept + x * x.coef + y.add * y.coef)/z.scal
z2 <- (Intercept + x * x.coef + (y.max * y.scal + y.add) *
y.coef)/z.scal
segments(x, z1, x + y.max * yx.f, z2 + yz.f * y.max, lty = ltya,
...)
y <- 0:y.max
ltya <- c(lty.box, rep(lty, length(y) - 2), lty.box)
y.coef <- (y * y.scal + y.add) * y.coef
z1 <- (Intercept + x.min * x.coef + y.coef)/z.scal
z2 <- (Intercept + x.max * x.coef + y.coef)/z.scal
segments(x.min + y * yx.f, z1 + y * yz.f, x.max + y * yx.f,
z2 + y * yz.f, lty = ltya, ...)
}
<environment: 0x00000000048f8830>
$box3d
function (...)
{
mem.par <- par(mar = mar, usr = usr)
on.exit(par(mem.par))
lines(c(x.min, x.max), c(z.max, z.max), ...)
lines(c(0, y.max * yx.f) + x.max, c(0, y.max * yz.f) + z.max,
...)
lines(c(0, y.max * yx.f) + x.min, c(0, y.max * yz.f) + z.max,
...)
lines(c(x.max, x.max), c(z.min, z.max), ...)
lines(c(x.min, x.min), c(z.min, z.max), ...)
lines(c(x.min, x.max), c(z.min, z.min), ...)
}
<environment: 0x00000000048f8830>
I'm not sure if this functionality is possible with Beaker Notebooks, but thought I check here if anyone has any tips.
Thanks,
-pH+
it worked for me, just by making sure the library was loaded: https://pub.beakernotebook.com/#/publications/312f12ee-1619-11e6-8e18-afd4bf712b6e
Figured it out. As part of my code, I was changing the working directory of R to more easily pull in datafiles from my project folder via:
setwd("C:/Users/macle/Desktop/UPC Masters/Semester 1/CN/MAI-CN/Final Project")
It appears that somewhere along the way, this breaks the ability of scatterplot3d to display the output in a Beaker Notebook.
I've instead just used absolute paths to load the files I need, which has solved the issue for me.
#spot Thanks for pointing me in the right direction and confirming the issue was on my end and not a limitation of Beaker.
Ps. I love working with Beaker, thanks for developing such a fantastic tool.
I have a fixed point (x1, y1) and a moving/rotating point (x2, y2), how do I find the tangent inverse point (x3, y3)
My circle radius is 40.
Assuming p1 and p2 are 2-vectors, the following will do it.
v12 = normalize(p2 - p1) // the unit vector from p1 to p2
p3 = p1 - 40 * v12 // 40 away from p1 in the direction opposite p2
The value of normalize(u) is simply u / sqrt(u.x * u.x + u.y * u.y).
achieved it this way, modified to be rotated to any angle
http://jsfiddle.net/christianpugliese/g2Lk9k12/1/
var dx = x2 - x1;
var dy = y2 - y1;
var radianAngle = Math.atan2(dy, dx);
var diameter = -80;
p3x = x1 + diameter * Math.cos(radianAngle);
p3y = y1 + diameters * Math.sin(radianAngle);
Is it possible to smooth the lines/edges for a polygon? It's currently very sharp and angular and it would be great if those angles actually had curvature to them. Any ideas?
Add additional points into your polygon. The more points that are plotted, the more gradual the curve will be.
Here is a smoothing algorithm based on bSpline that worked for me on Android inspired by https://johan.karlsteen.com/2011/07/30/improving-google-maps-polygons-with-b-splines/
public List<LatLng> bspline(List<LatLng> poly) {
if (poly.get(0).latitude != poly.get(poly.size()-1).latitude || poly.get(0).longitude != poly.get(poly.size()-1).longitude){
poly.add(new LatLng(poly.get(0).latitude,poly.get(0).longitude));
}
else{
poly.remove(poly.size()-1);
}
poly.add(0,new LatLng(poly.get(poly.size()-1).latitude,poly.get(poly.size()-1).longitude));
poly.add(new LatLng(poly.get(1).latitude,poly.get(1).longitude));
Double[] lats = new Double[poly.size()];
Double[] lons = new Double[poly.size()];
for (int i=0;i<poly.size();i++){
lats[i] = poly.get(i).latitude;
lons[i] = poly.get(i).longitude;
}
double ax, ay, bx, by, cx, cy, dx, dy, lat, lon;
float t;
int i;
List<LatLng> points = new ArrayList<>();
// For every point
for (i = 2; i < lats.length - 2; i++) {
for (t = 0; t < 1; t += 0.2) {
ax = (-lats[i - 2] + 3 * lats[i - 1] - 3 * lats[i] + lats[i + 1]) / 6;
ay = (-lons[i - 2] + 3 * lons[i - 1] - 3 * lons[i] + lons[i + 1]) / 6;
bx = (lats[i - 2] - 2 * lats[i - 1] + lats[i]) / 2;
by = (lons[i - 2] - 2 * lons[i - 1] + lons[i]) / 2;
cx = (-lats[i - 2] + lats[i]) / 2;
cy = (-lons[i - 2] + lons[i]) / 2;
dx = (lats[i - 2] + 4 * lats[i - 1] + lats[i]) / 6;
dy = (lons[i - 2] + 4 * lons[i - 1] + lons[i]) / 6;
lat = ax * Math.pow(t + 0.1, 3) + bx * Math.pow(t + 0.1, 2) + cx * (t + 0.1) + dx;
lon = ay * Math.pow(t + 0.1, 3) + by * Math.pow(t + 0.1, 2) + cy * (t + 0.1) + dy;
points.add(new LatLng(lat, lon));
}
}
return points;
}