code: protected boolean angleRecalculate(final long timeNew) {
  
          // recalculate angle using simple numerical integration of motion equation
          float deltaT1 = (timeNew - time1) / 1000f;
          if (deltaT1 > TIME_DELTA_THRESHOLD) {
              deltaT1 = TIME_DELTA_THRESHOLD;
              time1 = timeNew + Math.round(TIME_DELTA_THRESHOLD * 1000);
          }
          float deltaT2 = (time1 - time2) / 1000f;
          if (deltaT2 > TIME_DELTA_THRESHOLD) {
              deltaT2 = TIME_DELTA_THRESHOLD;
          }
  
          // circular acceleration coefficient
          float koefI = inertiaMoment / deltaT1 / deltaT2;
  
          // circular velocity coefficient
          float koefAlpha = alpha / deltaT1;
  
          // angular momentum coefficient
          float koefk = mB * (float) (Math.sin(Math.toRadians(angle0)) * Math.cos(Math.toRadians(angle1)) -
                  (Math.sin(Math.toRadians(angle1)) * Math.cos(Math.toRadians(angle0))));
  
          float angleNew = (koefI * (angle1 * 2f - angle2) + koefAlpha * angle1 + koefk) / (koefI + koefAlpha);
  
          // reassign previous iteration variables
          angle2 = angle1;
          angle1 = angleNew;
          time2 = time1;
          time1 = timeNew;
  
          // if angles changed less then threshold, return false - no need to redraw the view
          if (Math.abs(angleLastDrawn - angle1) < ANGLE_DELTA_THRESHOLD) {
              return false;
          } else {
              angleLastDrawn = angle1;
              return true;
          }
      }
docs: Recalculate angles using equation of dipole circular motion
  
  @param timeNew timestamp of method invoke
  @return if there is a need to redraw rotation