Drawing rudimentary graphics in text mode

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Message
Author
Aacini
Expert
Posts: 1885
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Drawing rudimentary graphics in text mode

#1 Post by Aacini » 03 Jan 2012 23:32

Although graphic applications had been used for years as the "computer standard", text mode may still be used to show interesting graphics (like 25 years ago!). Note that "rudimentary" term refer to the graphics presentation, not to the graphic contents. Batch programs below use Fixed Point arithmetic operations described in this post.

Let's start with the widely known statistical Bar graphic:

Code: Select all

@echo off
::Statistical Bar Graph drawing
::Antonio Perez Ayala - Jan/03/2012

setlocal EnableDelayedExpansion

set Set1=10 11 12 13 14 15 16 17 18 19 20 21
set Set2=24 22 20 18 16 14 16 18 20 22 24 26
set Set3=24 23 22 21 20 19 18 17 16 15 14 13
set Set4=14 16 18 20 22 24 22 20 18 16 14 12
set Set5=10 10 10 10 10 10 10 10 10 10 10 10
set SetNames=GROWING "DOWN TO UP" SHRINKING "UP TO DOWN" FLAT
set ValueNames=Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec

cls
echo/
echo       T H I S   I S   T H E   T I T L E   O F   T H E   B A R   G R A P H
echo/
call :DrawBarGraph 34 Set SetNames ValueNames
goto :EOF


:DrawBarGraph BarHeight SetsVar SetsNamesVar ValueNamesVar

rem Separate and count SetsVar elements
set /A maxV=0, numJ=9999, i=1
:nextSet
   set j=0
   for %%v in (!%2%i%!) do (
      set /A j+=1
      set V%i%.!j!=%%v
      if %%v gtr !maxV! set maxV=%%v
   )
   if %j% lss %numJ% set numJ=%j%
   set /A i+=1
   if defined %2%i% goto nextSet
set /A numI=i-1

rem Map elements to fit the graph
for /L %%i in (1,1,%numI%) do (
   for /L %%j in (1,1,%numJ%) do (
      set /A V%%i.%%j=V%%i.%%j * %1 / %maxV%
   )
)

rem Show set names
set i=0
for %%c in (█ ░ ▓ ▄ ▒) do (
   set /A i+=1
   set C!i!=%%c
)
set /A nameWide=(80/(numI+1))/2
set nameSep=
for /L %%n in (1,1,%nameWide%) do set nameSep= !nameSep!
set /P =%nameSep%< NUL
set nameSep=%nameSep%%nameSep%
set /A nameWide*=2, i=0
for %%n in (!%3!) do (
   set /A i+=1
   set name=%%~n%nameSep%
   for %%i in (!i!) do set /P =!C%%i! !name:~0,%nameWide%!< NUL
)
echo/
echo/
echo/

rem Get wide of left margin, bars and separators
set /A barWide=80/(numI*numJ)
if %barWide% gtr 10 set barWide=10
if %barWide% gtr 2 set /A barWide-=1
set /A nameWide=barWide*numI
set /A sepWide=(80-nameWide*numJ)/(numJ-1), leftWide=(80-nameWide*numJ-sepWide*(numJ-1))/2, nameWide+=sepWide
set leftBar=
for /L %%w in (1,1,%leftWide%) do set leftBar= !leftBar!
set sepBar=
for /L %%w in (1,1,%sepWide%) do set sepBar= !sepBar!

rem Draw the Bar Graph
for /L %%v in (%1,-1,1) do (
   set /P =%leftBar%< NUL
   for /L %%j in (1,1,%numJ%) do (
      for /L %%i in (1,1,%numI%) do (
         if !V%%i.%%j! geq %%v (
            for /L %%w in (1,1,%barWide%) do set /P =!C%%i!< NUL
         ) else (
            for /L %%w in (1,1,%barWide%) do set /P = < NUL
         )
      )
      set /P =%sepBar%< NUL
   )
   echo/
)

