小试 ionic

被纠结 jquery mobile 写的东西不好看,有极其轻微的闪动。然后跑来研究这个了..

起步

更新安装慢的,需要修改下nodejs镜像站

http://cnpmjs.org/

$ npm install -g cnpm --registry=https://r.cnpmjs.org

http://www.ionicframework.com/getting-started/

异常:

ionic build android error when download gradle

修复:

http://stackoverflow.com/questions/29874564/ionic-build-android-error-when-download-gradle

实例:

http://codepen.io/ionic/

文档:

http://www.ionicframework.com/docs/

小结:看似强大,但是相对问题也不少,罗列下

一、样式不是完全统一的,需要针对ios和android单独进行特殊调整。如在浏览器和ios里打开页面。tab 是在底部的,在android里,tab飘到顶部,需要进行特殊处理.

http://ionicframework.com/docs/api/provider/$ionicConfigProvider/

angular.module('ionicApp', [ 'ionic' ]).config(
		function($ionicConfigProvider) {
			//初始化函数
			//禁用缓存.
			$ionicConfigProvider.views.maxCache(0);
			//需要特殊设置安卓样式控制
			$ionicConfigProvider.platform.android.tabs.style('standard');
			$ionicConfigProvider.platform.android.tabs.position('standard');
			$ionicConfigProvider.platform.android.navBar.alignTitle('center');
			// note that you can also chain configs
			$ionicConfigProvider.backButton.text('Go Back').icon(
					'ion-chevron-left');
		})

安提示生成的demo,tab有问题,但是手动编写时。。没有问题。。。原因有待研究。

phonegap 3.0 以上版本需要通过插件进行缓存清理,不支持webview.getSettings 这种处理方式.

补充js清理神句…

location.reload(true);

执行时,会有提示

 

 

java获取基站 phonegap 插件

参考

http://code.google.com/p/dogood/source/browse/trunk/annole_android/LiveWallpaper/src/fixedPosition/CellIDInfoManager.java?r=142

代码:

package fixedPosition;

import java.util.ArrayList;
import java.util.List;

import android.content.Context;
import android.telephony.NeighboringCellInfo;
import android.telephony.TelephonyManager;
import android.telephony.cdma.CdmaCellLocation;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;

//三大网络运营商的网络制式对应如下:
//
//移动2G 网   -->      GSM
//
//移动3G 网   -->      TD-SCDMA
//
//电信2G 网   -->      CDMA
//
//电信3G 网   -->      CDMA2000
//
//联通2G 网   -->      GSM
//
//联通3G 网   -->      WCDMA

//NETWORK_TYPE_UNKNOWN
//NETWORK_TYPE_GPRS
//NETWORK_TYPE_EDGE
//NETWORK_TYPE_UMTS
//NETWORK_TYPE_HSDPA
//NETWORK_TYPE_HSUPA
//NETWORK_TYPE_HSPA
//NETWORK_TYPE_CDMA
//NETWORK_TYPE_EVDO_0
//NETWORK_TYPE_EVDO_A
//NETWORK_TYPE_EVDO_B
//NETWORK_TYPE_1xRTT
//NETWORK_TYPE_IDEN
//NETWORK_TYPE_LTE
//NETWORK_TYPE_EHRPD

public class CellIDInfoManager {

	private final static String TAG = "CellIDInfoManager";
	private Context context;

