Onscreen protractor / anglefinder

For discussions about programming, and for programming questions and advice


Moderator: Forum moderators

User avatar
MochiMoppel
Posts: 1240
Joined: Mon Jun 15, 2020 6:25 am
Location: Japan
Has thanked: 21 times
Been thanked: 440 times

Re: Onscreen protractor / anglefinder

Post by MochiMoppel »

@greengeek :thumbup:
This thing is getting sophisticated :D

Some debug comments at the end should be commented out or removed to avoid bash errors.

I think you can simplify some computations.
ACTUALDEGREE1=$(bc <<< "scale=2;$RAWRESULT1+180")
is the same as the faster
ACTUALDEGREE1=$((RAWRESULT1+180))
since you earlier converted RAWRESULT1 to integer

MODINTERNALANGLE=`sed "s/-//g"<<<$INTERNALANGLE`
can be handled faster by bash:
MODINTERNALANGLE=${INTERNALANGLE/-}

In some cases I get unexpected results. for example in case of your screenshot (Concave_Lens.jpg). When I start with the lower line (clicking 3 and 4) and then click 1 and 2 the result is about 333 degrees, i.e. the external angle.

User avatar
greengeek
Posts: 1384
Joined: Thu Jul 16, 2020 11:06 pm
Has thanked: 535 times
Been thanked: 192 times

Re: Onscreen protractor / anglefinder

Post by greengeek »

MochiMoppel wrote: Sun Dec 27, 2020 1:59 pm

In some cases I get unexpected results. for example in case of your screenshot (Concave_Lens.jpg). When I start with the lower line (clicking 3 and 4) and then click 1 and 2 the result is about 333 degrees, i.e. the external angle.

Many thanks for testing. Confirmed. Looks like i forgot to handle a negative number. Fixed now on version 0.2

Some debug comments at the end should be commented out or removed to avoid bash errors.

Ooops. I meant to comment out the whole debug data. Sorted now. cheers.

I think you can simplify some computations.
ACTUALDEGREE1=$(bc <<< "scale=2;$RAWRESULT1+180")
is the same as the faster
ACTUALDEGREE1=$((RAWRESULT1+180))
since you earlier converted RAWRESULT1 to integer

MODINTERNALANGLE=`sed "s/-//g"<<<$INTERNALANGLE`
can be handled faster by bash:
MODINTERNALANGLE=${INTERNALANGLE/-}

Great tips. I will incorporate those once i am happy that the bug you spotted is reliably fixed.
Thanks!

User avatar
rockedge
Site Admin
Posts: 6558
Joined: Mon Dec 02, 2019 1:38 am
Location: Connecticut,U.S.A.
Has thanked: 2761 times
Been thanked: 2640 times
Contact:

Re: Onscreen protractor / anglefinder

Post by rockedge »

cool stuff! absolutely a useful tool.
Well Done is what I say, to all of those involved.

Probably should become a built-in standard tool in Puppy Linux.

User avatar
puppy_apprentice
Posts: 692
Joined: Tue Oct 06, 2020 8:43 pm
Location: land of bigos and schabowy ;)
Has thanked: 5 times
Been thanked: 115 times

Re: Onscreen protractor / anglefinder

Post by puppy_apprentice »

It could be general purpose measure tool:

1) distance between two points
2) length of the square/rectangle sides
3) surface area of the square/rectangle
4) diameter and surface area of circle
5) point coordinates

with data export to CSV for use in eg. Gnumeric.

User avatar
MochiMoppel
Posts: 1240
Joined: Mon Jun 15, 2020 6:25 am
Location: Japan
Has thanked: 21 times
Been thanked: 440 times

Re: Onscreen protractor / anglefinder

Post by MochiMoppel »

@rockedge Thanks for the encouragement. I see it more as a mathematical challenge. Cost me some pulled out hairs.

@puppy_apprentice Distance between two points can only be measured in pixels and only for straight lines and for this tools already exist. I can't see how this tool can do more than it already does.

@greengeekYour new version seems to work fine - even when not clicking the narrow point first. The biggest problem with your/my code is the lack of precision. Rounding angles to integers is much too coarse, though of course it makes bash calculation easier.

In order to ensure that even a 1 pixel shift in coordinates results in a change of the angle value it requires a 2 digit floating point number. So eventually I decided to bite the bullet and calculated with floating point numbers. This results in very precise readings.

The second problem is the use of the mouse. Even with the cross cursor it's very hard to make precise clicks. For this reason and because now every pixel counts I implemented the option to enter the line coordinates into an entry box and let the script do the selection and the calculation. Much easier than using a mouse in a shaky hand. It's now also possible to edit the last used reference points and redo the selection/calculation with changed values. Just try the new script. I hope it's self explanatory.

Code: Select all

#!/bin/bash
trap "busybox pkill CLICKPOINT$$" EXIT
function  mark_clickpoint { 
	echo '<window title="P'$1'" decorated="false" skip_taskbar_hint="true" margin="0" window_position="2">
	<text use-markup="true" tooltip-text="'$3'">
	<label>"<span font='\''bold 10'\'' bgcolor='\'${2:-red}\'' color='\''white'\''>' $1 '</span>"
	</label></text></window>' |  exec -a CLICKPOINT$$ gtkdialog $4 -s 
}
function prepare_message {
	DG1=$(printf %6.2f $DEGREE1)
	DG2=$(printf %6.2f $DEGREE2)
	ANG=$(printf %9.2f $ANG)
	MSG=${1:-"Lines converge\n\nInner Angle:$ANG°"}
	MSG="$MSG\nVertex:    x=$vx y=$vy\nAngle Line 1: $DG1°\nAngle Line 2: $DG2°"
}
SAVD=$(</tmp/mm_anglefinder.tmp)
FLD1=${SAVD%%/*}
FLD1=$((FLD1>0&&FLD1<3?FLD1:1))
FLD2=$(</tmp/mm_anglefinder_FLD2)
FLD3=$(</tmp/mm_anglefinder_FLD3)
FLD4=$([[ $SAVD = *$'\n'checked ]] && echo on || echo off)
XDLG=$(Xdialog  --title="mm_anglefinder" --under --stdout --check "Use above reference points\n(uncheck to pick points with mouse) " "$FLD4" --left --help "After pushing 'OK' the mouse cursor will change to a ✛\nPick reference points on real or imaginary line(s) to measure their angles in degrees\n\nSingle Line mode requires 2 points\nTwo Line mode requires 4 points and will measure angle between 2 converging lines.\n\nPoints belonging to the same line may be selected in any order\n\nPicked points of previous run are read into entry boxes to allow manual changes.\nActivating checkbox allows automatic point selection based on values in entry boxes" -3input  "Measure angles on screen\nSee Help for more" x "Mode  (1=Single Line  2=Two Lines)" "$FLD1"  "\nx1 y1 x2 y2 (Points 1 and 2 of First Line)" "$FLD2" "\nx3 y3 x4 y4 (Points 3 and 4 of Second Line)" "$FLD3" )
(($?))&& exit || echo "$XDLG" > /tmp/mm_anglefinder.tmp
FLD1=${XDLG%%/*}
FLD2=${XDLG#*/}   FLD2=(${FLD2%%/*})
FLD3=${XDLG#*/*/} FLD3=(${FLD3%$'\n'*})
FLD4=${XDLG##*$'\n'}

LINE_MODE=$FLD1
USE_MOUSE=$([[ $FLD4 = unchecked ]] && echo 1 || echo 0)

((USE_MOUSE)) && read x1 y1 <<< $(xwininfo > /dev/null; getcurpos) || x1=${FLD2[0]} y1=${FLD2[1]} GEO1="-G +$((x1-7))+$((y1-8))"
mark_clickpoint 1 red "x=$x1 y=$y1" "$GEO1" &

((USE_MOUSE)) && read x2 y2 <<< $(xwininfo > /dev/null; getcurpos) || x2=${FLD2[2]} y2=${FLD2[3]} GEO2="-G +$((x2-7))+$((y2-8))"
mark_clickpoint 2 red "x=$x2 y=$y2" "$GEO2" &
echo "$x1 $y1 $x2 $y2" > /tmp/mm_anglefinder_FLD2

if ((x1==x2));then #avoid divide by zero error in SLOPE_1 calculation
	DEGREE1=90
	SLOPE_1=0
else
	SLOPE_1=$(bc -l <<< "($y1-$y2)/($x2-$x1)")
	DEGREE1=$(bc -l <<< "a($SLOPE_1)*180/3.14159")
fi

if ((LINE_MODE==1)) ;then
	[[ $DEGREE1 = -* ]] && ANG=$(bc<<<$DEGREE1+180) || ANG=$DEGREE1
	ANG=$(printf %.2f $ANG)
	CPL=$(bc<<<90-$ANG)
	[[ $CPL = -* ]] && CPL='—‎‎ '
	SUP=$(bc<<<180-$ANG)
	RFX=$(bc<<<360-$ANG)
	MSG="Angle:  $ANG°\n\nCompl. (90-A):  $CPL°\nSuppl. (180-A): $SUP°\nReflex (360-A): $RFX°"
fi

if ((LINE_MODE==2)) ;then
	((USE_MOUSE)) && read x3 y3 <<< $(xwininfo > /dev/null; getcurpos) || x3=${FLD3[0]} y3=${FLD3[1]} GEO3="-G +$((x3-7))+$((y3-8))"
	mark_clickpoint 3 blue "x=$x3 y=$y3" "$GEO3" &

	((USE_MOUSE)) && read x4 y4 <<< $(xwininfo > /dev/null; getcurpos) || x4=${FLD3[2]} y4=${FLD3[3]} GEO4="-G +$((x4-7))+$((y4-8))"
	mark_clickpoint 4 blue "x=$x4 y=$y4" "$GEO4" &
	echo "$x3 $y3 $x4 $y4" > /tmp/mm_anglefinder_FLD3

	if ((x3==x4));then #avoid divide by zero error in SLOPE_2 calculation
		DEGREE2=90
		SLOPE_2=0
	else
		SLOPE_2=$(bc -l <<< "($y3-$y4)/($x4-$x3)")
		DEGREE2=$(bc -l <<< "a($SLOPE_2)*180/3.14159")

	fi

	## VERTEX
	vx=$(bc -l <<< "((-($SLOPE_2))*$x4 -$y4 + $SLOPE_1*$x2 + $y2)/($SLOPE_1-($SLOPE_2))")
	vy=$(bc -l <<< "-($SLOPE_1*($vx-$x2)-$y2)")
	vx=$(printf %.0f $vx)
	vy=$(printf %.0f $vy)

	## LINES ARE PARALLEL
	if [[ $DEGREE1 = $DEGREE2 ]];then vx='‒' vy=$vx ; prepare_message "Lines are parallel\n"

	## LINES CROSS
	elif (( x1 < vx && x2 > vx || x1 > vx && x2 < vx ));then
		AN1=${DEGREE1/-}
		AN2=${DEGREE2/-}
		AN1=$(bc<<<$AN2+$AN1)
		AN2=$(bc<<<180-$AN1)
		AN1=$(printf %.2f $AN1)
		AN2=$(printf %.2f $AN2)
		prepare_message "Lines cross\n\nAngles at ╳: $AN1° and $AN2°"

	## BOTH POSITIVE OR BOTH NEGATIVE
	elif [[ $DEGREE1 != 0 && $DEGREE2 != 0 && $DEGREE1$DEGREE2 != *-* ]] || [[ $DEGREE1$DEGREE2 = -*-* ]];	then
		AN1=${DEGREE1/-}
		AN2=${DEGREE2/-}
		ANG=$(bc<<<$AN2-$AN1)
		ANG=${ANG/-}
		prepare_message

	## ONE OF THEM ZERO
	elif [[ $DEGREE1 = 0 || $DEGREE2 = 0 ]];then 
		[[ $DEGREE1 != 0 ]] && INNER=${DEGREE1/-} || INNER=${DEGREE2/-}
		OUTER=$(bc<<<180-$INNER)
		((x1>vx && x3>vx)) || ((x1<vx && x3<vx)) && ANG=$(printf %.2f $INNER) || ANG=$(printf %.2f $OUTER)
		prepare_message

	## ONE POSITIVE AND ONE NEGATIVE
	elif [[ $DEGREE1 = -* && $DEGREE2 != -* || $DEGREE2 = -* && $DEGREE1 != -* ]];then
		if ((y2>vy && y3>vy)) || ((y2<vy && y3<vy));then #vertical lines
			[[ $DEGREE1 = -* ]] && ANG=$(bc<<<$DEGREE1+180-$DEGREE2) || ANG=$(bc<<<$DEGREE2+180-$DEGREE1)
		else
			AN1=${DEGREE1/-}
			AN2=${DEGREE2/-}
			ANG=$(bc<<<$AN1+$AN2)
		fi
		prepare_message
	fi
fi
Xdialog -title 'mm_anglefinder' -left -o 'Try again' -y "$MSG" x
(($?)) || $0 & exit

[Edit] Changed "pkill" to "busybox pkill" since newer Puppy versions use the full version while older Puppies use the busybox version. Both versions are not fully compatible.

Attachments
mm_anglefinder.jpg
mm_anglefinder.jpg (100.91 KiB) Viewed 656 times
Last edited by MochiMoppel on Fri Jan 08, 2021 1:52 pm, edited 1 time in total.
User avatar
puppy_apprentice
Posts: 692
Joined: Tue Oct 06, 2020 8:43 pm
Location: land of bigos and schabowy ;)
Has thanked: 5 times
Been thanked: 115 times

Re: Onscreen protractor / anglefinder

Post by puppy_apprentice »

MochiMoppel wrote: Thu Jan 07, 2021 12:17 pm

Distance between two points can only be measured in pixels and only for straight lines and for this tools already exist. I can't see how this tool can do more than it already does.

96dpi/ppi (dots per inch/pixel per inch) so 100px = 100/96 ~ 1.04 inch or something like that

edited: you could make one big tool with menu ;)

