Skip to content

Commit fe08ec4

Browse files
committed
Initial implementation of new CPTScaleType, CPTScaleTypeLogModulus.
1 parent 71a09cd commit fe08ec4

File tree

7 files changed

+196
-1
lines changed

7 files changed

+196
-1
lines changed

framework/Source/CPTAxis.m

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -983,6 +983,10 @@ -(void)autoGenerateMajorTickLocations:(NSSet *__autoreleasing *)newMajorLocation
983983
}
984984
break;
985985

986+
case CPTScaleTypeLogModulus:
987+
// supported scale type
988+
break;
989+
986990
default:
987991
// unsupported scale type--bail out
988992
valid = NO;
@@ -1139,6 +1143,61 @@ -(void)autoGenerateMajorTickLocations:(NSSet *__autoreleasing *)newMajorLocation
11391143
}
11401144
break;
11411145

1146+
case CPTScaleTypeLogModulus:
1147+
{
1148+
double minLimit = range.minLimitDouble;
1149+
double maxLimit = range.maxLimitDouble;
1150+
1151+
// Determine interval value
1152+
if ( numTicks == 0 ) {
1153+
numTicks = 5;
1154+
}
1155+
1156+
double interval;
1157+
1158+
length = CPTLogModulus(maxLimit / minLimit);
1159+
1160+
if ( fabs(length) >= numTicks ) {
1161+
interval = CPTDecimalDoubleValue( CPTNiceNum( CPTDecimalFromDouble( length / (numTicks - 1) ) ) );
1162+
}
1163+
else {
1164+
interval = signbit(length) ? -1.0 : 1.0;
1165+
}
1166+
double intervalStep = pow( 10.0, fabs(interval) );
1167+
1168+
// Determine minor interval
1169+
double minorInterval = intervalStep * 0.9 * pow( 10.0, floor( CPTLogModulus(minLimit) ) ) / minorTicks;
1170+
1171+
// Determine the initial and final major indexes for the actual visible range
1172+
NSInteger initialIndex = (NSInteger)lrint( floor( CPTLogModulus( minLimit / fabs(interval) ) ) ); // can be negative
1173+
NSInteger finalIndex = (NSInteger)lrint( ceil( CPTLogModulus( maxLimit / fabs(interval) ) ) ); // can be negative
1174+
1175+
// Iterate through the indexes with visible ticks and build the locations sets
1176+
for ( NSInteger i = initialIndex; i <= finalIndex; i++ ) {
1177+
double pointLocation = pow(10.0, i * interval);
1178+
for ( NSUInteger j = 1; j < minorTicks; j++ ) {
1179+
double minorPointLocation = pointLocation + minorInterval * j;
1180+
if ( minorPointLocation < minLimit ) {
1181+
continue;
1182+
}
1183+
if ( minorPointLocation > maxLimit ) {
1184+
continue;
1185+
}
1186+
[minorLocations addObject:@(minorPointLocation)];
1187+
}
1188+
minorInterval *= intervalStep;
1189+
1190+
if ( pointLocation < minLimit ) {
1191+
continue;
1192+
}
1193+
if ( pointLocation > maxLimit ) {
1194+
continue;
1195+
}
1196+
[majorLocations addObject:@(pointLocation)];
1197+
}
1198+
}
1199+
break;
1200+
11421201
default:
11431202
break;
11441203
}

framework/Source/CPTDefinitions.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,8 @@ typedef NS_ENUM (NSInteger, CPTScaleType) {
163163
CPTScaleTypeLog, ///< Logarithmic axis scale
164164
CPTScaleTypeAngular, ///< Angular axis scale (not implemented)
165165
CPTScaleTypeDateTime, ///< Date/time axis scale (not implemented)
166-
CPTScaleTypeCategory ///< Category axis scale
166+
CPTScaleTypeCategory, ///< Category axis scale
167+
CPTScaleTypeLogModulus ///< Log-modulus axis scale
167168
};
168169

