How to make clock tactics tied to clock border?

I am trying to make the clock fast, but now I want to do something weird. I want to make the border radius. This is the easy part (easy because I already did it). I have drawn 60 ticks clockwise. The problem is that 60 ticks is a perfect circle. If I change the border radius I get this clock:

enter image description here

All ticks are made using NSBezierPath, and the code for calculating the position for each tick:

tickPath.moveToPoint(CGPoint(
            x: center.x + cos(angle) *  point1 ,
            y: center.y + sin(angle) * point1
            ))

        tickPath.lineToPoint(CGPoint(
            x: center.x + cos(angle) * point2,
            y: center.y + sin(angle) * point2
            ))

      

point1 and point2 are points for 12 bars.

My background soundtrack is made with bezel:

 let bezierPath = NSBezierPath(roundedRect:self.bounds, xRadius:currentRadius, yRadius:currentRadius) 

      

currentRadius is a custom var, so my background cube should be from a perfect circle (at corner radius = height / 2) to square (at corner radius = 0).

Is there any formula for calculating the position for each tick, so that for any border radius at the end, all ticks will be at the same distance to the border?

+3


source to share


1 answer


Mathematicians are quite difficult to explain without resorting to graphical diagrams, but basically if you are considering a polar coordinate approach with the origin at the center of the clock, then there are two cases:

  • where the spoke from the beginning falls on the straight side of the square - easily using trigonometry
  • where it hits the circular arc at the corner - we use the cosine rule to solve the triangle formed by the center of the clock, the center of the circular circle, and the point where the spoke intersects the corner. The angle of the origin of this triangle is 45º - angleOfSpoke, and the two sides are of known length. Solve the cosine equation as quadratic and you have it.

This function does it:



func radiusAtAngle(angleOfSpoke: Double, radius: Double, cornerRadius: Double) -> Double {
    // radius is the half-width of the square, = the full radius of the circle
    // cornerRadius is, of course, the corner radius. 
    // angleOfSpoke is the (maths convention) angle of the spoke
    // the function returns the radius of the spoke.

    let theta = atan((radius - cornerRadius) / radius) // This determines which case

    let modAngle = angleOfSpoke % M_PI_2 // By symmetry we need only consider the first quadrant

    if modAngle <= theta { // it on the vertical flat
        return radius / cos(modAngle)
    } else if modAngle > M_PI_2 - theta { // it on the horizontal flat
        return radius / cos(M_PI_2 - modAngle)
    } else { // it on the corner arc
        // We are using the cosine rule to solve the triangle formed by
        // the clock centre, the curved corner centre,
        // and the point of intersection of the spoke.
        // Then use quadratic solution to solve for the radius.
        let diagonal = hypot(radius - cornerRadius, radius - cornerRadius)
        let rcosa = diagonal * cos(M_PI_4 - modAngle)
        let sqrTerm = rcosa * rcosa - diagonal * diagonal + cornerRadius * cornerRadius
        if sqrTerm < 0.0 {
            println("Aaargh - Negative term") // Doesn't happen - use assert in production
            return 0.0
        } else {
            return rcosa + sqrt(sqrTerm) // larger of the two solutions
        }
    }
}

      

In the diagram OP = diagonal OA = radius PS = PB = cornerRadius, OS = function return, BÔX = theta, SÔX = angleOfSpoke

Diagram of solution

+2


source







All Articles