rem Show value names
echo/
set nameSep=
for /L %%n in (1,1,%nameWide%) do set nameSep= !nameSep!
set /P =%leftBar%< NUL
set i=0
for %%n in (!%4!) do (
   set /A i+=1
   set name=%%~n%nameSep%
   for %%i in (!i!) do set /P =!name:~0,%nameWide%!< NUL
)
echo/
exit /B
Note: the characters in this command: for %%c in (█ ░ ▓ ▄ ▒) do ( are ASCII 219, 220, 176, 177 and 178 that are shown as block characters in the standard Code Page 850.
Results:

Code: Select all


      T H I S   I S   T H E   T I T L E   O F   T H E   B A R   G R A P H

      █ GROWING     ░ DOWN TO UP  ▓ SHRINKING   ▄ UP TO DOWN  ▒ FLAT


                                                                       ░
                                                                       ░
                                                                       ░
     ░▓                              ▄                           ░     ░
     ░▓     ▓                        ▄                           ░     ░
     ░▓     ▓                        ▄                           ░     ░
     ░▓    ░▓     ▓            ▄     ▄     ▄               ░     ░     ░
     ░▓    ░▓     ▓     ▓      ▄     ▄     ▄               ░     ░    █░
     ░▓    ░▓    ░▓     ▓▄    ▓▄     ▄     ▄     ▄   ░     ░    █░    █░
     ░▓    ░▓    ░▓     ▓▄    ▓▄     ▄     ▄     ▄   ░     ░    █░    █░
     ░▓    ░▓    ░▓     ▓▄    ▓▄    ▓▄     ▄     ▄   ░    █░    █░    █░
     ░▓    ░▓    ░▓▄   ░▓▄    ▓▄    ▓▄    ▓▄   ░ ▄  █░ ▄  █░    █░    █░
     ░▓    ░▓    ░▓▄   ░▓▄    ▓▄    ▓▄    ▓▄  █░▓▄  █░ ▄  █░    █░    █░
     ░▓    ░▓    ░▓▄   ░▓▄    ▓▄    ▓▄    ▓▄  █░▓▄  █░ ▄  █░    █░    █░
     ░▓    ░▓▄   ░▓▄   ░▓▄   ░▓▄    ▓▄  █░▓▄  █░▓▄  █░▓▄  █░ ▄  █░    █░
     ░▓    ░▓▄   ░▓▄   ░▓▄   ░▓▄  █ ▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░    █░
     ░▓▄   ░▓▄   ░▓▄   ░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░
     ░▓▄   ░▓▄   ░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓
     ░▓▄   ░▓▄   ░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓
     ░▓▄   ░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄
     ░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄  █░▓▄
    █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒
    █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒
    █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒
    █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒
    █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒
    █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒
    █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒
    █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒
    █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒
    █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒
    █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒
    █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒
    █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒ █░▓▄▒

    Jan   Feb   Mar   Apr   May   Jun   Jul   Aug   Sep   Oct   Nov   Dec

Last edited by Aacini on 02 May 2012 18:39, edited 1 time in total.

Aacini
Expert
Posts: 1885
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Drawing rudimentary graphics in text mode

#2 Post by Aacini » 03 Jan 2012 23:33

2- We pass now to a more technical matter. The following program use extensive Fixed Point arithmetic operations to graphic a complex algebraic equation: the projection of a 3D-surface on the X-Y plane.

Code: Select all

@echo off
::Floating-point graphics in text mode via integer operations
::Antonio Perez Ayala - Jan/03/2012

setlocal EnableDelayedExpansion

REM Working values: maximum screen coordinates
set /A maxX=67, maxY=40, one=100

call :IntAsFP   xLeft=-2.01
call :IntAsFP    yTop= 2.00
call :IntAsFP  xRight= 2.01
call :IntAsFP yBottom=-2.00
set /A xStep=(xRight-xLeft)/maxX, yStep=(yBottom-yTop)/maxY

cls
echo Graphic of the projection of 3D-surface F(X,Y) = (X^^2+Y^^2)^^5 - ((X^^2-Y^^2)8XY)^^2
echo on Z=0 plane, from (-2.01,2.00) to (2.01,-2.00) coordinates.
set /A Y=yTop-yStep
for /L %%y in (1,1,%maxY%) do (
   set /A Y+=yStep, X=xLeft-xStep
   for /L %%x in (1,1,%maxX%) do (
      set /A X+=xStep,xSqr=X*X/one, ySqr=Y*Y/one, firstTerm=firstTerm1=xSqr+ySqr, secondTerm=(xSqr-ySqr^)*X/one*Y/one*8, secondTerm=secondTerm*secondTerm/one
      for /L %%p in (1,1,4) do set /A firstTerm=firstTerm*firstTerm1/one
      set /A Z=firstTerm-secondTerm
      if !Z! lss 0 (
          set /P =*< NUL
      ) else (
          set /P = < NUL
      )
   )
   echo/
)
pause

cls
echo Graphic of the perimeter of previous projection.
echo The result is equivalent to equation R=2*SIN(4*THETA) in polar coordinates.
set /A Y=yTop-yStep
for /L %%y in (1,1,%maxY%) do (
   set /A Y+=yStep, X=xLeft-xStep, lastZ=1
   for /L %%x in (1,1,%maxX%) do (
      set /A X+=xStep,xSqr=X*X/one, ySqr=Y*Y/one, firstTerm=firstTerm1=xSqr+ySqr, secondTerm=(xSqr-ySqr^)*X/one*Y/one*8, secondTerm=secondTerm*secondTerm/one
      for /L %%p in (1,1,4) do set /A firstTerm=firstTerm*firstTerm1/one
      set /A Z=firstTerm-secondTerm
      if !Z! lss 0 (set Z=-1) else set Z=1
      set /A lastZ*=Z
      if !lastZ! lss 0 (
          set /P =*< NUL
      ) else (
          set /P = < NUL
      )
      set lastZ=!Z!
   )
   echo/
)
pause
goto :EOF


:IntAsFP Int=FP
set FP=%2
set %1=!FP:.=!
exit /B
Results:

Code: Select all

Graphic of the projection of 3D-surface F(X,Y) = (X^2+Y^2)^5 - ((X^2-Y^2)8XY)^2
on Z=0 plane, from (-2.01,2.00) to (2.01,-2.00) coordinates.


                    ****                    ****
                   *******                *******
                   ********              ********
                   *********            *********
                    *********          *********
                    **********        **********
                     **********      **********
                      *********      *********
                      **********    **********
                       *********    *********
   ***********          ********    ********          ***********
   ***************       *******    *******       ***************
    *****************     ******    ******     *****************
     ******************     ***      ***     ******************
       *******************                *******************
          ****************                ****************
              ************                ************
                    ****                    ****

                    ****                    ****
              ************                ************
          ****************                ****************
       *******************                *******************
     ******************     ***      ***     ******************
    *****************     ******    ******     *****************
   ***************       *******    *******       ***************
   ***********          ********    ********          ***********
                       *********    *********
                      **********    **********
                      *********      *********
                     **********      **********
                    **********        **********
                    *********          *********
                   *********            *********
                   ********              ********
                   *******                *******
                    ****                    ****

Press any key to continue . . .

Graphic of the perimeter of previous projection.
The result is equivalent to equation R=2*SIN(4*THETA) in polar coordinates.


                    *   *                   *   *
                   *      *               *      *
                   *       *             *       *
                   *        *           *        *
                    *        *         *        *
                    *         *       *         *
                     *         *     *         *
                      *        *     *        *
                      *         *   *         *
                       *        *   *        *
   *          *         *       *   *       *         *          *
   *              *      *      *   *      *      *              *
    *                *    *     *   *     *    *                *
     *                 *    *  *     *  *    *                 *
       *                  *               *                  *
          *               *               *               *
              *           *               *           *
                    *   *                   *   *

                    *   *                   *   *
              *           *               *           *
          *               *               *               *
       *                  *               *                  *
     *                 *    *  *     *  *    *                 *
    *                *    *     *   *     *    *                *
   *              *      *      *   *      *      *              *
   *          *         *       *   *       *         *          *
                       *        *   *        *
                      *         *   *         *
                      *        *     *        *
                     *         *     *         *
                    *         *       *         *
                    *        *         *        *
                   *        *           *        *
                   *       *             *       *
                   *      *               *      *
                    *   *                   *   *

Press any key to continue . . .

Aacini
Expert
Posts: 1885
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Drawing rudimentary graphics in text mode

#3 Post by Aacini » 03 Jan 2012 23:34

3- Had you seen fractal graphics? The Mandelbrot Set is drawn on a complex plane of Z=X+iY coordinates. At each (X0,Y0) point, Zn+1=Zn^2-Z0 (Xn+1=Xn^2-Yn^2-X0)+i(Yn+1=2*Xn*Yn-Y0) is iterated until |Z|=SQRT(X^2+Y^2) is greater than 2; the number of iterations gives the color of that point. If |Z| don't exceed 2 after a certain limit of iterations, point color remains black. Easy, isn't it? The Mandelbrot Set fractal graphic is customarily drawn between (-1.00,1.25) and (2.00,-1.25) coordinates; the version below show different letters instead of colors.

Code: Select all

@echo off
::Mandelbrot Set graphic in text mode
::Antonio Perez Ayala - Jan/03/2012

setlocal EnableDelayedExpansion

REM Working values: maximum screen coordinates and iteration level
set /A maxX=78, maxY=42, maxLevel=26, one=10000

call :IntAsFP   xLeft=-1.0000
call :IntAsFP    yTop= 1.1250
call :IntAsFP  xRight= 2.0000
call :IntAsFP yBottom=-1.1250
set /A xStep=(xRight-xLeft)/maxX, yStep=(yBottom-yTop)/maxY, four=4*one
set showChars=A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
set "showChar[0]= "
set i=0
for %%c in (%showChars%) do (
    set /A i+=1
    set showChar[!i!]=%%c
)

cls
set /A yPos=yTop-yStep
for /L %%y in (0,1,%maxY%) do (
   set /A yPos+=yStep, xPos=xLeft-xStep
   for /L %%x in (0,1,%maxX%) do (
      set /A xPos+=xStep, xIter=xPos, yIter=yPos, xSquare=xIter*xIter/one, ySquare=yIter*yIter/one, root=xSquare+ySquare
      set level=0
      for /L %%i in (1,1,%maxLevel%) do (
         if !level! == 0 (
            if !root! lss %four% (
               set /A yIter=2*xIter*yIter/one-yPos, xIter=xSquare-ySquare-xPos, xSquare=xIter*xIter/one, ySquare=yIter*yIter/one, root=xSquare+ySquare
            ) else (
               set level=%%i
            )
         rem noelse
         )
      )
      for %%l in (!level!) do set /P =!showChar[%%l]!< NUL
      )
   )
   echo/
)
goto :EOF


