[Grace-core] Obejctdraw

Kim Bruce kim at cs.pomona.edu
Fri Dec 20 12:04:49 PST 2013


That's kind of overwhelming (and not very novice friendly).

While looking around for usability studies on graphics libraries, I found the following paper:  "A Portable Graphics Library for Introductory CS" by Eric Roberts and Schwartz.  It presents a graphics library that can be hooked up to virtually any language using a pipe to connect to a Java process.  It would just require us to implement the pipeline and then get all the benefits of the Java graphics facilities.  The library api is very much like the ACM Java graphics library (not surprising -- Eric chaired the committee and I served on it).

I added the paper to the repository under PortableGraphicsLibrary.pdf in background papers

If it looks interesting I can communicate with Eric to find out how we would hook up our stuff to it and see how it works in practice.  I'm guessing it would be easy to use.

Kim



On Dec 20, 2013, at 2:41 AM, Andrew P Black <black at cs.pdx.edu> wrote:

> 
> On 20 Dec 2013, at 14:41 , Kim Bruce <kim at cs.pomona.edu> wrote:
> 
>> Want to take a look at the Point class in Java and steal its API?
> 
> No, it doesn't have an API worth stealing
> Instead, look at Smalltalk's API for Points.  Here it is.  Well, I admit that this is larger than we need, but its a good starting point for pruning.
> 
> 
> *Polymorph-Geometry
> ===================
> directionToLineFrom: p1 to: p2
> 	"Answer the direction of the line from the receiver
> 	position.
> 	< 0 => left (receiver to right)
> 	= => on line
> 	> 0 => right (receiver to left)."
> *Polymorph-Widgets
> ==================
> angle
> 	"Answer the angle in radians between the vectors represented by
> 	the receiver and (1, 0) from the origin."
> angleWith: aPoint
> 	"Answer the angle in radians between the vectors represented by
> 	the receiver and aPoint from the origin."
> max
> 	"Answer a number that is the maximum
> 	of the x and y of the receiver."
> min
> 	"Answer a number that is the minimum
> 	of the x and y of the receiver."
> reflectedAbout: aPoint
> 	"Answer a new point that is the reflection of the receiver about the given point."
> accessing
> =========
> x
> 	"Answer the x coordinate."
> y
> 	"Answer the y coordinate."
> arithmetic
> ==========
> * arg 
> 	"Answer a Point that is the product of the receiver and arg."
> + arg 
> 	"Answer a Point that is the sum of the receiver and arg."
> - arg 
> 	"Answer a Point that is the difference of the receiver and arg."
> / arg 
> 	"Answer a Point that is the quotient of the receiver and arg."
> // arg 
> 	"Answer a Point that is the quotient of the receiver and arg."
> \\ arg 
> 	"Answer a Point that is the mod of the receiver and arg."
> abs
> 	"Answer a Point whose x and y are the absolute values of the receiver's x 
> 	and y."
> reciprocal
> comparing
> =========
> < aPoint 
> 	"Answer whether the receiver is above and to the left of aPoint."
> <= aPoint 
> 	"Answer whether the receiver is neither below nor to the right of aPoint."
> = aPoint
>> aPoint 
> 	"Answer whether the receiver is below and to the right of aPoint."
>> = aPoint 
> 	"Answer whether the receiver is neither above nor to the left of aPoint."
> closeTo: aPoint
> hash
> 	"Hash is reimplemented because = is implemented."
> max: aPoint 
> 	"Answer the lower right corner of the rectangle uniquely defined by the 
> 	receiver and the argument, aPoint."
> min: aPoint 
> 	"Answer the upper left corner of the rectangle uniquely defined by the 
> 	receiver and the argument, aPoint."
> min: aMin max: aMax 
> converting
> ==========
> asFloatPoint
> asIntegerPoint
> asNonFractionalPoint
> asPoint
> 	"Answer the receiver itself."
> corner: aPoint 
> 	"Answer a Rectangle whose origin is the receiver and whose corner is 
> 	aPoint. This is one of the infix ways of expressing the creation of a 
> 	rectangle."
> extent: aPoint 
> 	"Answer a Rectangle whose origin is the receiver and whose extent is 
> 	aPoint. This is one of the infix ways of expressing the creation of a 
> 	rectangle."
> isPoint
> rect: aPoint 
> 	"Answer a Rectangle that encompasses the receiver and aPoint.
> 	This is the most general infix way to create a rectangle."
> copying
> =======
> deepCopy
> 	"Implemented here for better performance."
> veryDeepCopyWith: deepCopier
> extent functions
> ================
> guarded
> scaleTo: anExtent
> geometry
> ========
> isInsideCircle: a with: b with: c 
> sideOf: otherPoint 
> to: end1 intersects: start2 to: end2 
> to: end sideOf: otherPoint 
> triangleArea: b with: c
> point functions
> ===============
> bearingToPoint: anotherPoint
> crossProduct: aPoint 
> 	"Answer a number that is the cross product of the receiver and the 
> 	argument, aPoint."
> dist: aPoint 
> dotProduct: aPoint 
> 	"Answer a number that is the dot product of the receiver and the 
> 	argument, aPoint. That is, the two points are multipled and the 
> 	coordinates of the result summed."
> eightNeighbors
> flipBy: direction centerAt: c
> fourDirections
> fourNeighbors
> grid: aPoint 
> insideTriangle: p1 with: p2 with: p3 
> leftRotated
> nearestPointAlongLineFrom: p1 to: p2 
> nearestPointOnLineFrom: p1 to: p2
> normal
> 	"Answer a Point representing the unit vector rotated 90 deg clockwise. For the zero point return -1 at 0."
> normalized
> octantOf: otherPoint 
> onLineFrom: p1 to: p2
> onLineFrom: p1 to: p2 within: epsilon
> 	"Answer true if the receiver lies on the given line segment between p1 and p2 within a small epsilon."
> quadrantOf: otherPoint
> rightRotated
> rotateBy: direction centerAt: c 
> sign
> sortsBefore: otherPoint
> squaredDistanceTo: aPoint 
> transposed
> polar coordinates
> =================
> degrees
> r
> 	"Answer the receiver's radius in polar coordinate system."
> theta
> 	"Answer the angle the receiver makes with origin in radians. right is 0; 
> 	down is 90. 
> 	Corrected the constants from single precision to 64 Bit precision 
> 	and changed the sends in case of overflow to constants HK 2005-07-23"
> printing
> ========
> printOn: aStream 
> 	"The receiver prints on aStream in terms of infix notation."
> storeOn: aStream 
> self evaluating
> ===============
> isSelfEvaluating
> testing
> =======
> isZero
> transforming
> ============
> adhereTo: aRectangle
> 	"If the receiver lies outside aRectangle, return the nearest point on the boundary of the rectangle, otherwise return self."
> negated
> rotateBy: angle about: center 
> scaleBy: factor 
> 	"Answer a Point scaled by factor (an instance of Point)."
> scaleFrom: rect1 to: rect2
> translateBy: delta 
> 	"Answer a Point translated by delta (an instance of Point)."
> truncation and roundoff
> =======================
> ceiling
> 	"Answer a Point that is the receiver's x and y ceiling. Answer the receiver if its coordinates are already integral."
> floor
> 	"Answer a Point that is the receiver's x and y floor. Answer the receiver if its coordinates are already integral."
> isIntegerPoint
> roundDownTo: grid
> roundTo: grid
> roundUpTo: grid
> rounded
> 	"Answer a Point that is the receiver's x and y rounded. Answer the receiver if its coordinates are already integral."
> truncateTo: grid 
> truncated
> 	"Answer a Point whose x and y coordinates are integers. Answer the receiver if its coordinates are already integral."
> private
> =======
> bitShiftPoint: bits 
> setR: rho degrees: degrees 
> setX: xValue setY: yValue 
> 
> Point is a bad name.  These objects don't represent pixels on the screen, but the mathematical abstraction of a 2D Vector.  That's why they has this protocol; +, for example, is 2DVector addition.
> 
> 2DVectors can be used to _represent_ points on the screen,  points in an abstract space (like a noughts-and-crossed board), or distances and directions in a Cartesian space.   So I think that we should call the type Vector2 or Vec2 rather than Point.
> 
>> http://docs.oracle.com/javase/7/docs/api/
>> The ACM Java graphics library uses GPoint.
>> By the way, the principled reason for using Location rather than Point is that a point usually is visible, whereas a location only indicates a spot.  That is, points would be expected to have an associated pixel that could be colored or erased, whereas a location would not.  Nevertheless I will concede Point as something that most folks use.
> 
> 3 at 4 as an infix constructor is indeed bizarre.  The justification for it is that it simplifies programs that use it.  If one has an infix constructor for Vec2s, then there is no need to provide methods that take separate x and y coordinates, because its just as easy to write, for example, moveTo(3 at 4) as it is to write moveToCoordinates(3,4).    Without such a constructor, one would have to write moveTo(aPoint.x 3 y 4) which is significantly longer and harder to read.  It also means coming up with two names for each method (e.g. moveToPoint() and moveToCoordinates()), because we don't allow overloading by arity.
> 
> [ ... ] as a constructor for lists has the same arguments for and against.
> 
> Here is what Kent Beck says about such constructors (from Best Practice Patterns).
> <Shortcut Constructor Method.pdf>
> 
> The other alternative to a notation like 3 at 4 is to do what Python does: make EVERY method that would take a point take a variable number of arguments, and explicitly writing code that says if there are two arguments turn them into a Vec2, while if there is only one argument treat it as a Vec2.   This takes the complexity out of the basic libraries (no @ on numbers) and pushes it into every program that uses Vec2s.  Is this the right tradeoff for us?
> 
> 	Andrew
> 
> 




More information about the Grace-core mailing list