How to clear those points from desktop. You should add clear button.

I have 20 points on desktop, could you make tool that will put points 1, 2, 3 ,4 etc. on the desktop and save their coordinates to text file?

User avatar
greengeek
Posts: 1384
Joined: Thu Jul 16, 2020 11:06 pm
Has thanked: 535 times
Been thanked: 192 times

Re: Onscreen protractor / anglefinder

Post by greengeek »

MochiMoppel wrote: Thu Jan 07, 2021 12:17 pm

Just try the new script. I hope it's self explanatory.

Very nice!

Just testing mouse method so far - what do you make of the following result?

OrderNotRespected.jpg
OrderNotRespected.jpg (21.69 KiB) Viewed 617 times

.
I would have expected this to yield a negative value for the angle (because it is downhill from click1 to click2)

168.80 is what i would expect if I had clicked the points in the opposite order.

User avatar
puppy_apprentice
Posts: 692
Joined: Tue Oct 06, 2020 8:43 pm
Location: land of bigos and schabowy ;)
Has thanked: 5 times
Been thanked: 115 times

Re: Onscreen protractor / anglefinder

Post by puppy_apprentice »

Base line goes through the lower point i think.

If you use option 2 you will have negative angles.

User avatar
greengeek
Posts: 1384
Joined: Thu Jul 16, 2020 11:06 pm
Has thanked: 535 times
Been thanked: 192 times