:IntAsFP Int=FP
set FP=%2
set %1=!FP:.=!
exit /B
Result:

Code: Select all

BBBBBBBBBBBBBBBBBBBCCCCCDDDDEEEFEDDDDDCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBBAAAAAAAAA
BBBBBBBBBBBBBBBBCCCCCCDDDDDEFFHIFEEDDDDDGCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBAAAAAAAA
BBBBBBBBBBBBBBCCCCCCDDDDDEGHGINIFEEEDDDDDDDDCCCCCCCCCCCCCCCCCCCFEBBBBBBAAAAAAAA
BBBBBBBBBBBBBCCCCCDDDDDDEFGISSJHGFEEEDDDDDDDDDCCCCCCCCCCCCCCCCCCEDEBBBBBAAAAAAA
BBBBBBBBBBBCCCCCCDDDDDDEEFGIMYSIHGFEEEDDDDDDDDDCCCCCCCCCCCCCCCCCCDEFBBBBBAAAAAA
BBBBBBBBBBCCCCCCDDDDDEEEFHMK  UQXNHFEEEEDDDDDDDDDCCCCCCCCCCCCCCCCCDFDEBBBBAAAAA
BBBBBBBBCCCCCCCDDDDEEEEFGIR      KHGFFFEEEDDDDDDDDDCCCCCCCCCCCCCCCCCDEGBBBAAAAA
BBBBBBBCCCCCCCDDDEEEEFFGGI        HHGGFFFFEEDDDDDDDDCCCCCCCCCCCCCCCCCCCDBBBAAAA
BBBBBBCCCCCCCDDEFJGFFGHIIJM      LJIIHHHJHHFEEDDDDDDDDCCCCCCCCCCCCCCCCCCCBBAAAA
BBBBBCCCCCCCCDEFH IHHI UQ           ZKKMRUJGFEEEEEDDDDDDCCCCCCCCCCCCCCCCCCBBAAA
BBBBCCCCCCCCDDEGMVQ MR                Y  OJGFFFEEEEEEDDDDDCCCCCCCCCCCCCCCCCBAAA
BBBBCCCCCCCCDEEFIO                       NJHGFFFEEEEEEEEEDDDCCCCCCCCCCCCCCCBBAA
BBBCCCCCCCCDDEEFHK                        MXKGFFFFEEEEEEEEEDDDCCCCCCCCCCCCCCBAA
BBBCCCCCCCCDDEFGH                           MIGGGFFFFFFFFFFHGEDDDDCCCCCCCCCCCAA
BBCCCCCCCCDDDEILT                           WJHHGGGGHKHGGHHLFFEEDDDDDDCCCCCCCBA
BBCCCCCCCCDDDFHN                             LJIIISJORJJVNNKGFEEEEDDDDDDDCCCCBA
BCCCCCCCCDDDDEGI                             QKKKN X UVY OKIGGFEEEEDDDDDDDECCCA
BCCCCCCCCDDDDEG                               NN         RLJGGGEEEEEEDDDDDDFFCA
BCCCCCCCCDDDDEFHU                             R            MJPHIFEEEEEDDDDDDDCA
BCCCCCCCCDDDDEFGS                                          PMLMJHGFFFFEDDDDDDDB
BCCCCCCCCDDDDEEFGM                                            QLIHGGFFGGJHFHEED
BCCCCCCCCDDDDEEFGHKT                                             URROONM MJKJJG
BCCCCCCCCDDDDEEFGL                                            ROJHHIGFGGJHFHEED
BCCCCCCCCDDDDEEGT                                          PMLNJHGFFFFFEDDDDDDC
BCCCCCCCCDDDDEFH                              S            MJIHJFEEEEEDDDDDDDDA
BCCCCCCCCDDDDEG                               NN         QLJGGGEEEEEEDDDDDDDECA
BCCCCCCCCDDDDEGI                             PKKKQ   VU  PKIGGFEEEEHDDDDDDJCCCA
BBCCCCCCCCDDDFHN                            WLJIII KPPKJ OPKGFEEEEDDDDDDDCCCCCA
BBCCCCCCCCDDDEIMU                            KHHGGGHHLHGGHIKFFEEDDDDDDCCCCCCCBA
BBBCCCCCCCCDDEFHI                           LIHGGFFFFFFFFFFHGEDDDDCCCCCCCCCCCAA
BBBCCCCCCCCDDEFFHJ                        M LGFFFFEEEEEEEEEEDDCCCCCCCCCCCCCCBAA
BBBBCCCCCCCCDEEFIO                       NJHGFFFEEEEEEEEEDDDCCCCCCCCCCCCCCCBBAA
BBBBCCCCCCCCDDEGM R NS                X  OJGFFFEEEEEEDDDDDCCCCCCCCCCCCCCCCCBAAA
BBBBBCCCCCCCCDEFHPIHHI WQ           XLK RUJGFEEEEEDDDDDDCCCCCCCCCCCCCCCCCCBBAAA
BBBBBBCCCCCCCDDEFIGFFGHIIJM      LJIIHHIKHIFEEEDDDDDDDCCCCCCCCCCCCCCCCCCCBBAAAA
BBBBBBBCCCCCCCDDDEEEFFFGGI       RIHGGFFFFEEDDDDDDDDCCCCCCCCCCCCCCCCCCCCBBBAAAA
BBBBBBBBCCCCCCCDDDDEEEEFGIQ      KHGFFFEEEDDDDDDDDDCCCCCCCCCCCCCCCCCIEIBBBAAAAA
BBBBBBBBBBCCCCCCDDDDDEEEFHRKU U URHFEEEEDDDDDDDDDCCCCCCCCCCCCCCCCCDEFGBBBBAAAAA
BBBBBBBBBBBCCCCCCDDDDDDEEFGIMV IHGFEEEDDDDDDDDDECCCCCCCCCCCCCCCCCEFHBBBBBAAAAAA
BBBBBBBBBBBBBCCCCCDDDDDDEFGIOQJHGFEEEDDDDDDDDDCCCCCCCCCCCCCCCCCCEDEBBBBBAAAAAAA
BBBBBBBBBBBBBBCCCCCCDDDDDEGJHIMHFEEEDDDDDDDDCCCCCCCCCCCCCCCCCCCDGBBBBBBAAAAAAAA
BBBBBBBBBBBBBBBBCCCCCCDDDDEEFFIIFEEDDDDDECCCCCCCCCCCCCCCCCCCCCCBBBBBBBBAAAAAAAA
BBBBBBBBBBBBBBBBBBBCCCCCDDDDEEEFFDDDDDDCCCCCCCCCCCCCCCCCCCCCCBBBBBBBBBAAAAAAAAA