	public CellIDInfoManager(Context context) {
		this.context=context;
	}
	/*
	 * 获取基站信息
	 */
	public ArrayList<CellIDInfo> getCellIDInfo() throws Exception{

		TelephonyManager manager = (TelephonyManager) context.getSystemService(Context.TELEPHONY_SERVICE);

		ArrayList<CellIDInfo> CellID = new ArrayList<CellIDInfo>();
		CellIDInfo currentCell = new CellIDInfo();

		int type = manager.getNetworkType();
		Log.d(TAG, "getCellIDInfo--> 		NetworkType = " + type);
		int phoneType = manager.getPhoneType();
		Log.d(TAG, "getCellIDInfo--> 		phoneType = " + phoneType);

		if (type == TelephonyManager.NETWORK_TYPE_GPRS				// GSM网
				|| type == TelephonyManager.NETWORK_TYPE_EDGE
				|| type == TelephonyManager.NETWORK_TYPE_HSDPA)
		{
			GsmCellLocation gsm = ((GsmCellLocation) manager.getCellLocation());
			if (gsm == null)
			{
				Log.e(TAG, "GsmCellLocation is null!!!");
				return null;
			}

			int lac = gsm.getLac();
			String mcc = manager.getNetworkOperator().substring(0, 3);
			String mnc = manager.getNetworkOperator().substring(3, 5);
			int cid = gsm.getCid();

			currentCell.cellId = gsm.getCid();
			currentCell.mobileCountryCode = mcc;
			currentCell.mobileNetworkCode = mnc;
			currentCell.locationAreaCode = lac;

			currentCell.radioType = "gsm";

			CellID.add(currentCell);

//			// 获得邻近基站信息
			List<NeighboringCellInfo> list = manager.getNeighboringCellInfo();
			int size = list.size();
			for (int i = 0; i < size; i++) {

				CellIDInfo info = new CellIDInfo();
				info.cellId = list.get(i).getCid();
				info.mobileCountryCode = mcc;
				info.mobileNetworkCode = mnc;
				info.locationAreaCode = lac;

				CellID.add(info);
			}

		}else if (type == TelephonyManager.NETWORK_TYPE_CDMA		//// 电信cdma网
				|| type == TelephonyManager.NETWORK_TYPE_1xRTT
				|| type == TelephonyManager.NETWORK_TYPE_EVDO_0
				|| type == TelephonyManager.NETWORK_TYPE_EVDO_A)
		{

			CdmaCellLocation cdma = (CdmaCellLocation) manager.getCellLocation();	
			if (cdma == null)
			{
				Log.e(TAG, "CdmaCellLocation is null!!!");
				return null;
			}

			int lac = cdma.getNetworkId();
			String mcc = manager.getNetworkOperator().substring(0, 3);
			String mnc = String.valueOf(cdma.getSystemId());
			int cid = cdma.getBaseStationId();

			currentCell.cellId = cid;
			currentCell.mobileCountryCode = mcc;
			currentCell.mobileNetworkCode = mnc;
			currentCell.locationAreaCode = lac;

			currentCell.radioType = "cdma";

			CellID.add(currentCell);

//			// 获得邻近基站信息
			List<NeighboringCellInfo> list = manager.getNeighboringCellInfo();
			int size = list.size();
			for (int i = 0; i < size; i++) {

				CellIDInfo info = new CellIDInfo();
				info.cellId = list.get(i).getCid();
				info.mobileCountryCode = mcc;
				info.mobileNetworkCode = mnc;
				info.locationAreaCode = lac;

				CellID.add(info);
			}
		}

		return CellID;

	}

}

phonegap插件版本(只编写了获取邻近的基站)

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.cordova.api.CallbackContext;
import org.apache.cordova.api.Plugin;
import org.apache.cordova.api.PluginResult;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.example.hello.MainActivity;

import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.telephony.NeighboringCellInfo;
import android.telephony.TelephonyManager;
import android.telephony.gsm.GsmCellLocation;
import android.util.Log;

public class UnicomGSMCell extends Plugin {

	public static final String PLUGIN_NAME = "UnicomGSMCell";
	NotificationManager notificationManager;
	Notification note;
	PendingIntent contentIntent;

	public CallbackContext callbackContext;
	private static final String STOP_ACTION = "stop";
	private static final String GET_ACTION = "LocationInfo";
	public LocationClient locationClient = null;
	public JSONObject jsonObj = new JSONObject();
	public boolean result = false;

	private static final Map<Integer, String> ERROR_MESSAGE_MAP = new HashMap<Integer, String>();

	private static final String DEFAULT_ERROR_MESSAGE = "服务端定位失败";

	public String getErrorMessage(int locationType) {
		String result = ERROR_MESSAGE_MAP.get(locationType);
		if (result == null) {
			result = DEFAULT_ERROR_MESSAGE;
		}
		return result;
	}

