pharo-graphics / Roassal

The Roassal Visualization Engine
MIT License
16 stars 12 forks source link

RSKiviat usePolygon does not work with even axis #78

Open Nyan11 opened 1 week ago

Nyan11 commented 1 week ago

Hello,

I want a kiviat with a polygon background with 4 axis. But the polygon is not correctly align.

reproduction

with the bug

kiviat := RSKiviat new.
kiviat addRow: #(3 5 1 2).
kiviat axisNames: #('axis1' 'axis2' 'axis3' 'axis4').
kiviat usePolygon.
kiviat open

image

without the bug

kiviat := RSKiviat new.
kiviat addRow: #(3 5 1 2 5).
kiviat axisNames: #('axis1' 'axis2' 'axis3' 'axis4' 'axis5').
kiviat usePolygon.
kiviat open

image

expected behavior

The square background on figure1 should be turned 45° on the right so the axis match the polygon corners.

Nyan11 commented 1 week ago

A simple fix could be done in the method RSKiviat >> #createPolygonFor:.

createPolygonFor: each
    "create the background polygon shape if the variable #shouldUseEllipse equals False.

    The polygon must be created with a rotation if the number of axis is even."

    | rotation |
    rotation := 0.
    axisNames size even ifTrue: [ rotation := Float pi / axisNames size ].

    ^ RSPolygon new
          noPaint;
          points:
              (RSPolygon
                   generateUnitNgonPoints: axisNames size
                   rotation: rotation) * each;
          border: self border;
          yourself

with 4 axis

image

with 8 axis

image

Nyan11 commented 1 week ago

In the above fix, the label on the bottom is not aligned properly.

('axis3' for the kiviat with 4 axis)

('amet,' for the kiviat with 8 axis)

Nyan11 commented 1 week ago

In order to fix the label issue.

fixLabelPosition: label angle: angle

    | positions gap |
    label position: angle cos @ angle sin * radius.
    gap := self labelGapSize.
    positions := Dictionary newFromPairs: {
                         0.
                         (0.5 @ 0).
                     Float halfPi.
                         (0 @ 0.5).
                         Float halfPi negated.
                         (0 @ -0.5).
                         Float pi.
                         (-0.5 @ 0).
                         (Float pi + Float halfPi).
                         (0 @ 0.5) }.
    positions
        at: angle
        ifPresent: [ :fix |
        label translateBy: label extent * fix + (gap * fix sign) ]
        ifAbsent: [
            gap := angle cos @ angle sin * gap.
            (angle between: Float halfPi negated and: 0) ifTrue: [
                ^ label translateBy: label baseRectangle bottomLeft negated + gap ].
            (angle between: 0 and: Float halfPi) ifTrue: [
                ^ label translateBy: label baseRectangle topLeft negated + gap ].
            (angle between: Float halfPi and: Float pi) ifTrue: [
                ^ label translateBy: label baseRectangle topRight negated + gap ].
            label translateBy: label baseRectangle bottomRight negated + gap ]

image

Nyan11 commented 1 week ago

I added a default value is the position dictionary for PI/2 (label is in the bottom).

 Float halfPi ->  (0 @ 0.5).

When the angle of the axis is half pi, the gap should be 0 horizontal and +0.5 vertical