jeb
Expert
Posts: 1041
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: Drawing rudimentary graphics in text mode

#4 Post by jeb » 05 Jan 2012 09:31

Hi Aacini,

very impressive :D :!:

But works only with XP, as Vista and Win7 have a feature in the SET/p output.
Trailing whitespaces will be removed.

I changed the Mandelbrot to real colors, looks really fine now.

Code: Select all

@echo off
@echo off
SETLOCAL EnableDelayedExpansion
for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
  set "DEL=%%a"
)

::Mandelbrot Set graphic in text mode
::Antonio Perez Ayala - Jan/03/2012

setlocal EnableDelayedExpansion

REM Working values: maximum screen coordinates and iteration level
set /A maxX=78, maxY=42, maxLevel=26, one=10000

call :IntAsFP   xLeft=-1.0000
call :IntAsFP    yTop= 1.1250
call :IntAsFP  xRight= 2.0000
call :IntAsFP yBottom=-1.1250
set /A xStep=(xRight-xLeft)/maxX, yStep=(yBottom-yTop)/maxY, four=4*one
set showChars=A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
set "showChar[0]=."
set "Xcolor=01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21"
set i=0
for %%c in (%showChars%) do (
    set /A i+=1
    set showChar[!i!]=%%c
)

cls
set /A yPos=yTop-yStep
for /L %%y in (0,1,%maxY%) do (
   set /A yPos+=yStep, xPos=xLeft-xStep
   for /L %%x in (0,1,%maxX%) do (
      set /A xPos+=xStep, xIter=xPos, yIter=yPos, xSquare=xIter*xIter/one, ySquare=yIter*yIter/one, root=xSquare+ySquare
      set level=0
      for /L %%i in (1,1,%maxLevel%) do (
         if !level! == 0 (
            if !root! lss %four% (
               set /A yIter=2*xIter*yIter/one-yPos, xIter=xSquare-ySquare-xPos, xSquare=xIter*xIter/one, ySquare=yIter*yIter/one, root=xSquare+ySquare
            ) else (
               set level=%%i
            )
         rem noelse
         )
      )
      rem for %%l in (!level!) do set /P =!showChar[%%l]!< NUL
     set /a col=level*3
     call :ColorText !col! "#"
   )
   echo(
)
goto :EOF


:IntAsFP Int=FP
set FP=%2
set %1=!FP:.=!
exit /B


:ColorText
echo off
set color=!Xcolor:~%1,2!
<nul set /p ".=%DEL%" > "%~2"
findstr /v /a:%color% /R "^$" "%~2" nul
del "%~2" > nul 2>&1
goto :eof


jeb

Aacini
Expert
Posts: 1885
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Drawing rudimentary graphics in text mode

#5 Post by Aacini » 05 Jan 2012 23:30

Jeb: that is awesome! :D :)

