Drawing Arcs - Hewlett Packard

This is a discussion on Drawing Arcs - Hewlett Packard ; Thanks for the code, Cyrille It seems we had a similar idea, as i started too with a simple Full Circle algorithm, in order to provide some "training ground" for arc (Circle are simpler, there is no need to check ...

+ Reply to Thread
Page 2 of 3 FirstFirst 1 2 3 LastLast
Results 21 to 40 of 43

Thread: Drawing Arcs

  1. Re: Drawing Arcs

    Thanks for the code, Cyrille

    It seems we had a similar idea, as i started too with a simple Full
    Circle algorithm,
    in order to provide some "training ground" for arc
    (Circle are simpler, there is no need to check bearing, just draw the
    pixel).

    Hence i already had an SASM code ready by the time i found yours.
    Anyway, the goal being to learn, it's always good to be able to
    compare.
    It seems your code is using a different syntax than SASM, probably
    MASD.
    I read here and then that MASD syntax is more powerfull than SASM,
    but for the time being, i'm not even able to compile such a piece of
    code using Debug4x.
    Could you give me a hint at how to do that ?

    Anyway, for those interested, here are some results for the current
    Full Circle algorithm, using an HP48SX :
    FastCircle on HP48X :
    30 pixels radius (65,30,30) ===> 0.24s
    60 pixels radius (30,-10,60) ==> 0.31s
    200pixels radios (60,215,200) => 0.75s

    This is a first try, so it most probably can be optimized more.
    But it was very usefull in helping to understand how to write ASM
    Code, and especilly how to initialise graphic area, write pixels, and
    so on.

    This implementation allows center outside of screen (including
    negative numbers), and radius up to 1000 pixels.

    The ASM code can draw circles on any Grob of any size.
    However, the herebelow proposed binary has a SysRPL header, which
    checks arguments, and provide the Graphic Grob as an input to ASM.
    Therefore, the circle is drawn in the Graphic Area, visible using
    GRAPH command (or LEFT arrow).
    A nice side effect is that it should support both 64 & 80 lines
    systems without any problem.
    And if Graphic Area is "larger than screen", it will make use of its
    full size.

    Binaries for both HP48 & HP49/50 are available here :
    http://www.xooimage.com/app/upload.php
    FastCircle V1.0 is 411 Bytes long.

    SASM Source Code can also be downloaded here :
    http://img22.xooimage.com/files/c/a/...ode-56ad87.zip
    Code is in english, but comment are written in french, though....

    Cyrille, i tried to compare both source code, but still lack some
    experience to properly understand MASD.
    It seems your code is much more ambitious, as it can provide GreyScale
    output.
    You're welcomed for any comment.

    OK, now for the more complex arc algorithm...

    Regards

  2. Re: Drawing Arcs

    Hello Jacob

    Here is a first try at an ASM Arc Algorithm :
    http://img21.xooimage.com/files/8/6/...1.0-570f4c.zip

    I've called it Fast Approximative Arc, because it can be wrong by one
    pixel.
    As i was not smart enough to properly understand how you did to check
    if a pixel must be drawn,
    i tried to invent an "homebrew" algorithm, based on circumference
    length
    (The most famous : Circ = 2 x Pi x R).
    Well, on paper, it looks pretty and simple, but it comes with problems
    of its own, especially estimating distance from a trail of pixel and
    correcting cumulated error from the "real" circle.

    As a consequence, this version is not directly comparable with yours.
    I would appreciate if you could give me a hand at understanding how
    you test [pixel within arc], this way it would be possible to create a
    code which use the same algorithm, remaining differences only coming
    from programming language.

    Well, nonetheless, i'm providing binaries for this version, because it
    can still usefull for comparison in the future.
    Input is as follows : X0, Y0, Radius (in pixel), StartBearing,
    EndBearing (in degree, with 0 being North).
    As approximation error increases with Radius, this version limits R to
    60 max.

    Here are some performance results, from an HP48SX (i expect later
    model to perform better) :
    30 pixels radius
    Full : 0.50s
    Half : 0.29s
    Quarter : 0.18s
    Eight : 0.12s
    1 : 0.07s (Note : 0 means "Full Circle", so cannot be tested)

  3. Re: Drawing Arcs

    On Aug 7, 6:32*am, Yann wrote:
    > Hello Jacob
    >
    > Here is a first try at an ASM Arc Algorithm :http://img21.xooimage.com/files/8/6/...e-arc-v1.0-570...
    >
    > I've called it Fast Approximative Arc, because it can be wrong by one
    > pixel.
    > As i was not smart enough to properly understand how you did to check
    > if a pixel must be drawn,
    > i tried to invent an "homebrew" algorithm, based on circumference
    > length
    > (The most famous : Circ = 2 x Pi x R).
    > Well, on paper, it looks pretty and simple, but it comes with problems
    > of its own, especially estimating distance from a trail of pixel and
    > correcting cumulated error from the "real" circle.
    >
    > As a consequence, this version is not directly comparable with yours.
    > I would appreciate if you could give me a hand at understanding how
    > you test [pixel within arc], this way it would be possible to create a
    > code which use the same algorithm, remaining differences only coming
    > from programming language.
    >
    > Well, nonetheless, i'm providing binaries for this version, because it
    > can still usefull for comparison in the future.
    > Input is as follows : X0, Y0, Radius (in pixel), StartBearing,
    > EndBearing (in degree, with 0 being North).
    > As approximation error increases with Radius, this version limits R to
    > 60 max.
    >
    > Here are some performance results, from an HP48SX (i expect later
    > model to perform better) :
    > 30 pixels radius
    > Full : 0.50s
    > Half : 0.29s
    > Quarter : 0.18s
    > Eight : 0.12s
    > 1 * *: 0.07s *(Note : 0 means "Full Circle", so cannot be tested)


    Hello Yann,

    I'll repost the program I came up with and put some explanatory notes
    in along with the code to try and explain it. This is something I am
    not very good at, but should get in the habit of doing regardless. So
    here goes from the top:

    ::
    CK5NOLASTWD
    DOCLLCD
    TURNMENUOFF
    5ROLL
    5ROLL
    COERCE2
    5UNROLL
    5UNROLL
    DUP
    COERCE
    %1
    3PICK
    %-
    BINT0
    DUP
    5ROLL
    DUP
    %*
    %2
    %/
    %SQRT
    COERCE
    BINT2
    {}N
    BINT8
    NDUPN
    DROP
    NULLLAM
    BINT15
    NDUPN
    DOBIND

    ***// This is preparing the input for the program and ends up being:
    LAM 1 - LAM 8 are all lists of {MIN MAX} pixel in x (or y) direction
    and by default I declare all 8 octants as being MIN= BINT0 and MAX=
    (square root of half the radius squared), meaning the full octant
    would be drawn if not otherwise interfered
    LAM 9 = x to be used in bresenham loop, intially BINT0
    LAM 10 = d to be used in bresenham loop, intially 1-radius
    LAM 11 = y=radius
    LAM 12 = bearing to end of arc, clockwise from North (as a surveyor
    this makes more sense to me)
    LAM 13 = bearing to beginning of arc
    LAM 14 = Y0, y pixel coordinate of arc center
    LAM 15 = X0, x pixel coordinate of arc center
    //***

    11GETLAM
    UNCOERCE
    12GETLAM
    %POL>%REC
    %ABS
    SWAP
    %ABS
    SWAP
    COERCE2
    12GETLAM
    COERCE

    ***//The above calculates the delta pixel in x and y directions from
    center to the end of the arc by using the polar to rectangular %POL>
    %REC and leaves in the stack:
    3: deltay (Absolute) from center of arc to pixel that defines the end
    of the arc as a BINT
    2: deltax, same as above
    1: bearing to end of arc
    NOTE: because my program was designed to be intuitive for myself to
    handle compass bearings, the x and y values will be switched later on,
    conveniently if you swap x and y rectangular values you can use %REC>
    %POL and get compass bearings, but that is really another topic
    //***


    11GETLAM
    UNCOERCE
    13GETLAM
    %POL>%REC
    %ABS
    SWAP
    %ABS
    SWAP
    COERCE2
    13GETLAM
    COERCE

    ***//This does the same as before except for the beginning of the arc
    so now we have 6 values in the stack:
    6: deltay (Absolute) from center of arc to pixel that defines the end
    of the arc as a BINT
    5: deltax, same as above BINT
    4: bearing to end of arc BINT
    3: deltay (Absolute) from center of arc to pixel that defines the
    beginning of the arc as a BINT
    2: deltax, same as above BINT
    1: bearing to beginning of arc BINT
    //***

    BINT3
    BINT1
    DO
    BINT9
    BINT1
    DO
    DUP
    BINT45
    INDEX@
    #*
    #1+
    #<
    IT
    ::
    DROP
    INDEX@
    ::
    DUP
    BINT1
    #=case
    TrueTrue
    DUP
    BINT2
    #=case
    FalseFalse
    DUP
    BINT3
    #=case
    TrueFalse
    DUP
    BINT4
    #=case
    FALSETRUE
    DUP
    BINT5
    #=case
    TrueTrue
    DUP
    BINT6
    #=case
    FalseFalse
    DUP
    BINT7
    #=case
    TrueFalse
    DUP
    BINT8
    #=case
    FALSETRUE
    ;
    ITE
    ::
    4ROLL
    DROP
    ;
    ::
    ROT
    DROP
    ;
    ITE
    ::
    SWAP
    JINDEX@
    INDEX@
    GETLAM
    PUTLIST
    INDEX@
    PUTLAM
    ;
    ::
    SWAP
    BINT3
    JINDEX@
    #-
    INDEX@
    GETLAM
    PUTLIST
    INDEX@
    PUTLAM
    ;
    DUP
    BINT14
    JINDEX@
    #-
    PUTLAM
    ISTOPSTO
    ;
    LOOP
    LOOP

    ***//Ok, there's a number of things going on the 2 loops going on, the
    "outer" loop first takes the bearing to first the beginning of arc in
    the first pass, (then bearing to end of arc in second pass) and then
    passes it to the "inner" loop to figure out which octant that bearing
    falls in, once a match is made, 2 flags are generated that enable the
    decisions whether for the corresponding arc, the bresenham loop is
    increasing the x or the y values during each iteration and also if the
    iterations proceed clockwise or counterclockwise, for example the
    first octant if looking at it from north to 45 degrees clockwise uses
    the x value as its going through the iterations and the direction is
    clockwise, the second octant increases the y value and the iteration
    goes counterclockwise. So basically the end product here is that for
    the 2 octants, (or 1 octant) these two loops put the correct {MIN MAX}
    values in the LAM1-LAM8 lists that will tell the bresenham loop
    whether or not to draw the pixel during the iteration.
    //***

    13GETLAM
    12GETLAM
    #>
    BINT9
    BINT1
    DO
    DUP
    INDEX@
    12GETLAM
    #>
    INDEX@
    13GETLAM
    #<
    ROT
    ITE
    AND
    OR
    IT
    ::
    BINT0
    INDEX@
    PUTLAM
    ;
    LOOP
    DROP

    ***//This loop stores BINT0 into any octant LAMs that are not
    contained in the arc, (which is not a list, and later a test is
    performed to check if the corresponding LAM is a list or not
    //***

    BEGIN
    ::
    10GETLAM
    %0<
    case
    ::
    10GETLAM
    9GETLAM
    UNCOERCE
    %2
    %*
    %3
    %+
    %+
    10PUTLAM
    ;
    ::
    10GETLAM
    9GETLAM
    UNCOERCE
    %2
    %*
    11GETLAM
    UNCOERCE
    %2
    %*
    %-
    %5
    %+
    %+
    10PUTLAM
    11GETLAM
    #1-
    11PUTLAM
    ;
    ;
    1GETLAM
    DUPTYPELIST?
    ITE
    ::
    INCOMPDROP
    9GETLAM
    #< NOT
    SWAP
    9GETLAM
    #> NOT
    AND
    IT
    ::
    15GETLAM
    9GETLAM
    #+
    14GETLAM
    11GETLAM
    #-
    PIXON
    ;
    ;
    DROP
    2GETLAM
    DUPTYPELIST?
    ITE
    ::
    INCOMPDROP
    9GETLAM
    #< NOT
    SWAP
    9GETLAM
    #> NOT
    AND
    IT
    ::
    15GETLAM
    11GETLAM
    #+
    14GETLAM
    9GETLAM
    #-
    PIXON
    ;
    ;
    DROP
    3GETLAM
    DUPTYPELIST?
    ITE
    ::
    INCOMPDROP
    9GETLAM
    #< NOT
    SWAP
    9GETLAM
    #> NOT
    AND
    IT
    ::
    15GETLAM
    11GETLAM
    #+
    14GETLAM
    9GETLAM
    #+
    PIXON
    ;
    ;
    DROP
    4GETLAM
    DUPTYPELIST?
    ITE
    ::
    INCOMPDROP
    9GETLAM
    #< NOT
    SWAP
    9GETLAM
    #> NOT
    AND
    IT
    ::
    15GETLAM
    9GETLAM
    #+
    14GETLAM
    11GETLAM
    #+
    PIXON
    ;
    ;
    DROP
    5GETLAM
    DUPTYPELIST?
    ITE
    ::
    INCOMPDROP
    9GETLAM
    #< NOT
    SWAP
    9GETLAM
    #> NOT
    AND
    IT
    ::
    15GETLAM
    9GETLAM
    #-
    14GETLAM
    11GETLAM
    #+
    PIXON
    ;
    ;
    DROP
    6GETLAM
    DUPTYPELIST?
    ITE
    ::
    INCOMPDROP
    9GETLAM
    #< NOT
    SWAP
    9GETLAM
    #> NOT
    AND
    IT
    ::
    15GETLAM
    11GETLAM
    #-
    14GETLAM
    9GETLAM
    #+
    PIXON
    ;
    ;
    DROP
    7GETLAM
    DUPTYPELIST?
    ITE
    ::
    INCOMPDROP
    9GETLAM
    #< NOT
    SWAP
    9GETLAM
    #> NOT
    AND
    IT
    ::
    15GETLAM
    11GETLAM
    #-
    14GETLAM
    9GETLAM
    #-
    PIXON
    ;
    ;
    DROP
    8GETLAM
    DUPTYPELIST?
    ITE
    ::
    INCOMPDROP
    9GETLAM
    #< NOT
    SWAP
    9GETLAM
    #> NOT
    AND
    IT
    ::
    15GETLAM
    9GETLAM
    #-
    14GETLAM
    11GETLAM
    #-
    PIXON
    ;
    ;
    DROP
    9GETLAM
    #1+
    DUP
    9PUTLAM
    11GETLAM
    #>
    UNTIL

    ***//So that is the bresenham loop, and because the x and y values are
    swapped (for surveyor piece of mind) you will find that even though
    the algorithm is the same its simply set up differently to draw the
    pixel I want it to. But for each octant it test if the pixel in
    question during the iteration falls within the range that is {MIN MAX}
    for that octant.
    //***

    ABND
    SetDAsTemp
    WaitForKey
    2DROP
    ;
    @

    I hope this helps at least give the concept of what I was trying to
    do. There are a number of different ways to attack this problem (and
    Claudio seems to at least one more idea I still haven't had the time
    to try out).

    My program I should also modify to allow GRAD mode set, and a few
    other tests to make it more universal...

    Jacob

    P.S. Thanks for the link to your binaries, Most likely a stupid
    question, but when I run the program (with 5 reals in the stack, same
    as the ones I was using or not?) I see only a blank screen, I did the
    PICT RCL and saw only a blank grob, What am I doing wrong?

  4. Re: Drawing Arcs

    Thanks very much for these informations

    Jacob,
    i believe your explanations are quite clear. It should prove enough to
    start again coding.
    I just need to find a way to calculate end/begin x/y without relying
    on RPL calls, should it be possible & efficient.

    Ah, and regarding this first implementation of "approximative arc",
    yes, there is a slight difference in the order of parameters compared
    your version :
    5 : X0
    4 : Y0
    3 : Radius
    2 : Beginning Arc ()
    1 : End Arc ()


    I've spent the last few days at improving the Circle algorithm,
    because this is still a root source for Arc.
    And the results are encouraging.

    After getting rid of the previous "shift" methodology, i end up with
    the following benchmarked results :
    FastCircle V2
    HP48SX
    30 pixels (65,32,30) ==> 92ms
    60 pixels (30,-10,60) ==> 98ms
    200 pixels (60,215,200)==> 195ms


    At this stage, FastCircle seems reasonably well optimised, and does
    even compare favorably to Mark Power's Graph Library (http://
    www.btinternet.com/~mark.power/hp48.htm) and any other assembler code
    from HpCalc.org i could test. I've borrowed some ideas from Mark
    Power's code by the end of development, which did not change
    performance much (even slowed slightly by 1-2%), but help decrease the
    code size.
    As a consequence, FastCircle V2 is still 410 Bytes, although the
    SysRPL header has increased quite a bit, due to a new feature : the
    possibility to draw into any externally defined Grob (optional).

    Input :
    4 : Grob (Optional, if none provided, will draw into Graphic area)
    3 : X0
    2 : Y0
    1 : Radius
    Notes :
    (0,0) is upper left.
    X0 & Y0 can be negative.
    All values are limited to 1000 (Grob Width/Height, X, Y & Radius)

    You can download Binaries & Source code here :
    http://phantasie.tonempire.net/utili...circle-t58.htm


    Cyrille, thank you for all these new inputs,
    i will spend some time to digest everything, and try to make use of it
    for the next step.
    Some parts are still mysterious to me, especially the one where you
    explain using a mask instead of a multiplication. well, that may be
    because i'm tired after a pretty long trip today...

    There are 2 directions which i believe can be investigated to improve
    performances a bit more.

    1) For drawn pixels, i'm using a hand-made multiplication, which is
    faster than standard #MUL call?
    For a standard 131 pixels width screen, it costs 163 cycles, instead
    of 360 as before.
    Quite an improvement, but it is still the most costly operation for a
    drawn pixel.

    Well, i find it quite a waste to do so many tests for each pixel,
    whereas i know since initialisation one of the values, nibble-width.
    For example, should i hard-code a fixed 131 pixels, which is 22h
    nibbles, i would rather program :
    "
    C=C+C A
    B=B+C A
    CSL A
    B=B+C A
    "
    That would be much much faster.

    So, instead of running the full "generic" multiplication code, i've
    ended up with the idea to actually produce the multiplication code at
    initialisation. A kind of "tiny little brother" to modern concept such
    as dynamic compilation.

    I wonder if this can be considered on HP48, and what would be best way
    to achieve this, if this is usefull.
    The first idea was to replace the current space for multiplication by
    a "writable" area, but that means self-modifying code, and does not
    sounds good.
    Another possibility would be to create a temporary object, in which
    the multiplication code will be created, and link to it. Sure, GOSBVL/
    RTN or PC manipulations are not cheap, but well, it should end up with
    some interesting gain.
    I currently wonder it that's actually an interesting idea.
    I should also look a bit more into your mask methodology.

    2) For partial circles (out of area sections), especially for large
    ones,
    the discarding algorithm, although very much improved, still run on a
    per-pixel basis.
    I guess it *could* be faster to discard whole sections if it can be
    easily calculated, at initialisation.
    This is still to be investigated at this stage,
    I have a simple idea in mind currently, based on squares,
    but this is bound to increase code size, so i wonder if this is
    actually worth it.


    Please feel free to comment on any of these lines Cyrille. I think i
    still have a lot to learn from your last posts, so will spend some
    time tomorrow to dig in a bit more.

    Regards

  5. Re: Drawing Arcs

    hello,

    >Some parts are still mysterious to me, especially the one where you
    >explain using a mask instead of a multiplication. well, that may be
    >because i'm tired after a pretty long trip today...


    ok, here is the trick.
    let us say that you KNOW that your first pixel to print is the pixel 2 at
    address X.
    Load X in D1 and load 4 in Ds (because 4 is 0100 or, pixel number 2 set...)

    now, the breasenham algo only works by UP/DOWN or LEFT/RIGHT moves...

    if you want to move UP, just increate D1 by the length of line (assuming
    line lenght is in R0: AD1EX CR0EX.A A+C.A AD1EX CR0EX.A ) and you are done!
    you have the address of the pixel one above in D1 and it's mask in Ds. So,
    to do a pixon, just do C=DAT1.S C!D.S DAT1=C.S
    if you want to move left: DSRB.S ?D#0.S { D1-1 D+8.S } ie: shift the mask 1
    bit to the right, if there is still a bit in Ds, all is ok, else it means
    that you need to work on pixel 3 (2^3=8) at the previous address...

    if you do that, then you only have to calculate the address and mask for 1
    pixel (the first one)...


    >1) For drawn pixels, i'm using a hand-made multiplication, which is
    >faster than standard #MUL call?
    >For a standard 131 pixels width screen, it costs 163 cycles, instead
    >of 360 as before.
    >Quite an improvement, but it is still the most costly operation for a
    >drawn pixel.

    heuu, if you are working on a standard size screen, you can calculate the
    address/mask for a pixel like this:
    %Aa: Y Ca:X R0:@screen
    P=C.0 D0=C C=R0.A % save X in P and D0. C=@Screen
    A+A.A C+A.A ASL.A C+A.A % C=C+A*2+A*2*16 -> C=C+A*34: ie: C=@line where
    pixel is
    AD0EX ASRB.A ASRB.A A+C.A D0=A % D0=@ of the pixel
    LC 1248124812481248 P=0 % Load in Cs the mask of the pixel to turn on...
    that should be around 120 cycles or so and does all the calculations needed
    to turn your pixel on, it only modifies A, C, P and D0...

    but anyhow, this is not a problem as, as stated above, you realy only need
    to do this once at the begining...


    >2) For partial circles (out of area sections), especially for large
    >ones,
    >the discarding algorithm, although very much improved, still run on a
    >per-pixel basis.
    >I guess it *could* be faster to discard whole sections if it can be
    >easily calculated, at initialisation.
    >This is still to be investigated at this stage,
    >I have a simple idea in mind currently, based on squares,
    >but this is bound to increase code size, so i wonder if this is
    >actually worth it.


    I think that the discard should be done by quadran... just work on the
    quadran where there are pixels that needs turning on... this is the best
    because easy to calculate the startup error for a quadran and easy to
    calcualte the X/Y coordinates of the pixel at the begining of the quadran...

    Just stop bothering about size. Size does mater, in some cases, but not in
    this one... there is plenty of space on the calculator so don't sweat it....

    regards, cyrille



  6. Re: Drawing Arcs

    On Aug 7, 6:32*am, Yann wrote:
    > Hello Jacob
    >
    > Here is a first try at an ASM Arc Algorithm :http://img21.xooimage.com/files/8/6/...e-arc-v1.0-570...
    >
    > I've called it Fast Approximative Arc, because it can be wrong by one
    > pixel.
    > As i was not smart enough to properly understand how you did to check
    > if a pixel must be drawn,
    > i tried to invent an "homebrew" algorithm, based on circumference
    > length
    > (The most famous : Circ = 2 x Pi x R).
    > Well, on paper, it looks pretty and simple, but it comes with problems
    > of its own, especially estimating distance from a trail of pixel and
    > correcting cumulated error from the "real" circle.
    >
    > As a consequence, this version is not directly comparable with yours.
    > I would appreciate if you could give me a hand at understanding how
    > you test [pixel within arc], this way it would be possible to create a
    > code which use the same algorithm, remaining differences only coming
    > from programming language.
    >
    > Well, nonetheless, i'm providing binaries for this version, because it
    > can still usefull for comparison in the future.
    > Input is as follows : X0, Y0, Radius (in pixel), StartBearing,
    > EndBearing (in degree, with 0 being North).
    > As approximation error increases with Radius, this version limits R to
    > 60 max.
    >
    > Here are some performance results, from an HP48SX (i expect later
    > model to perform better) :
    > 30 pixels radius
    > Full : 0.50s
    > Half : 0.29s
    > Quarter : 0.18s
    > Eight : 0.12s
    > 1 * *: 0.07s *(Note : 0 means "Full Circle", so cannot be tested)


    Hello Yann,

    I finally have some results from running your program on my 50g, here
    are the times for the 30 pixel radius circle:
    Full: 0.08 seconds
    Half: 0.05 seconds
    Quarter: 0.04 seconds
    Eighth: 0.03 seconds
    1 degree: 0.02 seconds

    That is incredible!!!! The arc simply appears instantly.

    Cyrille, still working on trying to get your arc program running on my
    calculator, for some reason no matter what the input when I call xCC I
    momentarily see a "ray" or "beam" of approximately 1 octant (octant 1
    as described in your program comments) basically from the center of
    the screen out to the extent (or close to) of the screen and the stack
    is unchanged. This happens even when I provide no input at all. Any
    idea as to what I'm doing wrong? I get the same results on Emu48.

    Jacob

  7. Re: Drawing Arcs

    > now, the breasenham algo only works by UP/DOWN or LEFT/RIGHT moves...
    > if you want to move UP, just increate D1 by the length of line (assuming
    > line lenght is in R0: AD1EX CR0EX.A A+C.A AD1EX CR0EX.A ) and you are done!


    OK, now i understand why you are not using circle symetry :
    you need the previous point and its nibble address to determine the
    next one.

    That's indeed very clever, good performances, low complexity, quite a
    dream.
    So be sure that i will make use of it for the next development phase.


    I've been using the last few hours at testing a previously mentionned
    idea : dynamically generate the code for multiplication during
    initialisation, and the results are pretty interesting.
    Actually, the funny thing is that now the multiplication code is so
    fast (28 cycles for a normal 131 pixels screen) that it costs less
    than the jump statements around it (48 cycles).
    I couldn't find anything faster (& simpler) than :
    A=D0 [16] % this in fact is ==> AD0EX D0=A
    APCEX [16]
    (... here is the dynamically created code ending with : )
    APCEX [16] or PC=A [16]

    Well anyway, this was interesting to try, and maybe such a concept
    could be reused later.
    New performance numbers follows :

    FastCircle V2.5 on HP48SX (422 Bytes)
    30 pixels (65,32,30) ==> 76ms
    60 pixels (30,-10,60) ==> 88ms
    200 pixels (60,215,200)==> 184ms

    At this level of performance, i was wondering if the header was
    becoming a bottleneck,
    so i released FastCircle PureCode, for programmers, in order to find
    out, and here are the results :

    FastCircle PureCode v2.5 on HP48SX (299.5 Bytes)
    30 pixels (65,32,30) ==> 56ms
    60 pixels (30,-10,60) ==> 66ms
    200 pixels (60,215,200)==> 161ms

    So it seems that the header does actually cost a fixed 20ms time,
    which is not unexpected.

    You can find the new binaries for all HP platforms at this address :
    http://phantasie.tonempire.net/utili...circle-t58.htm

    I believe this is the last release for full circle drawing, as it
    seems to be a good enough base to work on the real objective of this
    thread, Arcs drawing.


    > here is the code in ASM for an arc.
    > this is a source from a debug4x project, so it should compile readely if you
    > create a project and add this file in (make the project a library)...


    Thanks Cyrille. The sources codes you provided do indeed compile fine,
    both for Arcs & Circles.
    But for some reason, i'm unable to get any "drawn pixel" out of it.
    Note that it does not crash either.

    I've followed instructions to provide inputs directly in registers as
    requested
    % input: D0: @ grob %
    % Aa: Centre x %
    % Ba: Centre y %
    % Ca: Rayon %
    % R0a: 360-AngleStart*8.93608577019 90->804%
    % R1a: 360-AngleEnd*8.93608577019 %

    but to no avail, neither for Arc nor for Circle.

    Furthermore, it seems the header you provided with the second code is
    intentionnally wiping out input data with values of its own.
    Therefore, i was expecting a fixed output from running the code, but
    got a blank screen.

    It could be this is because i'm testing on HP48 S/G, and the results
    might be different on HP49 ?


    > I finally have some results from running your program on my 50g


    Thanks Jacob for taking the time to test it on your calc. Indeed, this
    is encouraging.
    I believe i will get rid of the "one pixel approximation" in the next
    version, thanks to your explanations on algorithm and thanks to
    Cyrille too.

    Regards

  8. Re: Drawing Arcs

    hello,

    >Thanks Cyrille. The sources codes you provided do indeed compile fine,
    >both for Arcs & Circles.
    >But for some reason, i'm unable to get any "drawn pixel" out of it.
    >Note that it does not crash either.


    >I've followed instructions to provide inputs directly in registers as
    >requested

    % input: D0: @ grob %
    % Aa: Centre x %
    % Ba: Centre y %
    % Ca: Rayon %
    % R0a: 360-AngleStart*8.93608577019 90->804%
    % R1a: 360-AngleEnd*8.93608577019 %

    >but to no avail, neither for Arc nor for Circle.


    does D0 point on the prolog of the GROB object or the data part of the GROB?
    if you get it to point on the GROB prolog, it should work....

    regards, cyrille



  9. Re: Drawing Arcs

    Hello Cyrille

    > does D0 point on the prolog of the GROB object or the data part of the GROB?
    > if you get it to point on the GROB prolog, it should work....
    >


    Yes, it is the prolog, straight from the stack :

    C=DAT1.A
    D0=C


    Regards


  10. Re: Drawing Arcs

    hello,

    that is strange.

    anyhow, here is an updated version with some optimizations (skip of first
    quadran if possible (I thouls do the same for the other quadrant, but I do
    not have that much more time to spend on it, so if someone wants to spend
    the time....

    Right now, using emu 48 for timing, it look like it can draw a 23 pixel
    diameter circle in around 8ms....

    if you need help in trying to implement the quadran skip for the Q2, Q3, Q4,
    just send em an email... what needs to be done is implement the skip code
    and remove an extra EXIT in the quatran to skip code at the begiing of the
    circle routine...

    cyrille



    RPL
    ( C:\Documents and Settings\cydeb\Desktop\circle\circ.S, part of the cr.HPP
    project, created by <> on 8/8/2008 )

    INCLUDE cr.h

    xNAME CC
    ::
    CODEM

    SAVE A=DAT1.A A+10.A R4=A.A
    A=0.A R2=A.A
    {
    D0=(5)$806D5 A=DAT0.A D0=A D1=A D1+20
    % erase screen
    A=0.W LC 87 { DAT1=A.16 D1+16 C-1.B UPNC }
    % angles 1 and 2

    D0=(5)$806D5 A=DAT0.A D0=A
    A=0.A R0=A.A LC 00B69 R1=C.A
    % X, Y, radius
    LA 00045 LC 00020 B=C.A LC 17
    GOSUB _Circle P=0

    D0=(5)$806D5 A=DAT0.A D0=A
    A=R2.A R0=A.A LC 0010C A+C.A LC 00B69 { A-C.A UPNC } A+C.A R1=A.A
    % LA 00Af4 R0=A.A LC 0010C A+C.A LC 00B69 { A-C.A UPNC } A+C.A R1=A.A
    % X, Y, radius
    LA 00045 LC 00020 B=C.A LC 15
    GOSUB _Circle P=0
    % LC 01000 { C-1.A UPNC }
    A=R2.A A+16.A R2=A.A LC 00B69 ?A>=C.A EXIT UP
    }
    LOADRPL

    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%
    % Circle asm toolbox %
    % %
    % input: D0: @ grob %
    % Aa: Centre x %
    % Ba: Centre y %
    % Ca: Rayon %
    % R0a: 360-AngleStart*8.4 %
    % R1a: 360-AngleEnd*8.4 %
    % the circle must be in the -2047, 2047 square %
    % Grob can not be bigger than 2048 pixels %
    % %
    % Uses: Carry, P, RSTK2 %
    % D0 (Last pix Plane1) %
    % D1 (Last pix plane2) %
    % R3a: +/- Line Width %
    % Cs: Pixel Mask %
    % As: Undefine %
    % Bs: Undefine %
    % All functions are using standard bresenham algo %
    % D0 is pointing on the bit plan. %
    % During the process, %
    % Am: 4*X Error %
    % Bm: 4*Y Error %
    % Cm: Error %
    % Dm: 2* Radius %
    % Ax: XCurrent %
    % Bx: XMax (Grob Width) %
    % Cx: YCurrent %
    % Dx: YMax (Grob Height) %
    % D0: Pointer on bit plan 1 %
    % D1: Nb Pixel until we turn pixon ON/OFF %
    % Cs: Pixel mask %
    % ST0: currently not drawing pixel (or drawing) %
    % Ds: nuber of pixon/pixof switch before bail out..%
    % Bs: bit feilf for quadrant to skip %
    % R1a: Nb pixel for next series of Pixon/OFF %
    % R3a: Line Width or - Line Width %
    % %
    % The Bresenham algo is use to draw the circle. %
    % The original Bresenham use to compute the circle %
    % Only on 1/8 of the circle and draw the other part%
    % using symetrie. Doing a full pixon is quite slow %
    % with a saturn, so, we are using 8 times %
    % bresenham to draw suxcecivly the 8 octants of %
    % the circle. Am, Bm and Cm are use to store the %
    % values needed by bresenam, Ax, Bx, Cx and Dx are %
    % used to store the current pixel coordinates %
    % and the grob dimention to perform the cliping. %
    % D0 and Cs are use to point on the current %
    % pixel. %
    % %
    % The algo we are using is: %
    % X=2*Rayon-1 %
    % Y=1 %
    % cx=cx+rayon %
    % cy=cy %
    % Error = 0 %
    % pixon(Cx, Cy) %
    % while Y % Begin %
    % Error=Error+Y %
    % Y=Y+2 %
    % cy=cy+1 %
    % If error>=X then %
    % Begin %
    % error= error-X %
    % X=X-2 %
    % cx=cx-1 %
    % End %
    % pixon(Cx, Cy) %
    % End; %
    % while X<>0 do %
    % Begin %
    % Error=Error-X %
    % X=X-2 %
    % cx=cx-1 %
    % If error<0 then %
    % Begin %
    % error= error+Y %
    % Y=Y+2 %
    % cy=cy+1 %
    % End %
    % pixon(Cx, Cy) %
    % End; %
    % %
    % The same routine is used all the time, but %
    % a different Pixon routine is copied in IRAMBUFF %
    % for each type of line, and this routine is used %
    % to affect the pixels. the _Prepx routine are used%
    % to copy the pixon routine in RAM. Note that to %
    % decrease teh amount of used register by this %
    % routine, the code is charged in Cm using LC with %
    % P=3. in order to have a readable code, the LC %
    % mnemonic is not used, bu is replaced by the hex %
    % opcode: 3x where x is the number of nibbles to %
    % load in C-1. at the end of the routine, C[34] are%
    % loaded with 00. This means the this part of the %
    % Ca register is lost %
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% %%
    *_Circle
    ?C=0.A RTY % Fast exit if radius = 0

    ST=0.1 ST=0.2 ST=0.0 % by default, start with pixel not drawn... the ST1 and
    2 are here for protection so the add do not change other flags
    D=0.S D+1.S
    B=0.S
    AR1EX.A CR0EX.A ?C angle, Aa: radius, R0: A2-A1, R1: Cx
    % D= C*A/512 -> D= Angle*8.9*R/512 -> A*2*pi*R/360 -> number of pixels from
    0 to Angle
    ST=0.3
    ?C#0.A
    {
    D-1.S CSTEX C+1.A CSTEX
    ST=1.3
    } SKELSE {
    % build a bitfeild for every quadran that needs to be skipped before we
    start painting
    ?ST=0.0 { { D=C.A LC 002D5 D-C.A EXITC B+1.S D-C.A EXIT EXITC B+2.S D-C.A
    EXITC B+4.S D-C.A EXITC B+8.S } C+D.A }
    D=0.A
    ?ABIT=0.0 { D+C.A } C+C.A
    ?ABIT=0.1 { D+C.A } C+C.A
    ?ABIT=0.2 { D+C.A } C+C.A
    ?ABIT=0.3 { D+C.A } C+C.A
    ?ABIT=0.4 { D+C.A } C+C.A
    ?ABIT=0.5 { D+C.A } C+C.A
    ?ABIT=0.6 { D+C.A } C+C.A
    ?ABIT=0.7 { D+C.A } DSRB.A
    ?ABIT=0.8 { D+C.A } DSRB.A
    ?ABIT=0.9 { D+C.A } DSRB.A
    ?ABIT=0.10 { D+C.A } DSRB.A
    ?ABIT=0.11 { D+C.A } DSRB.A
    DSR.A
    C=D.A D1=C % D1: number of pixel to first change Ca: A2-A1
    }
    C=R0.A D=0.A
    ?ABIT=0.0 { D+C.A } C+C.A
    ?ABIT=0.1 { D+C.A } C+C.A
    ?ABIT=0.2 { D+C.A } C+C.A
    ?ABIT=0.3 { D+C.A } C+C.A
    ?ABIT=0.4 { D+C.A } C+C.A
    ?ABIT=0.5 { D+C.A } C+C.A
    ?ABIT=0.6 { D+C.A } C+C.A
    ?ABIT=0.7 { D+C.A } DSRB.A
    ?ABIT=0.8 { D+C.A } DSRB.A
    ?ABIT=0.9 { D+C.A } DSRB.A
    ?ABIT=0.10 { D+C.A } DSRB.A
    ?ABIT=0.11 { D+C.A } DSRB.A
    DSR.A
    C=D.A ?ST=0.3 { D1=C } ACEX.A AR1EX.A % R1: number of pixel from A1 to A2,
    Ca: radius, Aa: Center X

    A+C.A % Compute cx (cx+Rayon)
    C=0.M C+C.A CSL.A CSL.A CSL.W % Cm=Rayon*2

    D0+10 C=DAT0.X C=D.S D=C.W % Dx: MaxY Dm: Rayon*2 Ds: nb pixel
    color changes...
    D0+5 C=DAT0.A RSTK=C C+7.A CSRB.A CSRB.A CBIT=0.0 R3=C.A % Compute line
    width
    D0+5

    % Aa: cx, Ba: cy, Ca: line lenght, D0: @screen D0=D0+B*C+A/4. Do not modify
    Aa and Ba

    % We must now compute the position of the first pixel
    AD0EX ABEX.A % D0: cx Ba: @Screen, Aa: cy Ca: line width
    C+C.A
    ?ABIT=0.1 { B+C.A } C+C.A % We Want: D0=@Pix+Y*Width+X/4,
    ?ABIT=0.2 { B+C.A } C+C.A % Step 1: Compute B=B+Y*Width ( Width even <=
    512 )
    ?ABIT=0.3 { B+C.A } C+C.A
    ?ABIT=0.4 { B+C.A } C+C.A
    ?ABIT=0.5 { B+C.A } C+C.A
    ?ABIT=0.6 { B+C.A } C+C.A
    ?ABIT=0.7 { B+C.A } C+C.A
    ?ABIT=0.8 { B+C.A } C+C.A
    ?ABIT=0.9 { B+C.A }
    % D0: cx Ba: @Pixel, Aa: cy
    CD0EX D0=C % Ca=X
    P=C.0 CSRB.A CSRB.A B+C.A % Compute pixel address
    ABEX.A AD0EX % Restore Ba=Ba, Aa=Aa, D0 point on pixel on plan
    1
    LC 1248124812481248 P=0 % Compute pixel mask

    C=RSTK BCEX.A % Bx: max X Cx: current y

    { ?ST=0.0 EXIT ?A>=B.X EXIT ?C>=D.X EXIT A=DAT0.S A!C.S DAT0=A.S } % Pixon
    ( With cliping )

    % First quadrant. do we need to bypass this quadrant or not?
    SB=0 BSRB.S ?SB=0 { } SKNC { GOTO .Do_Bypass_Q1 }
    % test for bypass of this quadran..
    % ok, quadrant needs bypassing, so X=X-Radius, Y=Y+Radius.
    DSRC DSRC DSRC DSRB.A CDEX.A % Ca: radius
    D+C.X A-C.X % Update current X and Y
    % Also need to move the pixel pointer... and this without modifying ANY
    registers!
    % need to do D0+R3*Radius+Radius/4 and also deal with the mask...
    AD0EX ABEX.A AR3EX.A % Ba: @ pixel, Aa: line width, Ca: radius
    B=B+A*C. note, A<512 and even
    C+C.A
    ?ABIT=0.1 { B+C.A } C+C.A P=C.0
    CSR.A B-C.A CSL.A C=P.0 % remove radius /4
    ?ABIT=0.2 { B+C.A } C+C.A
    ?ABIT=0.3 { B+C.A } C+C.A
    ?ABIT=0.4 { B+C.A } C+C.A
    ?ABIT=0.5 { B+C.A } C+C.A
    ?ABIT=0.6 { B+C.A } C+C.A
    ?ABIT=0.7 { B+C.A } C+C.A
    ?ABIT=0.8 { B+C.A }
    C=P.0 { C-4.B EXITC CSRB.S ?C#0.S UP B-1.A C+8.S UPNC }
    CSR.A CSR.A % restore C (radius)
    AR3EX.A ABEX.A AD0EX % restore updated D0, Aa and Ba
    CDEX.A D+D.A DSLC DSLC DSLC P=14 % restore Current Y, max Y and radius
    SKIP {
    *.Do_Bypass_Q1
    C=D.M A=C.M % X=Am=Rayon
    C=0.M % Y=Cm=0
    B=0.M % Er=0
    A-1.M C+1.M % Because the bresenham algo need to add -(X-1) or
    Y+1, we already add the 1 to X and Y
    P=14
    % Octant 1 From a=0 to - 45
    {
    ?A<=C.M EXIT % End of octant? X B+C.M % er+Y
    C+2.M C+1.X % Y+2, cy+1
    CR3EX.W % cy+1 part2
    AD0EX A+C.A AD0EX
    CR3EX.W

    D1-1 SKNC { CD1EX CR1EX.A CD1EX D-1.S RTNC CSTEX C+1.A CSTEX } % count
    pixels, turn pixelON Flag on/off as needed, update counter

    ?B= X
    {
    B-A.M % er - X
    A-2.M A-1.X % X-2, cx-1
    CSRB.S ?C#0.S { C+8.S D0-1 } % cx-1 part2
    } % Else, error<0
    ?ST=0.0 UP ?A>=B.X UP ?C>=D.X UP A=DAT0.S A!C.S DAT0=A.S UPNC % Pixon (
    With cliping )
    }
    % Octant 2. From a=-45 to -90
    {
    ?A#0.P EXIT % End of octan?
    B-A.M % er - X
    A-2.M A-1.X % X-2, cx-1
    CSRB.S ?C#0.S { C+8.S D0-1 } % cx-1 part2

    D1-1 SKNC { CD1EX CR1EX.A CD1EX D-1.S RTNC CSTEX C+1.A CSTEX } % count
    pixels, turn pixelON Flag on/off as needed, update counter

    ?B=0.P % if B>0 then do nothing
    { % else,
    B+C.M C+2.M C+1.X % er+Y, Y+2, cy+1
    CR3EX.W % cy+1 part2
    AD0EX A+C.A AD0EX
    CR3EX.W
    }
    ?ST=0.0 UP ?A>=B.X UP ?C>=D.X UP A=DAT0.S A!C.S DAT0=A.S UPNC % Pixon (
    With cliping )
    }
    }
    % Octant 3 From a=-90 to -135
    % Doing the same thing again, but inverting Y and X
    C=D.M A=C.M B=0.M C=0.M % ReInitializing values
    A-1.M C+1.M % Because the bresenham algo need to add -(X-1) or
    Y+1, we already add the 1 to X and Y
    {
    ?A<=C.M EXIT % End of octant? X B+C.M % er+Y
    C+2.M A-1.X % Y+2, cx-1
    CSRB.S ?C#0.S { C+8.S D0-1 } % cx-1 part2

    D1-1 SKNC { CD1EX CR1EX.A CD1EX D-1.S RTNC CSTEX C+1.A CSTEX } % count
    pixels, turn pixelON Flag on/off as needed, update counter

    ?B= X
    {
    B-A.M % er - X
    A-2.M C-1.X % X-2, cy-1
    CR3EX.W % cy-1 part2
    AD0EX A-C.A AD0EX
    CR3EX.W
    } % Else, error<0
    ?ST=0.0 UP ?A>=B.X UP ?C>=D.X UP A=DAT0.S A!C.S DAT0=A.S UPNC % Pixon (
    With cliping )
    }
    % Octant 4. From a=-135 to -180
    {
    ?A#0.P EXIT % End of octan?
    B-A.M % er - X
    A-2.M C-1.X % X-2, cy-1
    CR3EX.W % cy-1 part2
    AD0EX A-C.A AD0EX
    CR3EX.W

    D1-1 SKNC { CD1EX CR1EX.A CD1EX D-1.S RTNC CSTEX C+1.A CSTEX } % count
    pixels, turn pixelON Flag on/off as needed, update counter

    ?B=0.P % if B>0 then do nothing
    { % else,
    B+C.M C+2.M A-1.X % er+Y, Y+2, cx-1
    CSRB.S ?C#0.S { C+8.S D0-1 } % cx-1 part2
    }
    ?ST=0.0 UP ?A>=B.X UP ?C>=D.X UP A=DAT0.S A!C.S DAT0=A.S UPNC % Pixon (
    With cliping )
    }
    % Octant 5 From a=-180 to -225
    % Doing the same thing again, but inverting Y and X again and differantly
    C=D.M A=C.M B=0.M C=0.M % Reinitializing values
    A-1.M C+1.M % Because the bresenham algo need to add -(X-1) or
    Y+1, we already add the 1 to X and Y
    {
    ?A<=C.M EXIT % End of octant? X B+C.M % er+Y
    C+2.M C-1.X % Y+2, cy-1
    CR3EX.A % cy-1 part2
    AD0EX A-C.A AD0EX
    CR3EX.A

    D1-1 SKNC { CD1EX CR1EX.A CD1EX D-1.S RTNC CSTEX C+1.A CSTEX } % count
    pixels, turn pixelON Flag on/off as needed, update counter

    ?B= X
    {
    B-A.M % er - X
    A-2.M A+1.X % X-2, cx+1
    C+C.S SKNC { C+1.S D0+1 } % cx+1 part2
    } % Else, error<0
    ?ST=0.0 UP ?A>=B.X UP ?C>=D.X UP A=DAT0.S A!C.S DAT0=A.S UPNC % Pixon (
    With cliping )
    }
    % Octant 6. From a=-225 to -270
    {
    ?A#0.P EXIT % End of octan?
    B-A.M % er - X
    A-2.M A+1.X % X-2, cx+1
    C+C.S SKNC { C+1.S D0+1 } % cx+1 part2

    D1-1 SKNC { CD1EX CR1EX.A CD1EX D-1.S RTNC CSTEX C+1.A CSTEX } % count
    pixels, turn pixelON Flag on/off as needed, update counter

    ?B=0.P % if B>0 then do nothing
    { % else,
    B+C.M C+2.M C-1.X % er+Y, Y+2, cy-1
    CR3EX.A % cy-1 part2
    AD0EX A-C.A AD0EX
    CR3EX.A
    }
    ?ST=0.0 UP ?A>=B.X UP ?C>=D.X UP A=DAT0.S A!C.S DAT0=A.S UPNC % Pixon (
    With cliping )
    }
    % Octant 7 From a=-270 to -315
    % Doing the same thing again, but inverting Y and X again and differantly
    C=D.M A=C.M B=0.M C=0.M % Reinitializing values
    A-1.M C+1.M % Because the bresenham algo need to add -(X-1) or
    Y+1, we already add the 1 to X and Y
    {
    ?A<=C.M EXIT % End of octant? X B+C.M % er+Y
    C+2.M A+1.X % Y+2, cx+1
    C+C.S SKNC { C+1.S D0+1 } % cx+1 part2

    D1-1 SKNC { CD1EX CR1EX.A CD1EX D-1.S RTNC CSTEX C+1.A CSTEX } % count
    pixels, turn pixelON Flag on/off as needed, update counter

    ?B= X
    {
    B-A.M % er - X
    A-2.M C+1.X % X-2, cy+1
    CR3EX.A % cy+1 part2
    AD0EX A+C.A AD0EX
    CR3EX.A
    } % Else, error<0
    ?ST=0.0 UP ?A>=B.X UP ?C>=D.X UP A=DAT0.S A!C.S DAT0=A.S UPNC % Pixon (
    With cliping )
    }
    % Octant 8. From a=-315 to -360
    {
    B-A.M % er - X
    A-2.M C+1.X % X-2, cy+1
    CR3EX.A % cy+1 part2
    AD0EX A+C.A AD0EX
    CR3EX.A

    D1-1 SKNC { CD1EX CR1EX.A CD1EX D-1.S RTNC CSTEX C+1.A CSTEX } % count
    pixels, turn pixelON Flag on/off as needed, update counter

    ?B=0.P % if B>0 then do nothing
    { % else,
    B+C.M C+2.M A+1.X % er+Y, Y+2, cx+1
    C+C.S SKNC { C+1.S D0+1 } % cx+1 part2
    }
    ?A#0.P EXIT % End of octan?
    ?ST=0.0 UP ?A>=B.X UP ?C>=D.X UP A=DAT0.S A!C.S DAT0=A.S UPNC % Pixon (
    With cliping )
    }
    P=0 RTN

    ENDCODE

    ;

    "Yann" wrote in message
    news:ede8ccab-33f2-4bce-986f-32a54e52be26@m73g2000hsh.googlegroups.com...
    > Hello Cyrille
    >
    >> does D0 point on the prolog of the GROB object or the data part of the
    >> GROB?
    >> if you get it to point on the GROB prolog, it should work....
    >>

    >
    > Yes, it is the prolog, straight from the stack :
    >
    > C=DAT1.A
    > D0=C
    >
    >
    > Regards
    >




  11. Re: Drawing Arcs

    Thanks Cyrille, i will look into it

  12. Re: Drawing Arcs

    OK, Fine, i've got it working on a HP48GX.

    It seems to produce an "animation" with a small arc traveling into a
    larger full-circle.
    I expect this is fully intended by the header you produced.

    HP48SX on the other hand does not display anything (but there is some
    activity for sure)
    I noticed that you selected a fixed address for output, $806D5, which
    seems to be =ADISP (->Stack grob).
    Maybe GX and SX do not have the same behavior with it.
    For example, this could be because the screen is not "refreshed" while
    the ASM code is running.

    OK, so for now i cannot time your code, but i guess i just need to
    rewrite the header and that should be ok.
    With such a speed announced, i believe there is plenty to learn from
    reading your code.

    Regards

  13. Re: Drawing Arcs

    hello,

    > HP48SX on the other hand does not display anything (but there is some
    > activity for sure)
    > I noticed that you selected a fixed address for output, $806D5, which
    > seems to be =ADISP (->Stack grob).
    > Maybe GX and SX do not have the same behavior with it.
    > For example, this could be because the screen is not "refreshed" while
    > the ASM code is running.


    On the SX, the address of the display is not the same than the GX.. so, on
    the SX, you need to change $806D5 to some other address to get the demo
    working...

    if all you want to do is create an ARC program that takes a gROB as input,
    it will be compatible for SX/GX...
    if running on an apple, you can probably replace some of the code
    (multiplications) by some optimized multiplications instructions...

    > With such a speed announced, i believe there is plenty to learn from
    > reading your code.

    :-) well, I do have some experience developing Saturn code... so that
    helps...

    regards, cyrille



  14. Re: Drawing Arcs

    On Mon, 11 Aug 2008 17:52:25 -0500, Yann wrote:

    > OK, Fine, i've got it working on a HP48GX.
    > HP48SX on the other hand does not display anything...
    > a fixed address for output, $806D5, which seems to be =ADISP (->Stack grob).
    > Maybe GX and SX do not have the same behavior with it.


    Mika's "ent-srt.doc" (an old bible says:

    70000 - 707D9 RAM pointer & status area [S/SX]

    Pointer Name Description
    70551 VDISP2 Menu display grob
    70556 ADISP Text display grob
    7055B VDISP Current display grob
    70560* PDISP Pict grob???
    70565 GDISP Graphic display grob
    7056A* TEMPBOT Bottom of tempob area (?)
    7056F TEMPTOP Top of tempob area
    70574* RETTOP Top of rpl return stack
    FREE RAM
    70579 DSKTOP Top of stack
    7057E* DSKBOT Bottom of stack[*] not "supported"

    Whereas in G/GX: [non-rom starts at 80000 rather than 70000]

    806D5 ADISP
    806DA VDISP
    806DF PDISP
    806E4 GDISP
    806E9 TEMPBOT
    806EE TEMPTOP
    806F3 RETTOP
    806F8 DSKTOP
    806FD DSKBOT

    To get the same document:

    http://www.hpcalc.org/search.php?query=ent_srt

    [r->] [OFF]

  15. Re: Drawing Arcs

    Hello

    I rewrote the header of your code, Cyrille, in order to have it using
    the same convention as Jacob (Bearing 0 is North, Clockwise) and
    output in Graphical display, for both HP48SX & GX.

    You can download both SourceCode & Binary at :
    http://phantasie.tonempire.net/utili...arc-t59.htm#61

    No problem with speed, it is hand down the fastest code around, with
    output in the less-than-40ms zone for 48GX, including SysRPL header
    which costs about 11ms alone.

    However, there are still some issues with this version :

    1) Accuracy is not correct. I've displayed some screenshots in the
    link to illustrate.
    I think this is a direct consequence of the selected methodology
    (pixel counting).
    I had the same issue with my first code some time ago, with equivalent
    accuracy consequences.

    2) The first quarter is sometimes not drawn. Probably a bug into the
    discarding code.
    I tried to remove it in order to release a usable binary, but
    unfortunately it produced additionnal side effects, such as a sudden
    90 output shift depending on input values (try Start Bearing = -1 &
    +1).

    The bug can probably be corrected, but the accuracy may require a
    different methodology, potentially resulting non-trivial code changes.

    As a personal sidenote, i must add that your code provided me with the
    perfect opportunity to start learning MASD. So thanks for your
    contribution.

  16. Re: Drawing Arcs

    just to read this posting gives me
    as a log time hp user (1st my very own was HP-21)
    a very warm feeling

    thank you Cyrille and U 2, Yann
    VPN

    "Yann" wrote in message
    news:94754a55-b72a-4776-a8a2-ad8fdf00bb20@m45g2000hsb.googlegroups.com...
    Hello

    I rewrote the header of your code, Cyrille, in order to have it using
    the same convention as Jacob (Bearing 0 is North, Clockwise) and
    output in Graphical display, for both HP48SX & GX.

    You can download both SourceCode & Binary at :
    http://phantasie.tonempire.net/utili...arc-t59.htm#61

    No problem with speed, it is hand down the fastest code around, with
    output in the less-than-40ms zone for 48GX, including SysRPL header
    which costs about 11ms alone.

    However, there are still some issues with this version :

    1) Accuracy is not correct. I've displayed some screenshots in the
    link to illustrate.
    I think this is a direct consequence of the selected methodology
    (pixel counting).
    I had the same issue with my first code some time ago, with equivalent
    accuracy consequences.

    2) The first quarter is sometimes not drawn. Probably a bug into the
    discarding code.
    I tried to remove it in order to release a usable binary, but
    unfortunately it produced additionnal side effects, such as a sudden
    90 output shift depending on input values (try Start Bearing = -1 &
    +1).

    The bug can probably be corrected, but the accuracy may require a
    different methodology, potentially resulting non-trivial code changes.

    As a personal sidenote, i must add that your code provided me with the
    perfect opportunity to start learning MASD. So thanks for your
    contribution.



  17. Re: Drawing Arcs

    On Aug 12, 5:27*pm, "Veli-Pekka Nousiainen"
    wrote:
    > just to read this posting gives me
    > as a log time hp user (1st my very own was HP-21)
    > a very warm feeling
    >
    > thank you Cyrille and U 2, Yann
    > VPN


    You are a *logarithmic* time HP calulator user?
    Hmm.........

  18. Re: Drawing Arcs

    at least if you look back
    then timescale seems to be compressed
    :-D
    "username localhost" wrote in message
    news:c02d4b4e-29e4-4dc0-a3e7-6c1afe36922c@x35g2000hsb.googlegroups.com...
    On Aug 12, 5:27 pm, "Veli-Pekka Nousiainen"
    wrote:
    > just to read this posting gives me
    > as a log time hp user (1st my very own was HP-21)
    > a very warm feeling
    >
    > thank you Cyrille and U 2, Yann
    > VPN


    You are a *logarithmic* time HP calulator user?
    Hmm.........



  19. Re: Drawing Arcs

    At last,
    here is a (long awaited) usable version for Fast Arc, which seems
    reasonably accurate to be of any use.

    The binaries for HP48, 49 and 50 can be downloaded at this website :
    http://fastarc.webhop.org/

    Input :
    6 : Grob (<-- Optional, if none provided, will draw into Graphic Area)
    5 : X0
    4 : Y0
    3 : Radius
    2 : Start Bearing ()
    1 : End Bearing ()

    Being based on the code sample by Cyrille de Brebisson, it is quite
    fast, although after completing the fullcircle code, the focus was no
    longer speed, but rather arc accuracy, and getting something out of
    the door before any real life issues prevent me from working on it.
    Version 1 seems now completed. This version have the following change
    compared to previous releases :

    1) Accurary :
    Granted, the algorithm is still at its core based on an approximation,
    but this time, approximation should be less than one pixel, meaning in
    fact full accuracy as far as display is concerned.
    I've tried to trick the program in a number of way, and could no
    longer find any blatant loophole with this version.
    Some samples screenshots are provided in the link for illustration

    2) Breisenham's cache
    Well, i wanted to bring something new, so here it is.
    I added a simple but effective cache algorithm, which allows to run
    breisenham only once, reusing output for all octants. It significantly
    improves performances and makes the code shorter (a simple read-cache
    replace the optimized breisenham algo within each octant).

    3) Expanded Boundaries
    Due to improvements in register allocation, the input limits are now
    fairly large, up to 250 000.
    It is also possible to define X0 and Y0 (the center of the circle) as
    negative values.


    Thanks to Cyrille's "nibble traveler" methodology, which avoids
    calculating memory pixel location, performance are good.
    As a funny side effect, now the program spends more time in the header
    than drawing the arc. This was tested with the "PureCode" version,
    which removes the header, and it resulted in 31ms being spent on
    header alone (on GX), which means twice more time than is necessary to
    draw a 30pixels half-circle on the same platform.
    Of course, performances on newer platform should be even better.

    There are still some room for improvement though, especially as i
    really did not optimized the "arc specific" part of the code. This is
    partly because my focus was much more on getting something accurate
    and fastly available.

    Some ideas which could make it in a future release if need be :
    - Sector discarding : this avoids to "loop" for each not-drawed pixel,
    improving performances for circles with parts out of screen. Of
    course, this cost some bytes to program.
    - Dynamic compilation : the program would create the code which draws
    Arc, using inputs to optimized tests and loops. This will improve
    performance by a good margin, and potentially reduce code size too. It
    is complex though, and make maintenance more difficult. So this is
    rather a "last move" to do, when everything else is stable.

    Well, i guess the next move could be on functionality, instead of ever
    more performances.
    For example, how to allow a user to "replace" the embedded "Arc"
    function with this one ?
    Would a "forced save" with "ARC" global name in the HOME directory be
    enough for this ?
    Eventually, i can also add some more features to the header to make it
    compatible to HP syntax on top of the one already documented in this
    thread. Well, if that is usefull...

  20. Re: Drawing Arcs

    On Aug 14, 7:08*pm, Yann wrote:
    > At last,
    > here is a (long awaited) usable version for Fast Arc, which seems
    > reasonably accurate to be of any use.
    >
    > The binaries for HP48, 49 and 50 can be downloaded at this website :http://fastarc.webhop.org/
    >
    > Input :
    > 6 : Grob (<-- Optional, if none provided, will draw into Graphic Area)
    > 5 : X0
    > 4 : Y0
    > 3 : Radius
    > 2 : Start Bearing ()
    > 1 : End Bearing ()
    >
    > Being based on the code sample by Cyrille de Brebisson, it is quite
    > fast, although after completing the fullcircle code, the focus was no
    > longer speed, but rather arc accuracy, and getting something out of
    > the door before any real life issues prevent me from working on it.
    > Version 1 seems now completed. This version have the following change
    > compared to previous releases :
    >
    > 1) Accurary :
    > Granted, the algorithm is still at its core based on an approximation,
    > but this time, approximation should be less than one pixel, meaning in
    > fact full accuracy as far as display is concerned.
    > I've tried to trick the program in a number of way, and could no
    > longer find any blatant loophole with this version.
    > Some samples screenshots are provided in the link for illustration
    >
    > 2) Breisenham's cache
    > Well, i wanted to bring something new, so here it is.
    > I added a simple but effective cache algorithm, which allows to run
    > breisenham only once, reusing output for all octants. It significantly
    > improves performances and makes the code shorter (a simple read-cache
    > replace the optimized breisenham algo within each octant).
    >
    > 3) Expanded Boundaries
    > Due to improvements in register allocation, the input limits are now
    > fairly large, up to 250 000.
    > It is also possible to define X0 and Y0 (the center of the circle) as
    > negative values.
    >
    > Thanks to Cyrille's "nibble traveler" methodology, which avoids
    > calculating memory pixel location, performance are good.
    > As a funny side effect, now the program spends more time in the header
    > than drawing the arc. This was tested with the "PureCode" version,
    > which removes the header, and it resulted in 31ms being spent on
    > header alone (on GX), which means twice more time than is necessary to
    > draw a 30pixels half-circle on the same platform.
    > Of course, performances on newer platform should be even better.
    >
    > There are still some room for improvement though, especially as i
    > really did not optimized the "arc specific" part of the code. This is
    > partly because my focus was much more on getting something accurate
    > and fastly available.
    >
    > Some ideas which could make it in a future release if need be :
    > - Sector discarding : this avoids to "loop" for each not-drawed pixel,
    > improving performances for circles with parts out of screen. Of
    > course, this cost some bytes to program.
    > - Dynamic compilation : the program would create the code which draws
    > Arc, using inputs to optimized tests and loops. This will improve
    > performance by a good margin, and potentially reduce code size too. It
    > is complex though, and make maintenance more difficult. So this is
    > rather a "last move" to do, when everything else is stable.
    >
    > Well, i guess the next move could be on functionality, instead of ever
    > more performances.
    > For example, how to allow a user to "replace" the embedded "Arc"
    > function with this one ?
    > Would a "forced save" with "ARC" global name in the HOME directory be
    > enough for this ?
    > Eventually, i can also add some more features to the header to make it
    > compatible to HP syntax on top of the one already documented in this
    > thread. Well, if that is usefull...


    Hello Yann,

    This is terrific!!! I've done some tests and everything looks great.
    Here are my results using a 50g with the same input values you were
    using for your 48 tests (Fastarc_v1.hp49&50.hp):

    30px, Quarter Circle: 25ms
    30px, Half Circle: 26ms
    30px, Full Circle: 30ms
    60px, Full Circle: 33ms
    150px, 3/4 Circle: 41ms

    Much faster than my SysRPL program :-), congratulations on your
    incredible success.

    Jacob

+ Reply to Thread
Page 2 of 3 FirstFirst 1 2 3 LastLast