	@Override
	public boolean execute(String action, JSONArray args,
			final CallbackContext callbackContext) throws JSONException {
		Log.d(PLUGIN_NAME, "Plugin execute called with action: " + action);

		setCallbackContext(callbackContext);
		if (GET_ACTION.equals(action)) {
			cordova.getActivity().runOnUiThread(new Runnable() {
				@Override
				public void run() {
					TelephonyManager manager = (TelephonyManager) cordova
							.getActivity().getSystemService(
									Context.TELEPHONY_SERVICE);

					String operator = manager.getNetworkOperator();
					/** 通过operator获取 MCC 和MNC */
					int mcc = Integer.parseInt(operator.substring(0, 3));
					int mnc = Integer.parseInt(operator.substring(3));

					// GsmCellLocation location = (GsmCellLocation)
					// manager.getCellLocation();

					/** 通过GsmCellLocation获取中国移动和联通 LAC 和cellID */
					// int lac = location.getLac();
					// int cellid = location.getCid();
					/** 通过CdmaCellLocation获取中国电信 LAC 和cellID */
					// <span style="white-space:pre"> </span>
					/*
					 * CdmaCellLocation location1 = (CdmaCellLocation)
					 * mTelephonyManager.getCellLocation(); <span
					 * style="white-space:pre"> </span> lac =
					 * location1.getNetworkId(); <span style="white-space:pre">
					 * </span> cellId = location1.getBaseStationId(); <span
					 * style="white-space:pre"> </span> cellId /= 16;
					 */

					int strength = 0;
					/** 通过getNeighboringCellInfo获取BSSS */
					List<NeighboringCellInfo> infoLists = manager
							.getNeighboringCellInfo();
					System.out.println("infoLists:" + infoLists + "     size:"
							+ infoLists.size());

					// List<NeighboringCellInfo> celllist = new
					// ArrayList<NeighboringCellInfo>();

					JSONArray jsonarray = new JSONArray();
					for (NeighboringCellInfo info : infoLists) {
						JSONObject jo = new JSONObject();
						try {
							jo.put("rssi", info.getRssi());
							jo.put("cellid", info.getCid());
							jo.put("lac", info.getLac());
						} catch (JSONException e) {
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						jsonarray.put(jo);
						// org.json.JSONObject jo =
						// JSONArray.toJSONObject(info);
						// celllist.add( JSONArray.fromObject(info));
						strength += (-133 + 2 * info.getRssi());// 获取邻区基站信号强度
						// info.getLac();// 取出当前邻区的LAC
						// info.getCid();// 取出当前邻区的CID
						System.out.println("rssi:" + info.getRssi()
								+ ";cellid:" + info.getCid() + ";lac:"
								+ info.getLac());
					}
					// JSONArray jsonarray = JSONArray.toJSONObject(infoLists);
					callbackContext.success(jsonarray.toString());
					result = true;
				}

			});
		} else if (STOP_ACTION.equals(action)) {
			locationClient.stop();
		}

		while (result == false) {
			try {
				Thread.sleep(100);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		return true;
	}

	@Override
	public void onDestroy() {
		if (locationClient != null && locationClient.isStarted()) {
			locationClient.stop();
			locationClient = null;
		}
		super.onDestroy();
	}

	private void logMsg(String s) {
		System.out.println(s);
	}

	public CallbackContext getCallbackContext() {
		return callbackContext;
	}

	public void setCallbackContext(CallbackContext callbackContext) {
		this.callbackContext = callbackContext;
	}

	@SuppressWarnings("unused")
	@Override
	public PluginResult execute(String arg0, JSONArray arg1, String arg2) {
		// TODO Auto-generated method stub
		return null;
	}

}

index.html

<!DOCTYPE html>
<html class="ui-mobile">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>lbs测试</title>
<meta name="viewport"
	content="width=device-width, initial-scale=1,maximum-scale=1, user-scalable=no">
<script type="text/javascript" charset="utf-8" src="jquery-1.7.1.min.js"></script>
<script type="text/javascript" charset="utf-8" src="cordova.android.js"></script>
<script type="text/javascript">
	document.addEventListener("deviceready", appReady, false);
	function appReady() {
		getgsmcell();
	}
	function getlbs(){
		$('body').append('开始获取'+'<Br>');
		function onSuccess(pos) {
			$('body').append('成功结果:' + JSON.stringify(pos)+'<Br>');
		}
		function onFail(pos) {
			$('body').append('失败结果:' + JSON.stringify(pos)+'<Br>');
		}
		setTimeout(function(){
			cordova.exec(onSuccess, onFail, 'BaiduLocation', 'getCurrentPosition', []);
		},1000)
	}
	function getgsmcell(){
		$('body').append('开始获取'+'<Br>');
		function onSuccess(pos) {
			$('body').append('成功结果:' + JSON.stringify(pos)+'<Br>');
		}
		function onFail(pos) {
			$('body').append('失败结果:' + JSON.stringify(pos)+'<Br>');
		}
		setTimeout(function(){
			cordova.exec(onSuccess, onFail, 'UnicomGSMCell', 'LocationInfo', []);
		},1000)
	}
</script>
</head>
<body>
	<br>
	<h1 onclick="getlbs()">获取定位信息</h1>
	<br>
	<br>
	<h1 onclick="getgsmcell()">获取基站信息</h1>
	<br>
	测试页面
</body>
</html>

 

解决百度地图JS版在ios设备中异常退出

ios对内存控制器比较严格

需要特别注意,百度地图分两种版本

一、JavaScript API大众版

http://developer.baidu.com/map/index.php?title=jspopular

二、JavaScript API极速版

http://developer.baidu.com/map/index.php?title=jsextreme

极速版本是做了优化的,专门在手机中使用,但是功能相对简单。 如路线图,多点标注时的特殊处理都是没有的。但是大众版相对占内存,在多次拖放,缩放的情况下,会异常退出。

解决方案:

将百度地图坐标系转换成腾讯地图的坐标系统,然后套用对应的功能。腾讯地图做优化做得比较好。经多次测试,不会出现卡和异常退出的情况

坐标系转换:

坐标系纠偏,转换类

坐标系纠偏,转换类

缘由:常见各种坐标系由来和对应关系

WGS84、Web墨卡托、火星坐标、百度坐标互转

http://blog.csdn.net/wildboy2001/article/details/12031351

自己取的点为什么在地图上显示不准?

http://lbs.amap.com/home/faq/%E5%9D%90%E6%A0%87%E4%BD%93%E7%B3%BB/#Q03

常见坐标系对应关系

1.GPS/原始坐标系 WGS-84
2.百度 /加密坐标系 BD-09
3.谷歌/腾讯 GCJ-02

转换类

声明:类为复制

<?php
/**
 * 1.GPS/原始坐标系   WGS-84
 * 2.百度 /加密坐标系   BD-09
 * 3.谷歌/腾讯     GCJ-02
 */
class GPS {
	private $PI = 3.14159265358979324;
	private $x_pi = 0;
	public function __construct() {
		$this->x_pi = 3.14159265358979324 * 3000.0 / 180.0;
	}
	// WGS-84 to GCJ-02
	public function gcj_encrypt($wgsLat, $wgsLon) {
		if ($this->outOfChina ( $wgsLat, $wgsLon ))
			return array (
					'lat' => $wgsLat,
					'lon' => $wgsLon 
			);

		$d = $this->delta ( $wgsLat, $wgsLon );
		return array (
				'lat' => $wgsLat + $d ['lat'],
				'lon' => $wgsLon + $d ['lon'] 
		);
	}
	// GCJ-02 to WGS-84
	public function gcj_decrypt($gcjLat, $gcjLon) {
		if ($this->outOfChina ( $gcjLat, $gcjLon ))
			return array (
					'lat' => $gcjLat,
					'lon' => $gcjLon 
			);

		$d = $this->delta ( $gcjLat, $gcjLon );
		return array (
				'lat' => $gcjLat - $d ['lat'],
				'lon' => $gcjLon - $d ['lon'] 
		);
	}
	// GCJ-02 to WGS-84 exactly
	public function gcj_decrypt_exact($gcjLat, $gcjLon) {
		$initDelta = 0.01;
		$threshold = 0.000000001;
		$dLat = $initDelta;
		$dLon = $initDelta;
		$mLat = $gcjLat - $dLat;
		$mLon = $gcjLon - $dLon;
		$pLat = $gcjLat + $dLat;
		$pLon = $gcjLon + $dLon;
		$wgsLat = 0;
		$wgsLon = 0;
		$i = 0;
		while ( TRUE ) {
			$wgsLat = ($mLat + $pLat) / 2;
			$wgsLon = ($mLon + $pLon) / 2;
			$tmp = $this->gcj_encrypt ( $wgsLat, $wgsLon );
			$dLat = $tmp ['lat'] - $gcjLat;
			$dLon = $tmp ['lon'] - $gcjLon;
			if ((abs ( $dLat ) < $threshold) && (abs ( $dLon ) < $threshold))
				break;

			if ($dLat > 0)
				$pLat = $wgsLat;
			else
				$mLat = $wgsLat;
			if ($dLon > 0)
				$pLon = $wgsLon;
			else
				$mLon = $wgsLon;

			if (++ $i > 10000)
				break;
		}
		// console.log(i);
		return array (
				'lat' => $wgsLat,
				'lon' => $wgsLon 
		);
	}
	// GCJ-02 to BD-09
	public function bd_encrypt($gcjLat, $gcjLon) {
		$x = $gcjLon;
		$y = $gcjLat;
		$z = sqrt ( $x * $x + $y * $y ) + 0.00002 * sin ( $y * $this->x_pi );
		$theta = atan2 ( $y, $x ) + 0.000003 * cos ( $x * $this->x_pi );
		$bdLon = $z * cos ( $theta ) + 0.0065;
		$bdLat = $z * sin ( $theta ) + 0.006;
		return array (
				'lat' => $bdLat,
				'lon' => $bdLon 
		);
	}
	// BD-09 to GCJ-02
	public function bd_decrypt($bdLat, $bdLon) {
		$x = $bdLon - 0.0065;
		$y = $bdLat - 0.006;
		$z = sqrt ( $x * $x + $y * $y ) - 0.00002 * sin ( $y * M_PI );
		$theta = atan2 ( $y, $x ) - 0.000003 * cos ( $x * M_PI );
		$gg_lon = $z * cos ( $theta );
		$gg_lat = $z * sin ( $theta );
		// 方式2
		return array (
				'lat' => $gg_lat,
				'lon' => $gg_lon 
		);
		//
		$x = $bdLon - 0.0065;
		$y = $bdLat - 0.006;
		$z = sqrt ( $x * $x + $y * $y ) - 0.00002 * sin ( $y * $this->x_pi );
		$theta = atan2 ( $y, $x ) - 0.000003 * cos ( $x * $this->x_pi );
		$$gcjLon = $z * cos ( $theta );
		$gcjLat = $z * sin ( $theta );
		return array (
				'lat' => $gcjLat,
				'lon' => $gcjLon 
		);
	}
	public function bd_decrypt_lat($bdLat, $bdLon) {
		$result = $this->bd_decrypt ( $bdLat, $bdLon );
		return $result ['lat'];
	}
	public function bd_decrypt_lon($bdLat, $bdLon) {
		$result = $this->bd_decrypt ( $bdLat, $bdLon );
		return $result ['lon'];
	}

	// WGS-84 to Web mercator
	// $mercatorLat -> y $mercatorLon -> x
	public function mercator_encrypt($wgsLat, $wgsLon) {
		$x = $wgsLon * 20037508.34 / 180.;
		$y = log ( tan ( (90. + $wgsLat) * $this->PI / 360. ) ) / ($this->PI / 180.);
		$y = $y * 20037508.34 / 180.;
		return array (
				'lat' => $y,
				'lon' => $x 
		);
		/*
		 * if ((abs($wgsLon) > 180 || abs($wgsLat) > 90)) return NULL; $x =
		 * 6378137.0 * $wgsLon * 0.017453292519943295; $a = $wgsLat *
		 * 0.017453292519943295; $y = 3189068.5 * log((1.0 + sin($a)) / (1.0 -
		 * sin($a))); return array('lat' => $y, 'lon' => $x); //
		 */
	}
	// Web mercator to WGS-84
	// $mercatorLat -> y $mercatorLon -> x
	public function mercator_decrypt($mercatorLat, $mercatorLon) {
		$x = $mercatorLon / 20037508.34 * 180.;
		$y = $mercatorLat / 20037508.34 * 180.;
		$y = 180 / $this->PI * (2 * atan ( exp ( $y * $this->PI / 180. ) ) - $this->PI / 2);
		return array (
				'lat' => $y,
				'lon' => $x 
		);
		/*
		 * if (abs($mercatorLon) < 180 && abs($mercatorLat) < 90) return NULL;
		 * if ((abs($mercatorLon) > 20037508.3427892) || (abs($mercatorLat) >
		 * 20037508.3427892)) return NULL; $a = $mercatorLon / 6378137.0 *
		 * 57.295779513082323; $x = $a - (floor((($a + 180.0) / 360.0)) *
		 * 360.0); $y = (1.5707963267948966 - (2.0 * atan(exp((-1.0 *
		 * $mercatorLat) / 6378137.0)))) * 57.295779513082323; return
		 * array('lat' => $y, 'lon' => $x); //
		 */
	}
	// two point's distance
	public function distance($latA, $lonA, $latB, $lonB) {
		$earthR = 6371000.;
		$x = cos ( $latA * $this->PI / 180. ) * cos ( $latB * $this->PI / 180. ) * cos ( ($lonA - $lonB) * $this->PI / 180 );
		$y = sin ( $latA * $this->PI / 180. ) * sin ( $latB * $this->PI / 180. );
		$s = $x + $y;
		if ($s > 1)
			$s = 1;
		if ($s < - 1)
			$s = - 1;
		$alpha = acos ( $s );
		$distance = $alpha * $earthR;
		return $distance;
	}
	private function delta($lat, $lon) {
		// Krasovsky 1940
		//
		// a = 6378245.0, 1/f = 298.3
		// b = a * (1 - f)
		// ee = (a^2 - b^2) / a^2;
		$a = 6378245.0; // a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
		$ee = 0.00669342162296594323; // ee: 椭球的偏心率。
		$dLat = $this->transformLat ( $lon - 105.0, $lat - 35.0 );
		$dLon = $this->transformLon ( $lon - 105.0, $lat - 35.0 );
		$radLat = $lat / 180.0 * $this->PI;
		$magic = sin ( $radLat );
		$magic = 1 - $ee * $magic * $magic;
		$sqrtMagic = sqrt ( $magic );
		$dLat = ($dLat * 180.0) / (($a * (1 - $ee)) / ($magic * $sqrtMagic) * $this->PI);
		$dLon = ($dLon * 180.0) / ($a / $sqrtMagic * cos ( $radLat ) * $this->PI);
		return array (
				'lat' => $dLat,
				'lon' => $dLon 
		);
	}
	private function outOfChina($lat, $lon) {
		if ($lon < 72.004 || $lon > 137.8347)
			return TRUE;
		if ($lat < 0.8293 || $lat > 55.8271)
			return TRUE;
		return FALSE;
	}
	private function transformLat($x, $y) {
		$ret = - 100.0 + 2.0 * $x + 3.0 * $y + 0.2 * $y * $y + 0.1 * $x * $y + 0.2 * sqrt ( abs ( $x ) );
		$ret += (20.0 * sin ( 6.0 * $x * $this->PI ) + 20.0 * sin ( 2.0 * $x * $this->PI )) * 2.0 / 3.0;
		$ret += (20.0 * sin ( $y * $this->PI ) + 40.0 * sin ( $y / 3.0 * $this->PI )) * 2.0 / 3.0;
		$ret += (160.0 * sin ( $y / 12.0 * $this->PI ) + 320 * sin ( $y * $this->PI / 30.0 )) * 2.0 / 3.0;
		return $ret;
	}
	private function transformLon($x, $y) {
		$ret = 300.0 + $x + 2.0 * $y + 0.1 * $x * $x + 0.1 * $x * $y + 0.1 * sqrt ( abs ( $x ) );
		$ret += (20.0 * sin ( 6.0 * $x * $this->PI ) + 20.0 * sin ( 2.0 * $x * $this->PI )) * 2.0 / 3.0;
		$ret += (20.0 * sin ( $x * $this->PI ) + 40.0 * sin ( $x / 3.0 * $this->PI )) * 2.0 / 3.0;
		$ret += (150.0 * sin ( $x / 12.0 * $this->PI ) + 300.0 * sin ( $x / 30.0 * $this->PI )) * 2.0 / 3.0;
		return $ret;
	}
}