Mandelbrot Set color bands in the "sea" becomes narrow as we approach to the "land" (the black area). To compensate for this effect, several bands must be joined in the same color as the iteration level increases.

I wrote a very small and fast program to show text in color I called COLORMSG to differentiate it from your COLORTEXT. It is a .COM file with just 181 bytes in size, so it run much faster than other methods that do the same thing. Here it is:

³2ÿŠOÿ2íã9‹û° üó®tQã~ŠEÿ³$þÇS³­ÿãën€= tsÐàÐàÐàÐàŠàGŠEÿ³<Sëq³A€/!+ÄIãN2äP¸""ò®uDãB‹÷‹Ñò®u@J:%u;GIuó+Ñt-‹Ê³|€/!³†€/![° ´*€ì!Í1²"¬´/€ì!Í1:Âu—Šâ:$u‘Fâë2À´LÍ!ëÇë¦,0Ã<Arù²ùöÚ*Âëñ<arð, ëì

Just take the previous 181 bytes and store they in a file called COLORMSG.COM; you may first create COLORMSG.TXT and then do a REN COLORMSG.TXT COLORMSG.COM. Note that file contents must be comprised of a long string 181 bytes size with no line breaks, but that have white spaces in positions 15, 39, 118 and 179. The color graphic is drawn even faster if the DOS-Window is maximized with Alt-Enter key.

This is my version of Mandelbrot Set in color:

Code: Select all

@echo off
::Mandelbrot Set graphic in text mode in COLOR
::Antonio Perez Ayala

setlocal EnableDelayedExpansion

REM Working values: maximum screen coordinates and iteration level
set /A maxX=78, maxY=42, maxLevel=26, one=10000

call :IntAsFP   xLeft=-1.0000
call :IntAsFP    yTop= 1.1250
call :IntAsFP  xRight= 2.0000
call :IntAsFP yBottom=-1.1250
set /A xStep=(xRight-xLeft)/maxX, yStep=(yBottom-yTop)/maxY, four=4*one
set  showChars=█ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ █ ▓ ▓ ▒ ▒ ▒ ░ ░ ░ ░
set showColors=1 2 3 4 5 6 7 8 9 A B C C D D D D E E E E E E E E E
set "showChar[0]= "
set i=0
for %%c in (%showChars%) do (
    set /A i+=1
    set showChar[!i!]=%%c
)
set showColor[0]=0
set i=0
for %%c in (%showColors%) do (
    set /A i+=1
    set showColor[!i!]=%%c
)

cls
set /A yPos=yTop-yStep
for /L %%y in (0,1,%maxY%) do (
   set /A yPos+=yStep, xPos=xLeft-xStep
   for /L %%x in (0,1,%maxX%) do (
      set /A xPos+=xStep, xIter=xPos, yIter=yPos, xSquare=xIter*xIter/one, ySquare=yIter*yIter/one, root=xSquare+ySquare
      set level=0
      for /L %%i in (1,1,%maxLevel%) do (
         if !level! == 0 (
            if !root! lss %four% (
               set /A yIter=2*xIter*yIter/one-yPos, xIter=xSquare-ySquare-xPos, xSquare=xIter*xIter/one, ySquare=yIter*yIter/one, root=xSquare+ySquare
            ) else (
               set level=%%i
            )
         rem noelse
         )
      )
      for %%l in (!level!) do ColorMsg !showColor[%%l]! "!showChar[%%l]!"
   )
   echo/
)
goto :EOF


:IntAsFP Int=FP
set FP=%2
set %1=!FP:.=!
exit /B

You may review the result generated here; that image took 1 minute 42 seconds with the DOS window maximized via Alt-Enter.

Antonio
Last edited by Aacini on 02 May 2012 18:34, edited 1 time in total.

Squashman
Expert
Posts: 4465
Joined: 23 Dec 2011 13:59

Re: Drawing rudimentary graphics in text mode

#6 Post by Squashman » 06 Jan 2012 10:31

This is some cool stuff. Didn't realize you could change the color like that. I always assumed it was an all or nothing.

Aacini
Expert
Posts: 1885
Joined: 06 Dec 2011 22:15
Location: México City, México
Contact:

Re: Drawing rudimentary graphics in text mode

#7 Post by Aacini » 06 Jan 2012 20:27

I just realized that the definition of ColorMsg.com auxiliary program may be included in the Batch file. At beginning of the Batch file include this line:

Code: Select all

if not exist ColorMsg.com call :DefineColorMsg
And at the end:

Code: Select all

:DefineColorMsg
setlocal DisableDelayedExpansion
set ColorMsg=³2ÿŠOÿ2íã9‹û° üó®tQã~ŠEÿ³$þÇS³­ÿãën€= tsÐàÐàÐàÐàŠàGŠEÿ³^<Sëq³A€/!+ÄIãN2äP¸""ò®uDãB‹÷‹Ñò®u^@J:%%u;GIuó+Ñt-‹Ê³^|€/!³†€/![° ´*€ì!Í1²"¬´/€ì!Í1:Âu—Šâ:$u‘Fâë2À´LÍ!ëÇë¦,0Ã<Arù²ùöÚ*Âëñ<arð, ëì
setlocal EnableDelayedExpansion
echo !ColorMsg!> ColorMsg.com
exit /B

This way, the Batch file may be distributed with no additional instructions on create the auxiliary programs. Interesting, isn't it? :wink:

A VERY INTERESTING IDEA that crossed my mind is that ColorMsg variable above contains executable code in .COM file image format; that means, it represent a MACHINE LANGUAGE MACRO :!: :shock: I am looking for a method to execute it!!!!!!!!!!

dbenham
Expert
Posts: 2461
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: Drawing rudimentary graphics in text mode

#8 Post by dbenham » 07 Jan 2012 08:28

There are pitfalls when posting code containing non-ASCII characters (code > 128) on this site. I ran into this when I tried to post a solution for a "Universal" date parser.

Dave Benham

aGerman
Expert
Posts: 4654
Joined: 22 Jan 2010 18:01
Location: Germany

Re: Drawing rudimentary graphics in text mode

#9 Post by aGerman » 07 Jan 2012 09:55

I was able to copy the right characters from Aacinis code. But I should mention that the days of com files are numbered. They are 16 Bit applications and won't work on 64 Bit Systems.

Regards
aGerman

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Drawing rudimentary graphics in text mode

#10 Post by Ed Dyreen » 11 Apr 2012 00:53

'
Too bad, with me on XP $bs translates to a dot, not sure why, tried several codepages...

Code: Select all

@echo off &setlocal enableDelayedExpansion

for /f "delims=#" %%? in (

   '"prompt #$H# &echo on &for %%? in (1) do rem"'

) do    set "$BS=%%?"

echo.failed%$BS%%$BS%%$BS%%$BS%%$BS%%$BS%$bs

call :ColorText 0C "#"
call :ColorText 0B "#"

pause
exit /b 0

:ColorText
:: (
   > "%~2" (echo.h%$BS%%$BS%h)

   findstr /v /a:%~1 /R "^$" "%~2" nul
:: )
exit /b 0

Code: Select all

$bs
#:h. .. .h
#:h. .. .h
Druk op een toets om door te gaan. . .

tonysathre
Posts: 14
Joined: 20 Mar 2012 10:07

Re: Drawing rudimentary graphics in text mode

#11 Post by tonysathre » 11 Apr 2012 14:00

Wow this is really cool stuff. Writing out color with findstr is nice a trick.

Tony

foxidrive
Expert
Posts: 6031
Joined: 10 Feb 2012 02:20

Re: Drawing rudimentary graphics in text mode

#12 Post by foxidrive » 11 Apr 2012 14:49

jeb wrote:Hi Aacini,

very impressive :D :!:

But works only with XP, as Vista and Win7 have a feature in the SET/p output.
Trailing whitespaces will be removed.

I changed the Mandelbrot to real colors, looks really fine now.


This is nice work from you guys.

jeb, when I run yours the screen width seems to be around 500 characters wide. What am I doing wrong? Running XP Pro here.

I mean my console window is 80 x 35 or so but what displays looks nothing like a mandlebrot.

I added this and it still seems odd.
mode con: cols=120 lines=80

Liviu
Expert
Posts: 470
Joined: 13 Jan 2012 21:24

Re: Drawing rudimentary graphics in text mode

#13 Post by Liviu » 11 Apr 2012 20:26

jeb wrote:I changed the Mandelbrot to real colors, looks really fine now.

Neat! Thanks for sharing.

Wasn't aware of (or paying attention to) findstr's /A option. Note to myself: get into the habit of browsing to http://www.dostips.com/DosCommandIndex.php more often, and search for uncommon words such as "color" ;-)

foxidrive wrote:jeb, when I run yours the screen width seems to be around 500 characters wide. What am I doing wrong? Running XP Pro here.

Try pre-setting the console at the smallest allowed Lucida Console font, and a screen width of 400+.

Liviu

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: Drawing rudimentary graphics in text mode

#14 Post by Ed Dyreen » 12 Apr 2012 13:58

'
I'm pleased y'all got it working, still have no idea why the $bs doen't work with me in jeb's solution, I don't like to use Aacini's .COM file, cause it won't stand in time without having to be rewritten. But don't let it stop you from writing witchCraft Aacini, I like the ability to choose :D

jeb
Expert
Posts: 1041
Joined: 30 Aug 2007 08:05
Location: Germany, Bochum

Re: Drawing rudimentary graphics in text mode

#15 Post by jeb » 12 Apr 2012 17:50

@Ed and @foxidrive and all other XP-users

Yes it fails, as XP seems to use a different findstr.
The findstr does not print the backspace character instead it replace it with a dot.

I made a special "hotfix" for XP-only, I echo the backspace 4 times to remove the ":. ." characters.

Code: Select all

@echo off
::Mandelbrot Set graphic in text mode
::Antonio Perez Ayala - Jan/03/2012

SETLOCAL EnableDelayedExpansion
set "DisplayChar=#"

for /F "tokens=1,2 delims=#" %%a in ('"prompt #$H#$E# & echo on & for %%b in (1) do rem"') do (
  set "DEL=%%a"
)
<nul set /p ".=%DEL%" > "DisplayChar"

setlocal EnableDelayedExpansion
REM Working values: maximum screen coordinates and iteration level
set /A maxX=78, maxY=42, maxLevel=26, one=10000

call :IntAsFP   xLeft=-1.0000
call :IntAsFP    yTop= 1.1250
call :IntAsFP  xRight= 2.0000
call :IntAsFP yBottom=-1.1250
set /A xStep=(xRight-xLeft)/maxX, yStep=(yBottom-yTop)/maxY, four=4*one
set showChars=A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
set "showChar[0]=."
set "Xcolor=01 02 03 04 05 06 07 08 09 0a 0b 0c 0d 0e 0f 10 12 13 14 15 16 17 18 19 1a 1b 1c 1d 1e 1f 20 21"
set i=0
for %%c in (%showChars%) do (
    set /A i+=1
    set showChar[!i!]=%%c
)

cls
set /A yPos=yTop-yStep
for /L %%y in (0,1,%maxY%) do (
   set /A yPos+=yStep, xPos=xLeft-xStep
   for /L %%x in (0,1,%maxX%) do (
      set /A xPos+=xStep, xIter=xPos, yIter=yPos, xSquare=xIter*xIter/one, ySquare=yIter*yIter/one, root=xSquare+ySquare
      set level=0
      for /L %%i in (1,1,%maxLevel%) do (
         if !level! == 0 (
            if !root! lss %four% (
               set /A yIter=2*xIter*yIter/one-yPos, xIter=xSquare-ySquare-xPos, xSquare=xIter*xIter/one, ySquare=yIter*yIter/one, root=xSquare+ySquare
            ) else (
               set level=%%i
            )
         rem noelse
         )
      )
      rem for %%l in (!level!) do set /P =!showChar[%%l]!< NUL
     set /a col=level*3
     call :ColorText !col! !DisplayChar!
   )
   echo(
)
goto :EOF


:IntAsFP Int=FP
set FP=%2
set %1=!FP:.=!
exit /B


:ColorText
echo off
set "color=!Xcolor:~%1,2!"
findstr /v /a:%color% /R "^$" "%~2" nul
type #
type #
type #
type #
goto :eof


One of my next goals is to use multiple threads for the mandelbrot.
So on a Core-I7 it could be 8 times faster.

jeb

Post Reply