Reworked arc code - More versatile circles/arcs in horiz and vertical planes

This commit is contained in:
walterhiggins 2013-02-03 12:09:05 +00:00
parent b34d456427
commit 86fd3c0a28
2 changed files with 380 additions and 78 deletions

View file

@ -396,7 +396,7 @@ var Drone = Drone || {
faster cuboid because blockid, meta and world must be provided
use this method when you need to repeatedly place blocks
*/
Drone.prototype.cuboidX = function(blockId, meta, world, w, h, d){
Drone.prototype.cuboidX = function(blockType, meta, world, w, h, d){
if (typeof h == "undefined")
h = 1;
@ -409,7 +409,7 @@ var Drone = Drone || {
var depthFunc = function(){
var block = world.getBlockAt(that.x,that.y,that.z);
block.setTypeIdAndData(blockId,meta,false);
block.setTypeIdAndData(blockType,meta,false);
};
var heightFunc = function(){
_traverse[dir].depth(that,d,depthFunc);
@ -591,67 +591,10 @@ var Drone = Drone || {
print(this.toString());
return this;
};
// ========================================================================
// Private variables and functions
// ========================================================================
var _cylinderX = function(block,radius,height,drone,fill,exactParams)
{
drone.chkpt('cylinderX');
var world = null;
var blockType = null;
var meta = 0;
if (typeof exactParams == "undefined"){
world = drone._getWorld();
bm = drone._getBlockIdAndMeta(block);
blockType = bm[0];
meta = bm[1];
}else{
world = exactParams.world;
blockType = exactParams.blockType;
meta = exactParams.meta;
}
var x0, y0, gotoxy;
drone.right(radius).fwd(radius).chkpt('center');
switch (drone.dir){
case 0: // east
x0 = drone.z;
y0 = drone.x;
gotoxy = function(xo,yo){ return drone.right(xo).fwd(yo);};
break;
case 1: // south
x0 = drone.x;
y0 = drone.z;
gotoxy = function(xo,yo){ return drone.right(xo).fwd(0-yo);};
break;
case 2: // west
x0 = drone.z;
y0 = drone.x;
gotoxy = function(xo,yo){ return drone.right(0-xo).fwd(0-yo);};
break;
case 3: // north
x0 = drone.x;
y0 = drone.z;
gotoxy = function(xo,yo){ return drone.right(xo).fwd(0-yo);};
break;
}
var points = [];
var setPixel = function(a,b){
var xo = (a-x0);
var yo = (b-y0);
if (fill){
// wph 20130114 more efficient esp. for large cylinders/spheres
if (yo < 0){
drone
.fwd(yo).right(xo)
.cuboidX(blockType,meta,world,1,height,Math.abs(yo*2)+1)
.back(yo).left(xo);
}
}else{
gotoxy(xo,yo).cuboidX(blockType,meta,world,1,height,1).move('center');
}
};
/*
do the bresenham thing
*/
var _bresenham = function(x0,y0,radius, setPixel,quadrants){
//
// credit: Following code is copied almost verbatim from
// http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
@ -662,10 +605,23 @@ var Drone = Drone || {
var ddF_y = -2 * radius;
var x = 0;
var y = radius;
setPixel(x0, y0 + radius);
setPixel(x0, y0 - radius);
setPixel(x0 + radius, y0);
setPixel(x0 - radius, y0);
quadrants = quadrants || {topleft: true,
topright: true,
bottomleft: true,
bottomright: true};
/*
II | I
------------
III | IV
*/
if (quadrants.topleft || quadrants.topright)
setPixel(x0, y0 + radius); // quadrant I/II topmost
if (quadrants.bottomleft || quadrants.bottomright)
setPixel(x0, y0 - radius); // quadrant III/IV bottommost
if (quadrants.topright || quadrants.bottomright)
setPixel(x0 + radius, y0); // quadrant I/IV rightmost
if (quadrants.topleft || quadrants.bottomleft)
setPixel(x0 - radius, y0); // quadrant II/III leftmost
while(x < y)
{
@ -681,22 +637,292 @@ var Drone = Drone || {
x++;
ddF_x += 2;
f += ddF_x;
setPixel(x0 + x, y0 + y);
setPixel(x0 - x, y0 + y);
setPixel(x0 + x, y0 - y);
setPixel(x0 - x, y0 - y);
setPixel(x0 + y, y0 + x);
setPixel(x0 - y, y0 + x);
setPixel(x0 + y, y0 - x);
setPixel(x0 - y, y0 - x);
if (quadrants.topright){
setPixel(x0 + x, y0 + y); // quadrant I
setPixel(x0 + y, y0 + x); // quadrant I
}
if (quadrants.topleft){
setPixel(x0 - x, y0 + y); // quadrant II
setPixel(x0 - y, y0 + x); // quadrant II
}
if (quadrants.bottomleft){
setPixel(x0 - x, y0 - y); // quadrant III
setPixel(x0 - y, y0 - x); // quadrant III
}
if (quadrants.bottomright){
setPixel(x0 + x, y0 - y); // quadrant IV
setPixel(x0 + y, y0 - x); // quadrant IV
}
}
};
/*
ArcParams {
drone:
orientation: horizontal || vertical
quadrants: [1,2,3,4]
blockType :
meta:
xyCallback:
radius:
stack:
fill: true || false
world:
}
*/
/*
The daddy of all arc-related API calls -
if you're drawing anything that bends it ends up here.
*/
var _arc2 = function( params ) {
var drone = params.drone;
var orientation = params.orientation || "horizontal";
var quadrants = params.quadrants || {
topright:1,
topleft:2,
bottomleft:3,
bottomright:4
};
var stack = params.stack || 1;
var world = params.world || drone._getWorld();
var radius = params.radius;
var strokeWidth = params.strokeWidth || 1;
drone.chkpt('arc2');
var x0, y0, gotoxy,setPixel;
if (orientation == "horizontal"){
gotoxy = function(x,y){ return drone.right(x).fwd(y);};
drone.right(radius).fwd(radius).chkpt('center');
switch (drone.dir) {
case 0: // east
case 2: // west
x0 = drone.z;
y0 = drone.x;
break;
case 1: // south
case 3: // north
x0 = drone.x;
y0 = drone.z;
}
setPixel = function(x,y) {
x = (x-x0);
y = (y-y0);
if (params.fill){
// wph 20130114 more efficient esp. for large cylinders/spheres
if (y < 0){
drone
.fwd(y).right(x)
.cuboidX(params.blockType,params.meta,world,1,stack,Math.abs(y*2)+1)
.back(y).left(x);
}
}else{
if (strokeWidth == 1)
gotoxy(x,y).cuboidX(params.blockType,
params.meta,
world,
1, // width
stack, // height
strokeWidth // depth
).move('center');
else{
var strokeDir;
var absY = Math.abs(y);
var absX = Math.abs(x);
if (y > 0 && absY >= absX)
strokeDir = 0 ; //down
else if (y < 0 && absY >= absX)
strokeDir = 1 ; // up
else if (x > 0 && absX >= absY)
strokeDir = 2 ; // left
else if (x < 0 && absX >= absY)
strokeDir = 3 ; // right
else
throw new Error("can't get strokeDir");
switch (strokeDir){
case 0: // down
gotoxy(x,y-(strokeWidth-1))
.cuboidX(params.blockType,
params.meta,
world,
1, // width
stack, // height
strokeWidth // depth
).move('center');
break;
case 1: // up
gotoxy(x,y)
.cuboidX(params.blockType,
params.meta,
world,
1, // width
stack, // height
strokeWidth // depth
).move('center');
break;
case 2: // left
gotoxy(x-(strokeWidth-1),y)
.cuboidX(params.blockType,
params.meta,
world,
strokeWidth, // width
stack, // height
1 // depth
).move('center');
break;
case 3: // right
gotoxy(x,y)
.cuboidX(params.blockType,
params.meta,
world,
strokeWidth, // width
stack, // height
1 // depth
).move('center');
break;
}
}
}
};
}else{
// vertical
gotoxy = function(x,y){ return drone.right(x).up(y);};
drone.right(radius).up(radius).chkpt('center');
switch (drone.dir) {
case 0: // east
case 2: // west
x0 = drone.z;
y0 = drone.y;
break;
case 1: // south
case 3: // north
x0 = drone.x;
y0 = drone.y;
}
setPixel = function(x,y) {
x = (x-x0);
y = (y-y0);
if (params.fill){
// wph 20130114 more efficient esp. for large cylinders/spheres
if (y < 0){
drone
.up(y).right(x)
.cuboidX(params.blockType,params.meta,world,1,Math.abs(y*2)+1,stack)
.down(y).left(x);
}
}else{
gotoxy(x,y).cuboidX(params.blockType,params.meta,world,strokeWidth,1,stack).move('center');
}
};
}
/*
setPixel assumes a 2D plane - need to put a block along appropriate plane
*/
_bresenham(x0,y0,radius,setPixel,quadrants);
params.drone.move('arc2');
};
Drone.prototype.arc = function(params) {
params.drone = this;
_arc2(params);
return this;
}
// ========================================================================
// Private variables and functions
// ========================================================================
var _cylinderX = function(block,radius,height,drone,fill,exactParams) {
drone.chkpt('cylinderX');
var world = null;
var blockType = null;
var meta = 0;
if (typeof exactParams == "undefined"){
world = drone._getWorld();
bm = drone._getBlockIdAndMeta(block);
blockType = bm[0];
meta = bm[1];
}else{
world = exactParams.world;
blockType = exactParams.blockType;
meta = exactParams.meta;
}
var x0, y0;
var gotoxy = function(xo,yo){ return drone.right(xo).fwd(yo);};
drone.right(radius).fwd(radius).chkpt('center');
switch (drone.dir){
case 0: // east
case 2: // west
x0 = drone.z;
y0 = drone.x;
break;
case 1: // south
case 3: // north
x0 = drone.x;
y0 = drone.z;
break;
}
var setPixel = function(x,y){
x = (x-x0);
y = (y-y0);
if (fill){
// wph 20130114 more efficient esp. for large cylinders/spheres
if (yo < 0){
drone
.fwd(y).right(x)
.cuboidX(blockType,meta,world,1,height,Math.abs(y*2)+1)
.back(y).left(x);
}
}else{
gotoxy(x,y).cuboidX(blockType,meta,world,1,height,1).move('center');
}
};
_bresenham(x0,y0,radius,setPixel);
return drone.move('cylinderX');
}
var _cylinder0 = function(block,radius,height,exactParams){
return _cylinderX(block,radius,height,this,false,exactParams);
var arcParams = {
radius: radius,
fill: false,
orientation: 'horizontal',
stack: height,
};
if (exactParams){
arcParams.blockType = exactParams.blockType;
arcParams.meta = exactParams.meta;
arcParams.world = exactParams.world;
}else{
var md = this._getBlockIdAndMeta(block);
arcParams.blockType = md[0];
arcParams.meta = md[1];
arcParams.world = this._getWorld();
}
return this.arc(arcParams);
};
var _cylinder1 = function(block,radius,height,exactParams){
return _cylinderX(block,radius,height,this,true,exactParams);
var arcParams = {
radius: radius,
fill: true,
orientation: 'horizontal',
stack: height,
};
if (exactParams){
arcParams.blockType = exactParams.blockType;
arcParams.meta = exactParams.meta;
arcParams.world = exactParams.world;
}else{
var md = this._getBlockIdAndMeta(block);
arcParams.blockType = md[0];
arcParams.meta = md[1];
arcParams.world = this._getWorld();
}
return this.arc(arcParams);
};
var _getDirFromRotation = function(r){
// 0 = east, 1 = south, 2 = west, 3 = north

View file

@ -51,10 +51,86 @@ Drone.extend('sphere', function(block,radius)
//
Drone.extend('sphere0', function(block,radius)
{
return this.sphere(block,radius)
/*
this.sphere(block,radius)
.fwd().right().up()
.sphere(0,radius-1)
.back().left().down();
*/
var lastRadius = radius;
var slices = [[radius,0]];
var diameter = radius*2;
var world = this._getWorld();
var bm = this._getBlockIdAndMeta(block);
var r2 = radius*radius;
for (var i = 0; i <= radius;i++){
var newRadius = Math.round(Math.sqrt(r2 - i*i));
if (newRadius == lastRadius)
slices[slices.length-1][1]++;
else
slices.push([newRadius,1]);
lastRadius = newRadius;
}
this.chkpt('sphere0');
//
// mid section
//
//.cylinder(block,radius,(slices[0][1]*2)-1,{blockType: bm[0],meta: bm[1],world: world})
this.up(radius - slices[0][1])
.arc({blockType: bm[0],
meta: bm[1],
radius: radius,
strokeWidth: 2,
stack: (slices[0][1]*2)-1,
world: world,
fill: false
})
.down(radius-slices[0][1]);
var yOffset = -1;
var len = slices.length;
for (var i = 1; i < len;i++)
{
yOffset += slices[i-1][1];
var sr = slices[i][0];
var sh = slices[i][1];
var v = radius + yOffset, h = radius-sr;
// northern hemisphere
// .cylinder(block,sr,sh,{blockType: bm[0],meta: bm[1],world: world})
this.up(v).fwd(h).right(h)
.arc({
blockType: bm[0],
meta: bm[1],
world: world,
radius: sr,
stack: sh,
fill: false,
strokeWidth: i<len-1?1+(sr-slices[i+1][0]):1
})
.left(h).back(h).down(v);
// southern hemisphere
v = radius - (yOffset+sh+1);
//.cylinder(block,sr,sh,{blockType: bm[0],meta: bm[1],world: world})
this.up(v).fwd(h).right(h)
.arc({
blockType: bm[0],
meta: bm[1],
world: world,
radius: sr,
stack: sh,
fill: false,
strokeWidth: i<len-1?1+(sr-slices[i+1][0]):1
})
.left(h).back(h). down(v);
}
this.move('sphere0');
return this;
});
Drone.extend('hemisphere', function(block,radius, northSouth){
var lastRadius = radius;