169170
/**

framework/Source/CPTPlot.m

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -941,6 +941,7 @@ -(void)cacheNumbers:(id)numbers forField:(NSUInteger)fieldEnum
941941
switch ( [thePlotSpace scaleTypeForCoordinate:coordinate] ) {
942942
case CPTScaleTypeLinear:
943943
case CPTScaleTypeLog:
944+
case CPTScaleTypeLogModulus:
944945
{
945946
CPTMutableNumericData *mutableNumbers = [self numericDataForNumbers:numbers];
946947

@@ -1035,6 +1036,7 @@ -(void)cacheNumbers:(id)numbers forField:(NSUInteger)fieldEnum atRecordIndex:(NS
10351036
switch ( [thePlotSpace scaleTypeForCoordinate:coordinate] ) {
10361037
case CPTScaleTypeLinear:
10371038
case CPTScaleTypeLog:
1039+
case CPTScaleTypeLogModulus:
10381040
{
10391041
mutableNumbers = [self numericDataForNumbers:numbers];
10401042

framework/Source/CPTUtilities.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,12 @@ CGFloat squareOfDistanceBetweenPoints(CGPoint point1, CGPoint point2);
147147
CPTEdgeInsets CPTEdgeInsetsMake(CGFloat top, CGFloat left, CGFloat bottom, CGFloat right);
148148
BOOL CPTEdgeInsetsEqualToEdgeInsets(CPTEdgeInsets insets1, CPTEdgeInsets insets2);
149149

150+
/// @}
151+
152+
/// @name Log Modulus Definition
153+
/// @{
154+
double CPTLogModulus(double value);
155+
150156
/// @}
151157

152158
#if __cplusplus

framework/Source/CPTUtilities.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,3 +1004,12 @@ BOOL CPTEdgeInsetsEqualToEdgeInsets(CPTEdgeInsets insets1, CPTEdgeInsets insets2
10041004
(insets1.bottom == insets2.bottom) &&
10051005
(insets1.right == insets2.right);
10061006
}
1007+
1008+
#pragma mark -
1009+
#pragma mark Log Modulus Definition
1010+
1011+
double CPTLogModulus(double value)
1012+
{
1013+
double sign = (value < 0) ? -1.0 : +1.0;
1014+
return sign * log10(fabs(value) + 1);
1015+
}

framework/Source/CPTXYAxis.m

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -718,6 +718,15 @@ -(NSNumber *)defaultTitleLocation
718718
}
719719
break;
720720

721+
case CPTScaleTypeLogModulus:
722+
{
723+
double loc = axisRange.locationDouble;
724+
double end = axisRange.endDouble;
725+
726+
location = @( pow(10.0, ( CPTLogModulus(loc) + CPTLogModulus(end) ) / 2.0) );
727+
}
728+
break;
729+
721730
default:
722731
location = axisRange.midPoint;
723732
break;

framework/Source/CPTXYPlotSpace.m

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -904,6 +904,51 @@ -(double)doublePrecisionPlotCoordinateForViewLength:(CGFloat)viewLength logPlotR
904904
return pow(10.0, coordinate);
905905
}
906906

907+
// Log-modulus
908+
-(CGFloat)viewCoordinateForViewLength:(NSDecimal)viewLength logModulusPlotRange:(CPTPlotRange *)range plotCoordinateValue:(NSDecimal)plotCoord
909+
{
910+
if ( !range ) {
911+
return CPTFloat(0.0);
912+
}
913+
914+
NSDecimal factor = CPTDecimalDivide(CPTDecimalSubtract(plotCoord, range.locationDecimal), range.lengthDecimal);
915+
if ( NSDecimalIsNotANumber(&factor) ) {
916+
factor = CPTDecimalFromInteger(0);
917+
}
918+
919+
NSDecimal viewCoordinate = CPTDecimalMultiply(viewLength, factor);
920+
921+
return CPTDecimalCGFloatValue(viewCoordinate);
922+
}
923+
924+
-(CGFloat)viewCoordinateForViewLength:(CGFloat)viewLength logModulusPlotRange:(CPTPlotRange *)range doublePrecisionPlotCoordinateValue:(double)plotCoord
925+
{
926+
if ( !range || (range.lengthDouble == 0.0) ) {
927+
return CPTFloat(0.0);
928+
}
929+
930+
double logLoc = CPTLogModulus(range.locationDouble);
931+
double logCoord = CPTLogModulus(plotCoord);
932+
double logEnd = CPTLogModulus(range.endDouble);
933+
934+
return viewLength * (CGFloat)( (logCoord - logLoc) / (logEnd - logLoc) );
935+
}
936+
937+
938+
-(double)doublePrecisionPlotCoordinateForViewLength:(CGFloat)viewLength logModulusPlotRange:(CPTPlotRange *)range boundsLength:(CGFloat)boundsLength
939+
{
940+
if ( boundsLength == 0.0 ) {
941+
return 0.0;
942+
}
943+
944+
double logLoc = CPTLogModulus(range.locationDouble);
945+
double logEnd = CPTLogModulus(range.endDouble);
946+
double coordinate = viewLength * (logEnd - logLoc) / boundsLength + logLoc;
947+
948+
return pow(10.0, coordinate);
949+
950+
}
951+
907952
/// @endcond
908953

909954
#pragma mark -
@@ -944,6 +989,12 @@ -(CGPoint)plotAreaViewPointForPlotPoint:(NSArray *)plotPoint
944989
}
945990
break;
946991

992+
case CPTScaleTypeLogModulus:
993+
{
994+
viewPoint.x = [self viewCoordinateForViewLength:layerSize.width logModulusPlotRange:self.xRange doublePrecisionPlotCoordinateValue:[plotPoint[CPTCoordinateX] doubleValue]];
995+
}
996+
break;
997+
947998
default:
948999
[NSException raise:CPTException format:@"Scale type not supported in CPTXYPlotSpace"];
9491000
}
@@ -960,6 +1011,12 @@ -(CGPoint)plotAreaViewPointForPlotPoint:(NSArray *)plotPoint
9601011
}
9611012
break;
9621013

1014+
case CPTScaleTypeLogModulus:
1015+
{
1016+
viewPoint.y = [self viewCoordinateForViewLength:layerSize.height logModulusPlotRange:self.yRange doublePrecisionPlotCoordinateValue:[plotPoint[CPTCoordinateY] doubleValue]];
1017+
}
1018+
break;
1019+
9631020
default:
9641021
[NSException raise:CPTException format:@"Scale type not supported in CPTXYPlotSpace"];
9651022
}
@@ -995,6 +1052,13 @@ -(CGPoint)plotAreaViewPointForPlotPoint:(NSDecimal *)plotPoint numberOfCoordinat
9951052
}
9961053
break;
9971054

1055+
case CPTScaleTypeLogModulus:
1056+
{
1057+
double x = CPTDecimalDoubleValue(plotPoint[CPTCoordinateX]);
1058+
viewPoint.x = [self viewCoordinateForViewLength:layerSize.width logModulusPlotRange:self.xRange doublePrecisionPlotCoordinateValue:x];
1059+
}
1060+
break;
1061+
9981062
default:
9991063
[NSException raise:CPTException format:@"Scale type not supported in CPTXYPlotSpace"];
10001064
}
@@ -1012,6 +1076,13 @@ -(CGPoint)plotAreaViewPointForPlotPoint:(NSDecimal *)plotPoint numberOfCoordinat
10121076
}
10131077
break;
10141078

1079+
case CPTScaleTypeLogModulus:
1080+
{
1081+
double y = CPTDecimalDoubleValue(plotPoint[CPTCoordinateY]);
1082+
viewPoint.y = [self viewCoordinateForViewLength:layerSize.height logModulusPlotRange:self.yRange doublePrecisionPlotCoordinateValue:y];
1083+
}
1084+
break;
1085+
10151086
default:
10161087
[NSException raise:CPTException format:@"Scale type not supported in CPTXYPlotSpace"];
10171088
}
@@ -1044,6 +1115,10 @@ -(CGPoint)plotAreaViewPointForDoublePrecisionPlotPoint:(double *)plotPoint numbe
10441115
viewPoint.x = [self viewCoordinateForViewLength:layerSize.width logPlotRange:self.xRange doublePrecisionPlotCoordinateValue:plotPoint[CPTCoordinateX]];
10451116
break;
10461117

1118+
case CPTScaleTypeLogModulus:
1119+
viewPoint.x = [self viewCoordinateForViewLength:layerSize.width logModulusPlotRange:self.xRange doublePrecisionPlotCoordinateValue:plotPoint[CPTCoordinateX]];
1120+
break;
1121+
10471122
default:
10481123
[NSException raise:CPTException format:@"Scale type not supported in CPTXYPlotSpace"];
10491124
}
@@ -1058,6 +1133,10 @@ -(CGPoint)plotAreaViewPointForDoublePrecisionPlotPoint:(double *)plotPoint numbe
10581133
viewPoint.y = [self viewCoordinateForViewLength:layerSize.height logPlotRange:self.yRange doublePrecisionPlotCoordinateValue:plotPoint[CPTCoordinateY]];
10591134
break;
10601135

1136+
case CPTScaleTypeLogModulus:
1137+
viewPoint.y = [self viewCoordinateForViewLength:layerSize.height logModulusPlotRange:self.yRange doublePrecisionPlotCoordinateValue:plotPoint[CPTCoordinateY]];
1138+
break;
1139+
10611140
default:
10621141
[NSException raise:CPTException format:@"Scale type not supported in CPTXYPlotSpace"];
10631142
}
@@ -1097,6 +1176,10 @@ -(NSArray *)plotPointForPlotAreaViewPoint:(CGPoint)point
10971176
plotPoint[CPTCoordinateX] = @([self doublePrecisionPlotCoordinateForViewLength:point.x logPlotRange:self.xRange boundsLength:boundsSize.width]);
10981177
break;
10991178

1179+
case CPTScaleTypeLogModulus:
1180+
plotPoint[CPTCoordinateX] = @([self doublePrecisionPlotCoordinateForViewLength:point.x logModulusPlotRange:self.xRange boundsLength:boundsSize.width]);
1181+
break;
1182+
11001183
default:
11011184
[NSException raise:CPTException format:@"Scale type not supported in CPTXYPlotSpace"];
11021185
}
@@ -1112,6 +1195,10 @@ -(NSArray *)plotPointForPlotAreaViewPoint:(CGPoint)point
11121195
case CPTScaleTypeLog:
11131196
plotPoint[CPTCoordinateY] = @([self doublePrecisionPlotCoordinateForViewLength:point.y logPlotRange:self.yRange boundsLength:boundsSize.height]);
11141197
break;
1198+
1199+
case CPTScaleTypeLogModulus:
1200+
plotPoint[CPTCoordinateY] = @([self doublePrecisionPlotCoordinateForViewLength:point.y logModulusPlotRange:self.yRange boundsLength:boundsSize.height]);
1201+
break;
11151202

11161203
default:
11171204
[NSException raise:CPTException format:@"Scale type not supported in CPTXYPlotSpace"];
@@ -1147,6 +1234,10 @@ -(void)plotPoint:(NSDecimal *)plotPoint numberOfCoordinates:(NSUInteger)count fo
11471234
case CPTScaleTypeLog:
11481235
plotPoint[CPTCoordinateX] = CPTDecimalFromDouble([self doublePrecisionPlotCoordinateForViewLength:point.x logPlotRange:self.xRange boundsLength:boundsSize.width]);
11491236
break;
1237+
1238+
case CPTScaleTypeLogModulus:
1239+
plotPoint[CPTCoordinateX] = CPTDecimalFromDouble([self doublePrecisionPlotCoordinateForViewLength:point.x logModulusPlotRange:self.xRange boundsLength:boundsSize.width]);
1240+
break;
11501241

11511242
default:
11521243
[NSException raise:CPTException format:@"Scale type not supported in CPTXYPlotSpace"];
@@ -1162,6 +1253,10 @@ -(void)plotPoint:(NSDecimal *)plotPoint numberOfCoordinates:(NSUInteger)count fo
11621253
plotPoint[CPTCoordinateY] = CPTDecimalFromDouble([self doublePrecisionPlotCoordinateForViewLength:point.y logPlotRange:self.yRange boundsLength:boundsSize.height]);
11631254
break;
11641255

1256+
case CPTScaleTypeLogModulus:
1257+
plotPoint[CPTCoordinateY] = CPTDecimalFromDouble([self doublePrecisionPlotCoordinateForViewLength:point.y logModulusPlotRange:self.yRange boundsLength:boundsSize.height]);
1258+
break;
1259+
11651260
default:
11661261
[NSException raise:CPTException format:@"Scale type not supported in CPTXYPlotSpace"];
11671262
}
@@ -1194,6 +1289,10 @@ -(void)doublePrecisionPlotPoint:(double *)plotPoint numberOfCoordinates:(NSUInte
11941289
plotPoint[CPTCoordinateX] = [self doublePrecisionPlotCoordinateForViewLength:point.x logPlotRange:self.xRange boundsLength:boundsSize.width];
11951290
break;
11961291

1292+
case CPTScaleTypeLogModulus:
1293+
plotPoint[CPTCoordinateX] = [self doublePrecisionPlotCoordinateForViewLength:point.x logModulusPlotRange:self.xRange boundsLength:boundsSize.width];
1294+
break;
1295+
11971296
default:
11981297
[NSException raise:CPTException format:@"Scale type not supported in CPTXYPlotSpace"];
11991298
}
@@ -1208,6 +1307,10 @@ -(void)doublePrecisionPlotPoint:(double *)plotPoint numberOfCoordinates:(NSUInte
12081307
plotPoint[CPTCoordinateY] = [self doublePrecisionPlotCoordinateForViewLength:point.y logPlotRange:self.yRange boundsLength:boundsSize.height];
12091308
break;
12101309

1310+
case CPTScaleTypeLogModulus:
1311+
plotPoint[CPTCoordinateY] = [self doublePrecisionPlotCoordinateForViewLength:point.y logModulusPlotRange:self.yRange boundsLength:boundsSize.height];
1312+
break;
1313+
12111314
default:
12121315
[NSException raise:CPTException format:@"Scale type not supported in CPTXYPlotSpace"];
12131316
}
@@ -1758,6 +1861,9 @@ -(id)debugQuickLookObject
17581861
case CPTScaleTypeLog:
17591862
xScaleTypeDesc = @"CPTScaleTypeLog";
17601863
break;
1864+
1865+
case CPTScaleTypeLogModulus:
1866+
xScaleTypeDesc = @"CPTScaleTypeLogModulus";
17611867

17621868
case CPTScaleTypeAngular:
17631869
xScaleTypeDesc = @"CPTScaleTypeAngular";
@@ -1789,6 +1895,9 @@ -(id)debugQuickLookObject
17891895
yScaleTypeDesc = @"CPTScaleTypeLog";
17901896
break;
17911897

1898+
case CPTScaleTypeLogModulus:
1899+
yScaleTypeDesc = @"CPTScaleTypeLogModulus";
1900+
17921901
case CPTScaleTypeAngular:
17931902
yScaleTypeDesc = @"CPTScaleTypeAngular";
17941903
break;

0 commit comments

Comments
 (0)