Re: Onscreen protractor / anglefinder

Post by greengeek »

puppy_apprentice wrote: Thu Jan 07, 2021 7:22 pm

Base line goes through the lower point i think.

Yes, i think I understand what you mean. But sometimes i may want to measure a single angle that is negative relative to an elevated "origin" or viewpoint.

I will try to illustrate two different circumstances:
.

VectorAboveHorizontal.png
VectorAboveHorizontal.png (318.65 KiB) Viewed 573 times

.

VectorBelowHorizontal.png
VectorBelowHorizontal.png (287.49 KiB) Viewed 573 times

.
In the first example the positive angle is meaningful - but in the second example a positive value is misleading if you think of the viewpoint of the crane operator.

User avatar
puppy_apprentice
Posts: 692
Joined: Tue Oct 06, 2020 8:43 pm
Location: land of bigos and schabowy ;)
Has thanked: 5 times
Been thanked: 115 times

Re: Onscreen protractor / anglefinder

Post by puppy_apprentice »

Look at this. Option 2 in MM tool. Red line 1-2 is a base and blue 3-4 is line for which you want know angle.

Or you can use some math.

Code: Select all

should be:
so beta = 90 - gamma = 90 - (alfa - 90) = 180 - alfa
which in MM tool is Suppl.
Attachments
some_math.png
some_math.png (4.58 KiB) Viewed 567 times
2lines.jpg
2lines.jpg (51.76 KiB) Viewed 571 times
Post Reply

Return to “Programming”