Change of coordinates in Javascript: part 3 in a series

The same line; two different mappings to the screen
The same line; two different mappings to the screen

Comments about Change of Basis

The previous article in this series covered drawing lines in Javascript.  This article adds another tool, mapping of coordinates.

It often comes up that the coordinate system used on your computer screen is not the same as the coordinate system for the problem you are working on.  So, there is frequently an need to map between coordinate systems in order to draw a picture of your problem.

I could have done this by writing a function that takes ten parameters, four to describe the screen coordinates, four to describe the coordinates of my problem, and two to describe the point that I want to map to the screen.  However, I choose instead to store the description of the screen and problem coordinates in an object, and just pass the x and y values of the point I wish to map to a method of that object.

I used the Javascript prototype mechanism to make it possible to base other, similar objects on this one.

In the example, I drew two lines from (-1,-1) to (1,1), but varied the screen coordinates that they map to.  The result is one long line starting in the lower left and rising, which is a more
conventional mapping.  The second line is shorter, starts in the upper left corner and falls to the right, because in this coordinate system greater values of y map to points that are lower on the screen.

I didn't demonstrate it, but changing values of an instance of the jgcoordinates will not change the defaults for subsequent new instances. 

The future examples in my series will make use of coordinate mapping.  If you are interested, I
suggest playing around with this mechanism, some.

example code for changing coordinates in javascript

<html>
<head>
<style type="text/css" >
.whiterectangle { color: white; background-color: white; z-index: 0;}
.blackrectangle { color: black; background-color: black; z-index: 1;}
</style>
<script type="text/javascript" >

var jgpointbase = {
	x: 0,
	y: 0
};

function jgpoint( ) {
	//this.x = x;
	//this.y = y;
};

jgpoint.prototype = jgpointbase;

function jgptsc( x, y ) {
		var rval = new jgpoint( );
		rval.x =  this.screenx0 + (( this.screenx1 - this.screenx0 ) / ( this.x1 - this.x0 )) * ( x - this.x0 );
		rval.y =  this.screeny0 + (( this.screeny1 - this.screeny0 ) / ( this.y1 - this.y0 )) * ( y - this.y0 );
		return( rval );
}

var jgcoordinatesbase = {
	x0: -1.25,
	screenx0: 50,
	y0: -1.25,
	screeny0: 450,
	x1: 1.25,
	screenx1: 450,
	y1: 1.25,
	screeny1: 50,
	pointToScreenCoordinates: jgptsc
};

function jgcoordinates() {
}

jgcoordinates.prototype = jgcoordinatesbase;

function drawrectangle( myclass, top, left, width, height )
{
	var bodylist = document.getElementsByTagName( "body" );
	var rect = document.createElement( "div" );
	var mystyle = 'position:absolute;top:' + top + ";left:" + left + ';width:' + width + ";height:" + height;
	rect.setAttribute( "class", myclass );
	rect.setAttribute( "style", mystyle );
	bodylist[0].appendChild( rect );
}

function drawline( width, x1, y1, x2, y2 )
{
	var x, y, nexty, nextx;

	// ensure x1, y1 is leftmost point
	if( x1 > x2 ) {
		tmp = x2;
		x2 = x1;
		x1 = tmp;
		tmp = y2;
		y2 = y1;
		y1 = tmp;
	}
	var dx = x2 - x1;
	var dy = y2 - y1;

	if( dy == 0 ) { // horizontal line
		drawrectangle( "blackrectangle", y1 - width / 2, x1, dx, width );
		return;
	} else if ( dx == 0 ) { // vertical line
		drawrectangle( "blackrectangle", y1, x1 - width / 2, width, dy );
		return;
	}
	var slope = dy / dx;
	if( slope > 1 || slope < -1 ) {
		// one x per multiple y
		if( y1 < y2 ) {
			y = y1;
			for( x = x1 ; x < x2 ; x += 1 ) {
				nexty = y + slope;
				drawrectangle( "blackrectangle", y, x - width / 2, width, nexty - y );
				y = nexty;
			}
		} else {
			y = y1;
			for( x = x1 ; x < x2 ; x += 1 ) {
				nexty = y + slope;
				drawrectangle( "blackrectangle", nexty, x - width / 2, width, y - nexty );
				y = nexty;
			}
		}

	} else {
		// one y per multiple x
		if( y1 < y2 ){
			x = x1;
			for( y = y1 ; y < y2 ; y += 1 ) {
				nextx = x + 1 / slope;
				drawrectangle( "blackrectangle", y - width / 2, x, nextx - x, width );
				x = nextx;
			}
		} else {
			x = x2;
			for( y = y2 ; y < y1 ; y += 1 ) {
				nextx = x + 1 / slope;
				drawrectangle( "blackrectangle", y - width / 2, nextx, x - nextx, width );
				x = nextx;
			}
		}
	}
		
	
}
</script>
</head>
<body>
<script type="text/javascript" >
drawrectangle( "whiterectangle", 0, 0, "100%", "100%" );  // make a background rectangle, not necessary with default browser settings
var unitsquare = new jgcoordinates();
startpoint = unitsquare.pointToScreenCoordinates( -1, -1 );
endpoint = unitsquare.pointToScreenCoordinates( 1, 1 );
drawline( 4, startpoint.x, startpoint.y, endpoint.x, endpoint.y );
unitsquare.screenx0 = 0;
unitsquare.screeny0 = 0;
unitsquare.screenx1 = 50;
unitsquare.screeny1 = 50;
startpoint = unitsquare.pointToScreenCoordinates( -1, -1 );
endpoint = unitsquare.pointToScreenCoordinates( 1, 1 );
drawline( 4, startpoint.x, startpoint.y, endpoint.x, endpoint.y );

</script>
</body>
</html>

More by this Author


Comments

No comments yet.

    Sign in or sign up and post using a HubPages Network account.

    0 of 8192 characters used
    Post Comment

    No HTML is allowed in comments, but URLs will be hyperlinked. Comments are not for promoting your articles or other sites.


    Click to Rate This Article
    working