ArthurGuibert / FSInteractiveMap

A charting library to visualize and interact with a vector map on iOS. It's like Geochart but for iOS!

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

add City/Province name labels in the center of their corresponding city/province.

liuxuan30 opened this issue · comments

commented

Can FSInteractiveMap supports adding City/Province name labels in the center of their corresponding city/province.

I am trying to do the same. I edited the svg(s) in inkscape to add city labels. I can see them when I open the svg in chrome (Browser) but when I load it using FsInteractiveMap the labels dont show up.

Any suggestions how this can be fixed?

commented

Well I do solved my problem on my side. However, my solution is strongly bound to the svg maker who is amCharts. I use amCharts' free svg map, and they have something called mercator projection calculation. I rewrite the mercator calculation. It can turn longitude and latitude into iOS coordinate system, so as long as I have a longitude and latitude, I can define its center in the FsInteractiveMap. If you are not using amCharts svg map, I cannot help.

For your question, if you are editing the svg file itself, you'd better to add some breakpoints to see if the XML parser get the correct elements and attributes you added. You have to follow how FsInteractiveMap parse the XML file.

I can use amCharts' svg maps (not an issue). So can you share your part of code which achieves this labeling?

commented

Are you using longitude and latitude and want to convert it into CGPoint as UIView's center? If not, my code will not work.

This is what I intend to do. So your code should fit in my use case. Kindly share.

commented

All right, here you go:
Be careful about self.mapView.actualSize, the actual size means the size has to be precise, it needs to be the smallest CGRect to contain your svg map, a.k.a all the CGPaths. The whole process relys on it. if the size is not correct, you will see offset

#pragma mark - latitude & longitude convertion functions
//Xuan: Don't ask me why
-(CGFloat)degreesToRadians:(CGFloat)degree {
    return (degree/180) * M_PI;
}

-(CGFloat)radiansToDegrees:(CGFloat)radians {
    return (radians/M_PI) * 180;
}

-(CGFloat)mercatorLatitudeToCoordinate:(CGFloat)latitude {
    if (latitude > 89.5) {
        latitude = 89.5;
    }
    if (latitude < -89.5) {
        latitude = -89.5;
    }
    CGFloat radians = [self degreesToRadians:latitude];
    CGFloat mRadians = 0.5 * log((1 + sin(radians)) / (1 - sin(radians)));
    CGFloat coordinate = [self radiansToDegrees:mRadians/2];
    return coordinate;
}

-(CGFloat)latitudeToCoordinate:(CGFloat)latitude {
    CGFloat topLatitude = 53.562517; // from amcharts svg map
    CGFloat bottomLatitude = 18.153878; // from amcharts svg map
    CGFloat cal_latitude;
    if ([@"mercator" isEqualToString:@"mercator"]) {
        cal_latitude = [self mercatorLatitudeToCoordinate:latitude];
        topLatitude = [self mercatorLatitudeToCoordinate:topLatitude];
        bottomLatitude = [self mercatorLatitudeToCoordinate:bottomLatitude];
    }

    CGFloat coordinate = (cal_latitude - topLatitude) / (bottomLatitude - topLatitude) * self.mapView.actualSize.height;
    return ceil(coordinate);
}

-(CGFloat)recalculateLongitude:(CGFloat)longitude {
    return longitude;
}

-(CGFloat)longitudeToCoordinate:(CGFloat)longitude {
    CGFloat leftLongitude = 73.554302; // from amcharts svg map
    CGFloat rightLongitude = 134.775703; // from amcharts svg map
    CGFloat reLongitude = [self recalculateLongitude:longitude];
    CGFloat coordinate = (reLongitude - leftLongitude) / (rightLongitude - leftLongitude) * self.mapView.actualSize.width;
    return ceil(coordinate);
}

Thanks!

commented

closing it since I found the solution