Reworked arc code - More versatile circles/arcs in horiz and vertical planes
This commit is contained in:
parent
b34d456427
commit
86fd3c0a28
2 changed files with 380 additions and 78 deletions
|
@ -396,7 +396,7 @@ var Drone = Drone || {
|
||||||
faster cuboid because blockid, meta and world must be provided
|
faster cuboid because blockid, meta and world must be provided
|
||||||
use this method when you need to repeatedly place blocks
|
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")
|
if (typeof h == "undefined")
|
||||||
h = 1;
|
h = 1;
|
||||||
|
@ -409,7 +409,7 @@ var Drone = Drone || {
|
||||||
|
|
||||||
var depthFunc = function(){
|
var depthFunc = function(){
|
||||||
var block = world.getBlockAt(that.x,that.y,that.z);
|
var block = world.getBlockAt(that.x,that.y,that.z);
|
||||||
block.setTypeIdAndData(blockId,meta,false);
|
block.setTypeIdAndData(blockType,meta,false);
|
||||||
};
|
};
|
||||||
var heightFunc = function(){
|
var heightFunc = function(){
|
||||||
_traverse[dir].depth(that,d,depthFunc);
|
_traverse[dir].depth(that,d,depthFunc);
|
||||||
|
@ -591,67 +591,10 @@ var Drone = Drone || {
|
||||||
print(this.toString());
|
print(this.toString());
|
||||||
return this;
|
return this;
|
||||||
};
|
};
|
||||||
|
/*
|
||||||
// ========================================================================
|
do the bresenham thing
|
||||||
// Private variables and functions
|
*/
|
||||||
// ========================================================================
|
var _bresenham = function(x0,y0,radius, setPixel,quadrants){
|
||||||
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');
|
|
||||||
}
|
|
||||||
};
|
|
||||||
//
|
//
|
||||||
// credit: Following code is copied almost verbatim from
|
// credit: Following code is copied almost verbatim from
|
||||||
// http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
|
// http://en.wikipedia.org/wiki/Midpoint_circle_algorithm
|
||||||
|
@ -662,10 +605,23 @@ var Drone = Drone || {
|
||||||
var ddF_y = -2 * radius;
|
var ddF_y = -2 * radius;
|
||||||
var x = 0;
|
var x = 0;
|
||||||
var y = radius;
|
var y = radius;
|
||||||
setPixel(x0, y0 + radius);
|
quadrants = quadrants || {topleft: true,
|
||||||
setPixel(x0, y0 - radius);
|
topright: true,
|
||||||
setPixel(x0 + radius, y0);
|
bottomleft: true,
|
||||||
setPixel(x0 - radius, y0);
|
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)
|
while(x < y)
|
||||||
{
|
{
|
||||||
|
@ -681,22 +637,292 @@ var Drone = Drone || {
|
||||||
x++;
|
x++;
|
||||||
ddF_x += 2;
|
ddF_x += 2;
|
||||||
f += ddF_x;
|
f += ddF_x;
|
||||||
setPixel(x0 + x, y0 + y);
|
if (quadrants.topright){
|
||||||
setPixel(x0 - x, y0 + y);
|
setPixel(x0 + x, y0 + y); // quadrant I
|
||||||
setPixel(x0 + x, y0 - y);
|
setPixel(x0 + y, y0 + x); // quadrant I
|
||||||
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.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');
|
return drone.move('cylinderX');
|
||||||
}
|
}
|
||||||
var _cylinder0 = function(block,radius,height,exactParams){
|
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){
|
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){
|
var _getDirFromRotation = function(r){
|
||||||
// 0 = east, 1 = south, 2 = west, 3 = north
|
// 0 = east, 1 = south, 2 = west, 3 = north
|
||||||
|
|
|
@ -51,10 +51,86 @@ Drone.extend('sphere', function(block,radius)
|
||||||
//
|
//
|
||||||
Drone.extend('sphere0', function(block,radius)
|
Drone.extend('sphere0', function(block,radius)
|
||||||
{
|
{
|
||||||
return this.sphere(block,radius)
|
/*
|
||||||
|
this.sphere(block,radius)
|
||||||
.fwd().right().up()
|
.fwd().right().up()
|
||||||
.sphere(0,radius-1)
|
.sphere(0,radius-1)
|
||||||
.back().left().down();
|
.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){
|
Drone.extend('hemisphere', function(block,radius, northSouth){
|
||||||
var lastRadius = radius;
|
var lastRadius = radius;
|
||||||
|
|
Reference in a new issue