Advertisement
Guest User

Untitled

a guest
Feb 9th, 2016
60
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. -(void)autoGenerateMajorTickLocations:(CPTNumberSet __autoreleasing *)newMajorLocations minorTickLocations:(CPTNumberSet __autoreleasing *)newMinorLocations
  2. {
  3.     // Create sets for locations
  4.     CPTMutableNumberSet majorLocations = [NSMutableSet set];
  5.     CPTMutableNumberSet minorLocations = [NSMutableSet set];
  6.  
  7.     // Get plot range
  8.     CPTMutablePlotRange *range    = [[self.plotSpace plotRangeForCoordinate:self.coordinate] mutableCopy];
  9.     CPTPlotRange *theVisibleRange = self.visibleRange;
  10.  
  11.     if ( theVisibleRange ) {
  12.         [range intersectionPlotRange:theVisibleRange];
  13.     }
  14.  
  15.     // Validate scale type
  16.     BOOL valid             = YES;
  17.     CPTScaleType scaleType = [self.plotSpace scaleTypeForCoordinate:self.coordinate];
  18.  
  19.     switch ( scaleType ) {
  20.         case CPTScaleTypeLinear:
  21.             // supported scale type
  22.             break;
  23.  
  24.         case CPTScaleTypeLog:
  25.             // supported scale type--check range
  26.             if ( (range.minLimitDouble <= 0.0) || (range.maxLimitDouble <= 0.0) ) {
  27.                 valid = NO;
  28.             }
  29.             break;
  30.  
  31.         case CPTScaleTypeLogModulus:
  32.             // supported scale type
  33.             break;
  34.  
  35.         default:
  36.             // unsupported scale type--bail out
  37.             valid = NO;
  38.             break;
  39.     }
  40.  
  41.     if ( !valid ) {
  42.         *newMajorLocations = majorLocations;
  43.         *newMinorLocations = minorLocations;
  44.         return;
  45.     }
  46.  
  47.     // Cache some values
  48.     NSUInteger numTicks   = self.preferredNumberOfMajorTicks;
  49.     NSUInteger minorTicks = self.minorTicksPerInterval + 1;
  50.     double length         = fabs(range.lengthDouble);
  51.  
  52.     // Filter troublesome values and return empty sets
  53.     if ( length != 0.0 ) {
  54.         switch ( scaleType ) {
  55.             case CPTScaleTypeLinear:
  56.             {
  57.                 // Determine interval value
  58.                 switch ( numTicks ) {
  59.                     case 0:
  60.                         numTicks = 5;
  61.                         break;
  62.  
  63.                     case 1:
  64.                         numTicks = 2;
  65.                         break;
  66.  
  67.                     default:
  68.                         // ok
  69.                         break;
  70.                 }
  71.  
  72.                 NSDecimal zero = CPTDecimalFromInteger(0);
  73.                 NSDecimal one  = CPTDecimalFromInteger(1);
  74.  
  75.                 NSDecimal majorInterval;
  76.                 if ( numTicks == 2 ) {
  77.                     majorInterval = CPTNiceLength(range.lengthDecimal);
  78.                 }
  79.                 else {
  80.                     majorInterval = CPTDecimalDivide( range.lengthDecimal, CPTDecimalFromUnsignedInteger(numTicks - 1) );
  81.                     majorInterval = CPTNiceNum(majorInterval);
  82.                 }
  83.                 if ( CPTDecimalLessThan(majorInterval, zero) ) {
  84.                     majorInterval = CPTDecimalMultiply( majorInterval, CPTDecimalFromInteger(-1) );
  85.                 }
  86.  
  87.                 NSDecimal minorInterval;
  88.                 if ( minorTicks > 1 ) {
  89.                     minorInterval = CPTDecimalDivide( majorInterval, CPTDecimalFromUnsignedInteger(minorTicks) );
  90.                 }
  91.                 else {
  92.                     minorInterval = zero;
  93.                 }
  94.  
  95.                 // Calculate actual range limits
  96.                 NSDecimal minLimit = range.minLimitDecimal;
  97.                 NSDecimal maxLimit = range.maxLimitDecimal;
  98.  
  99.                 // Determine the initial and final major indexes for the actual visible range
  100.                 NSDecimal initialIndex = CPTDecimalDivide(minLimit, majorInterval);
  101.                 NSDecimalRound(&initialIndex, &initialIndex, 0, NSRoundDown);
  102.  
  103.                 NSDecimal finalIndex = CPTDecimalDivide(maxLimit, majorInterval);
  104.                 NSDecimalRound(&finalIndex, &finalIndex, 0, NSRoundUp);
  105.  
  106.                 // Iterate through the indexes with visible ticks and build the locations sets
  107.                 for ( NSDecimal i = initialIndex; CPTDecimalLessThanOrEqualTo(i, finalIndex); i = CPTDecimalAdd(i, one) ) {
  108.                     NSDecimal pointLocation      = CPTDecimalMultiply(majorInterval, i);
  109.                     NSDecimal minorPointLocation = pointLocation;
  110.  
  111.                     for ( NSUInteger j = 1; j < minorTicks; j++ ) {
  112.                         minorPointLocation = CPTDecimalAdd(minorPointLocation, minorInterval);
  113.  
  114.                         if ( CPTDecimalLessThan(minorPointLocation, minLimit) ) {
  115.                             continue;
  116.                         }
  117.                         if ( CPTDecimalGreaterThan(minorPointLocation, maxLimit) ) {
  118.                             continue;
  119.                         }
  120.                         [minorLocations addObject:[NSDecimalNumber decimalNumberWithDecimal:minorPointLocation]];
  121.                     }
  122.  
  123.                     if ( CPTDecimalLessThan(pointLocation, minLimit) ) {
  124.                         continue;
  125.                     }
  126.                     if ( CPTDecimalGreaterThan(pointLocation, maxLimit) ) {
  127.                         continue;
  128.                     }
  129.                     [majorLocations addObject:[NSDecimalNumber decimalNumberWithDecimal:pointLocation]];
  130.                 }
  131.             }
  132.             break;
  133.  
  134.             case CPTScaleTypeLog:
  135.             {
  136.                 double minLimit = range.minLimitDouble;
  137.                 double maxLimit = range.maxLimitDouble;
  138.  
  139.                 if ( (minLimit > 0.0) && (maxLimit > 0.0) ) {
  140.                     // Determine interval value
  141.                     length = log10(maxLimit / minLimit);
  142.  
  143.                     double interval     = signbit(length) ? -1.0 : 1.0;
  144.                     double intervalStep = pow( 10.0, fabs(interval) );
  145.  
  146.                     // Determine minor interval
  147.                     double minorInterval = intervalStep * 0.9 * pow( 10.0, floor( log10(minLimit) ) ) / minorTicks;
  148.  
  149.                     // Determine the initial and final major indexes for the actual visible range
  150.                     NSInteger initialIndex = (NSInteger)lrint( floor( log10( minLimit / fabs(interval) ) ) ); // can be negative
  151.                     NSInteger finalIndex   = (NSInteger)lrint( ceil( log10( maxLimit / fabs(interval) ) ) );  // can be negative
  152.  
  153.                     // Iterate through the indexes with visible ticks and build the locations sets
  154.                     for ( NSInteger i = initialIndex; i <= finalIndex; i++ ) {
  155.                         double pointLocation = pow(10.0, i * interval);
  156.                         for ( NSUInteger j = 1; j < minorTicks; j++ ) {
  157.                             double minorPointLocation = pointLocation + minorInterval * j;
  158.                             if ( minorPointLocation < minLimit ) {
  159.                                 continue;
  160.                             }
  161.                             if ( minorPointLocation > maxLimit ) {
  162.                                 continue;
  163.                             }
  164.                             [minorLocations addObject:@(minorPointLocation)];
  165.                         }
  166.                         minorInterval *= intervalStep;
  167.  
  168.                         if ( pointLocation < minLimit ) {
  169.                             continue;
  170.                         }
  171.                         if ( pointLocation > maxLimit ) {
  172.                             continue;
  173.                         }
  174.                         [majorLocations addObject:@(pointLocation)];
  175.                     }
  176.                 }
  177.             }
  178.             break;
  179.  
  180.             case CPTScaleTypeLogModulus:
  181.             {
  182.                 double minLimit = range.minLimitDouble;
  183.                 double maxLimit = range.maxLimitDouble;
  184.  
  185.                 // Determine interval value
  186.                 double modMinLimit = CPTLogModulus(minLimit);
  187.                 double modMaxLimit = CPTLogModulus(maxLimit);
  188.  
  189.                 double multiplier = pow( 10.0, floor( log10(length) ) );
  190.                 multiplier = (multiplier < 1.0) ? multiplier : 1.0;
  191.  
  192.                 double intervalStep = 10.0;
  193.  
  194.                 // Determine the initial and final major indexes for the actual visible range
  195.                 NSInteger initialIndex = (NSInteger)lrint( floor(modMinLimit / multiplier) ); // can be negative
  196.                 NSInteger finalIndex   = (NSInteger)lrint( ceil(modMaxLimit / multiplier) );  // can be negative
  197.  
  198.                 if ( initialIndex < 0 ) {
  199.                     // Determine minor interval
  200.                     double minorInterval = intervalStep * 0.9 * multiplier / minorTicks;
  201.  
  202.                     for ( NSInteger i = MIN(0, finalIndex); i >= initialIndex; i-- ) {
  203.                         double pointLocation;
  204.                         double sign = -multiplier;
  205.  
  206.                         if ( multiplier < 1.0 ) {
  207.                             pointLocation = sign * pow(10.0, fabs( (double)i ) - 1.0);
  208.                         }
  209.                         else {
  210.                             pointLocation = sign * pow( 10.0, fabs( (double)i ) );
  211.                         }
  212.  
  213.                         for ( NSUInteger j = 1; j < minorTicks; j++ ) {
  214.                             double minorPointLocation = pointLocation + sign * minorInterval * j;
  215.                             if ( minorPointLocation < minLimit ) {
  216.                                 continue;
  217.                             }
  218.                             if ( minorPointLocation > maxLimit ) {
  219.                                 continue;
  220.                             }
  221.                             [minorLocations addObject:@(minorPointLocation)];
  222.                         }
  223.                         minorInterval *= intervalStep;
  224.  
  225.                         if ( i == 0 ) {
  226.                             pointLocation = 0.0;
  227.                         }
  228.                         if ( pointLocation < minLimit ) {
  229.                             continue;
  230.                         }
  231.                         if ( pointLocation > maxLimit ) {
  232.                             continue;
  233.                         }
  234.                         [majorLocations addObject:@(pointLocation)];
  235.                     }
  236.                 }
  237.  
  238.                 if ( finalIndex >= 0 ) {
  239.                     // Determine minor interval
  240.                     double minorInterval = intervalStep * 0.9 * multiplier / minorTicks;
  241.  
  242.                     for ( NSInteger i = MAX(0, initialIndex); i <= finalIndex; i++ ) {
  243.                         double pointLocation;
  244.                         double sign = multiplier;
  245.  
  246.                         if ( multiplier < 1.0 ) {
  247.                             pointLocation = sign * pow(10.0, fabs( (double)i ) - 1.0);
  248.                         }
  249.                         else {
  250.                             pointLocation = sign * pow( 10.0, fabs( (double)i ) );
  251.                         }
  252.  
  253.                         for ( NSUInteger j = 1; j < minorTicks; j++ ) {
  254.                             double minorPointLocation = pointLocation + sign * minorInterval * j;
  255.                             if ( minorPointLocation < minLimit ) {
  256.                                 continue;
  257.                             }
  258.                             if ( minorPointLocation > maxLimit ) {
  259.                                 continue;
  260.                             }
  261.                             [minorLocations addObject:@(minorPointLocation)];
  262.                         }
  263.                         minorInterval *= intervalStep;
  264.  
  265.                         if ( i == 0 ) {
  266.                             pointLocation = 0.0;
  267.                         }
  268.                         if ( pointLocation < minLimit ) {
  269.                             continue;
  270.                         }
  271.                         if ( pointLocation > maxLimit ) {
  272.                             continue;
  273.                         }
  274.                         [majorLocations addObject:@(pointLocation)];
  275.                     }
  276.                 }
  277.             }
  278.             break;
  279.  
  280.             default:
  281.                 break;
  282.         }
  283.     }
  284.  
  285.     // Return tick locations sets
  286.     *newMajorLocations = majorLocations;
  287.     *newMinorLocations = minorLocations;
  288. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement