[转载]基于prototype的输入自动提示autocomplete

mikel阅读(954)

[转载]基于prototype的输入自动提示autocomplete – ╰⑥月の雨╮ – 博客园.

对老外的加了修改,对中文的支持和条数的显示

原作者地址: http://www.devbridge.com/projects/autocomplete/

效果:

var Autocomplete = function(el, options){
  this.el = $(el);
  this.id = this.el.identify();
  this.el.setAttribute('autocomplete','off');
  this.suggestions = [];
  this.data = [];
  this.badQueries = [];
  this.selectedIndex = -1;
  this.currentValue = this.el.value;
  this.intervalId = 0;
  this.cachedResponse = [];
  this.instanceId = null;
  this.onChangeInterval = null;
  this.ignoreValueChange = false;
  this.serviceUrl = options.serviceUrl;
  this.numbers = [];//条数
  this.options = {
    autoSubmit:false,
    minChars:1,
    maxHeight:300,
    deferRequestBy:0,
    width:0,
    showNumber:true, //是否显示条数
    container:null
  };
  if(options){ Object.extend(this.options, options); }
  if(Autocomplete.isDomLoaded){
    this.initialize();
  }else{
    Event.observe(document, 'dom:loaded', this.initialize.bind(this), false);
  }
};

Autocomplete.instances = [];
Autocomplete.isDomLoaded = false;

Autocomplete.getInstance = function(id){
  var instances = Autocomplete.instances;
  var i = instances.length;
  while(i--){ if(instances[i].id === id){ return instances[i]; }}
};

Autocomplete.highlight = function(value, re){
  return value.replace(re, function(match){ return '<strong>' + match + '<\/strong>' });
};

Autocomplete.prototype = {

  killerFn: null,

  initialize: function() {
    var me = this;
    this.killerFn = function(e) {
      if (!$(Event.element(e)).up('.autocomplete')) {
        me.killSuggestions();
        me.disableKillerFn();
      }
    } .bindAsEventListener(this);

    if (!this.options.width) { this.options.width = this.el.getWidth(); }

    var div = new Element('div', { style: 'position:absolute;' });
    div.update('<div class="autocomplete-w1"><div class="autocomplete-w2"><div class="autocomplete" id="Autocomplete_' + this.id + '" style="display:none; width:' + this.options.width + 'px;"></div></div></div>');

    this.options.container = $(this.options.container);
    if (this.options.container) {
      this.options.container.appendChild(div);
      this.fixPosition = function() { };
    } else {
      document.body.appendChild(div);
    }

    this.mainContainerId = div.identify();
    this.container = $('Autocomplete_' + this.id);
    this.fixPosition();
    
    Event.observe(this.el, window.opera ? 'keypress':'keydown', this.onKeyPress.bind(this));
    Event.observe(this.el, 'keyup', this.onKeyUp.bind(this));
    Event.observe(this.el, 'blur', this.enableKillerFn.bind(this));
    Event.observe(this.el, 'focus', this.fixPosition.bind(this));
    this.container.setStyle({ maxHeight: this.options.maxHeight + 'px' });
    this.instanceId = Autocomplete.instances.push(this) - 1;
  },

  fixPosition: function() {
    var offset = this.el.cumulativeOffset();
    $(this.mainContainerId).setStyle({ top: (offset.top + this.el.getHeight()) + 'px', left: offset.left + 'px' });
  },

  enableKillerFn: function() {
    Event.observe(document.body, 'click', this.killerFn);
  },

  disableKillerFn: function() {
    Event.stopObserving(document.body, 'click', this.killerFn);
  },

  killSuggestions: function() {
    this.stopKillSuggestions();
    this.intervalId = window.setInterval(function() { this.hide(); this.stopKillSuggestions(); } .bind(this), 300);
  },

  stopKillSuggestions: function() {
    window.clearInterval(this.intervalId);
  },

  onKeyPress: function(e) {
    if (!this.enabled) { return; }
    switch (e.keyCode) {
      case Event.KEY_ESC:
        this.el.value = this.currentValue;
        this.hide();
        break;
      case Event.KEY_TAB:
      case Event.KEY_RETURN:
        if (this.selectedIndex === -1) {
          this.hide();
          return;
        }
        this.select(this.selectedIndex);
        if (e.keyCode === Event.KEY_TAB) { return; }
        break;
      case Event.KEY_UP:
        this.moveUp();
        break;
      case Event.KEY_DOWN:
        this.moveDown();
        break;
      default:
        return;
    }
    Event.stop(e);
  },

  onKeyUp: function(e) {
    switch (e.keyCode) {
      case Event.KEY_UP:
      case Event.KEY_DOWN:
        return;
    }
    clearInterval(this.onChangeInterval);
    if (this.currentValue !== this.el.value) {
      if (this.options.deferRequestBy > 0) {
        // Defer lookup in case when value changes very quickly:
        this.onChangeInterval = setInterval((function() {
          this.onValueChange();
        }).bind(this), this.options.deferRequestBy);
      } else {
        this.onValueChange();
      }
    }
  },

  onValueChange: function() {
    clearInterval(this.onChangeInterval);
    this.currentValue = this.el.value;
    this.selectedIndex = -1;
    if (this.ignoreValueChange) {
      this.ignoreValueChange = false;
      return;
    }
    if (this.currentValue === '' || this.currentValue.length < this.options.minChars) {
      this.hide();
    } else {
      this.getSuggestions();
    }
  },

  getSuggestions: function() {
    var cr = this.cachedResponse&#91;this.currentValue&#93;;
    if (cr && Object.isArray(cr.suggestions)) {
      this.suggestions = cr.suggestions;
      this.data = cr.data;
      this.numbers = cr.numbers;
      this.suggest();
    } else if (!this.isBadQuery(this.currentValue)) {
      new Ajax.Request(this.serviceUrl, {
        parameters: { query: this.currentValue },
        onComplete: this.processResponse.bind(this),
        method: 'get'
      });
    }
  },

  isBadQuery: function(q) {
    var i = this.badQueries.length;
    while (i--) {
      if (q.indexOf(this.badQueries&#91;i&#93;) === 0) { return true; }
    }
    return false;
  },

  hide: function() {
    this.enabled = false;
    this.selectedIndex = -1;
    this.container.hide();
  },

  suggest: function() {
    if (this.suggestions.length === 0) {
      this.hide();
      return;
    }
    var content = &#91;&#93;;
    var re = new RegExp('\\b' + this.currentValue.match(/&#91;\u4e00-\u9fa5a-zA-Z0-9&#93;+/g).join('|\\b'), 'gi');
    var numbersContent = '';
    this.suggestions.each(function(value, i) {
      if (Object.isArray(this.numbers) && this.options.showNumber){
        numbersContent = ' <span class="number">约' + this.numbers[i] + '条</span>';
      }
      content.push((this.selectedIndex === i ? '<div class="selected"' : '<div'), ' title="', value, '" onclick="Autocomplete.instances&#91;', this.instanceId, '&#93;.select(', i, ');" onmouseover="Autocomplete.instances&#91;', this.instanceId, '&#93;.activate(', i, ');">', Autocomplete.highlight(value, re), numbersContent, '</div>');
    } .bind(this));
    this.enabled = true;
    this.container.update(content.join('')).show();
  },

  processResponse: function(xhr) {
    var response;
    try {
      response = xhr.responseText.evalJSON();
      if (!Object.isArray(response.data)) { response.data = []; }
    } catch (err) { return; }
    this.cachedResponse[response.query] = response;
    if (response.suggestions.length === 0) { this.badQueries.push(response.query); }
    if (response.query === this.currentValue) {
      this.suggestions = response.suggestions;
      this.data = response.data;
      this.numbers = response.numbers;
      this.suggest(); 
    }
  },

  activate: function(index) {
    var divs = this.container.childNodes;
    var activeItem;
    // Clear previous selection:
    if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
      divs[this.selectedIndex].className = '';
    }
    this.selectedIndex = index;
    if (this.selectedIndex !== -1 && divs.length > this.selectedIndex) {
      activeItem = divs[this.selectedIndex]
      activeItem.className = 'selected';
    }
    return activeItem;
  },

  deactivate: function(div, index) {
    div.className = '';
    if (this.selectedIndex === index) { this.selectedIndex = -1; }
  },

  select: function(i) {
    var selectedValue = this.suggestions[i];
    if (selectedValue) {
      this.el.value = selectedValue;
      if (this.options.autoSubmit && this.el.form) {
        this.el.form.submit();
      }
      this.ignoreValueChange = true;
      this.hide();
      this.onSelect(i);
    }
  },

  moveUp: function() {
    if (this.selectedIndex === -1) { return; }
    if (this.selectedIndex === 0) {
      this.container.childNodes[0].className = '';
      this.selectedIndex = -1;
      this.el.value = this.currentValue;
      return;
    }
    this.adjustScroll(this.selectedIndex - 1);
  },

  moveDown: function() {
    if (this.selectedIndex === (this.suggestions.length - 1)) { return; }
    this.adjustScroll(this.selectedIndex + 1);
  },

  adjustScroll: function(i) {
    var container = this.container;
    var activeItem = this.activate(i);
    var offsetTop = activeItem.offsetTop;
    var upperBound = container.scrollTop;
    var lowerBound = upperBound + this.options.maxHeight - 25;
    if (offsetTop < upperBound) {
      container.scrollTop = offsetTop;
    } else if (offsetTop > lowerBound) {
      container.scrollTop = offsetTop - this.options.maxHeight + 25;
    }
    this.el.value = this.suggestions[i];
  },

  onSelect: function(i) {
    (this.options.onSelect || Prototype.emptyFunction)(this.suggestions[i], this.data[i]);
  }

};

Event.observe(document, 'dom:loaded', function(){ Autocomplete.isDomLoaded = true; }, false

使用:Event.observe(window, ‘load’, function() {

  function onAutocompleteSelect(value, data){
            //..
    }
    var rand = new Date().getTime();
    var url = 'data.js?r=' + rand;
    new Autocomplete('txtEmployeeNum', { 
        serviceUrl: url, 
        width: 300,  //可选
        onSelect: onAutocompleteSelect, //可选
        showNumber: true //显示条数
        //container: 'ac_container'  //可选
    });
});

<input type="text" name="q" id="txtEmployeeNum" />
<!-- <div id="ac_container"></div>  -->  

data.js 有后台控制,产生json格式数据,如下:

//{query:'z',suggestions:['z','z1','z2','z3']}

//{query:'q',suggestions:['q','q1','q2','q3'],numbers:[99,88,77,66]}

{query:'去',suggestions:['去','去1','去12','去123'],numbers:[99,88,77,66]}

弹出提示层的原型:

Lithuania约88个服务

[转载]PHP书写规范 PHP Coding Standard

mikel阅读(809)

[转载]PHP书写规范 PHP Coding Standard – sink_cup – 博客园.

PHP书写规范
作者:sink <sink.cup@gmail.com>
最后修改:2011-7-7

参考资料:
PHP Manual
http://www.php.net/manual/zh/language.oop5.basic.php
PEAR Coding Standards
http://pear.php.net/manual/en/standards.php
C++ Coding Standard
http://www.possibility.com/Cpp/CppCodingStandard.html
Google C++ Style Guide
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml
Code Conventions for the Java
http://www.oracle.com/technetwork/java/codeconvtoc-136057.html

通用原则:
1、语义化
看到名字,就知道意思。

2、通用前缀
is表示是否、get表示读、set表示写。is后面优先跟形容词,而不是名词,比如是否多语言文字,应使用is_multilingual,而不是is_multilanguage。

3、单数与复数
参考js的函数命名规则:getElementById、getElementsByTagName、getElementsByName。
例如:
取我的多个好友的名字,应使用getFriendsName,而不是getFriendNames或者getFriendName
取一个用户,是getUser
取多个用户,是getUsers

4、冗余后缀
尽量不使用data、list、info后缀。
比如,js的命名就很注意,使用getElementsByTagName而不是getElementsInfoByTagName。
应该使用getFriends或者getFriendsUserId,而不是getFriendsList;应该使用getUser,而不使用getUserInfo或者getUserData。
不过有时候很难避免,比如有2个函数,分别是取用户基本信息,和取用户详细信息。
取用户基本信息:昵称、头像URI,函数名getUserBasic还是getUserBasicInfo?函数名以形容词结尾感觉不合适,待讨论。
取用户详细信息:昵称、头像URI、签名、生日,函数名getUser没问题。

5、含义模糊的类名、文件名、目录名
每当使用common、util、functions、class、object、basic作为文件名时要慎重,由于这些词太通用,发展下去里面东西可 能越来越多,变成垃圾箱。要给这些起一个准确的名字,比如要做字符串处理的类,可以叫StringLib.php,放在lib目录里。

6、lib、plugin与addon的区别
有些类、函数算做lib、plugin还是addon。待讨论。

类名:
大写字母开头,驼峰命名。一般使用名词,比如配置解析类ConfigParser,而不是ParseConfig。
与Java、C++一致。
例如:class UserModel

类的文件名:
与类名相同。这与php autoload有关,为了autoload,类名总要很长,待讨论。
与Java一致。
例如:class UserModel的文件名为UserModel.php

非类文件名:
全小写,下划线分隔,不得使用空格。比如get_user.php。

目录名:
全小写,下划线分隔,不得使用空格。比如model、www。

函数名:
小写字母开头,驼峰命名,例如:function addBlog()。
与Java、C++一致。
函数表示功能,即动作,所以动词优先,例如使用editBlog,而不用blogEdit。
PHP内置函数由于历史原因,有多种风格,do_something,something_do,dosomething,比较新的函数用了doSomething,才与目前主流语言保持一致。
比如:paser_str、json_encode、substr、fetchAll。
历史原因可能无法改变,但我们能保证新的代码是严谨的,不要让自己成为历史原因。

类中的函数:
两个函数中间空一行。如果有时间的话,各个函数按英文字母排序,免得太混乱。
例如:
class BlogModel
{
public function addBlog()
{

}

public function updateBlog()
{

}
}

文件注释:
注释紧跟<?php下一行。注明作者。@version暂不需要写,因为svn提供了版本管理。
格式按照PHPdoc的要求:http://manual.phpdoc.org/HTMLframesConverter/default/phpDocumentor/tutorial_tags.author.pkg.html
<?php
/**
* blog的各种业务:添加、更新
* @author sink
*
*/
class BlogModel
{

}
?>

API注释:
一定要写输入参数,和输出格式。写清楚正确时输出什么,错误时输出什么。
否则别人无法使用。

函数注释:
一定要写输出格式。写清楚正确时输出什么,错误时输出什么。
如果输入参数比较复杂,包含数组,看参数无法一目了然,则要写输入参数的注释。
文档注释与函数之间不能有空行。
如果函数内部步骤比较复杂,需要写“行内注释”。
例如:
/**
* 更新blog
* @param int $id blog_id
* @param array $data array(
“content” => “”, //内容
“tags” => “”, //标签
“update_time” => “”, //更新时间
)
* @return bool
*/
public function updateBlog($id,$data)
{
step1 //第一步:asdf
step2 //第二步:qwer
}

URI:
根据rfc1034国际标准的规定,域名中禁止出现下划线“_”,域名不区分大小写。
比如http://dl_dir.qq.com/是错误域名。
http://example.com与http://EXAMPLE.COM相同。
所以优先在URI中使用全小写,GET的name小写,但是GET的值除外。
比如
http://www.google.com/?hl=zh-CN
http://www.google.com/?hl=zh-cn
URI中非参数的专有名词的缩写是否使用小写,有争议无定论。
比如
http://fedoraproject.org/zh_CN/
http://zh.wikipedia.org/zh-cn/
http://code.google.com/intl/zh-CN/
http://www.microsoft.com/en-us/
语言文字代码是专有名词,ISO规定必须是减号,且建议地区使用大写。
fedora的用法很奇怪,使用了自己制造的zh_CN,而不是zh-CN。而且不建议在URI中使用下划线。
wiki用了小写,google用了大写,微软用了小写。

优先在URI中使用减号“-”,而不是下划线,GET的name除外。
比如
http://example.com/1-2-2
http://example.com/?user_id=123
如果希望用户手动输入URI,则不要区分大小写,且优先使用小写,因为用户输入更方便。
实际情况是:用户一般是手动输入域名,而不手动输入URI,因为URI很长。在这种情况下,URI小写是否有意义,如果使用 http://example.com/?userId=123,变量名就可以使用驼峰$userId = $_GET[‘userId’],就能够和Java、C++保持一致,这样数据库也要驼峰命名。待讨论。

变量:
全小写,下划线分隔,例如:$user_id。
与Java、C++不一致。待讨论。
类的成员变量、函数的形参、类实例化成一个对象,都遵守变量的命名规则。
原因:URI、数据库有小写惯例,从$_GET、$_POST中获得参数入库,所以用小写。
PHP内置变量$_GET、$_POST使用下划线开头,全大写。自定义的变量无论多么重要,都不要使用下划线开头,以免将来与内置变量冲突。
比如:不要使用$_PUT、$_DELETE。

常量:
全大写,下划线分隔。例如:const MEMCACHE_TTL = 600;

PHP短标签:
使用<?php ?>,不使用短标签<? ?>。因为与xml冲突,且不利于部署。

类大括号换行:
可以采用大括号单独占一行,也可以大括号与别的放在一行,有争议无定论,待讨论。
class UserModel
{

}
支持换行者:
http://www.php.net/manual/zh/language.oop5.basic.php
http://pear.php.net/manual/en/standards.classdef.php

函数大括号换行:
有争议无定论,待讨论。
function getUser()
{
}
支持换行者:
http://www.php.net/manual/zh/language.oop5.basic.php
http://pear.php.net/manual/en/standards.funcdef.php

if大括号换行:
有争议无定论,待讨论。
例如:
if(!empty($name))
{

}
或者
if(!empty($name)){

}
支持换行者:
http://www.possibility.com/Cpp/CppCodingStandard.html#brace

支持同行者:
http://www.php.net/manual/zh/language.oop5.basic.php
http://pear.php.net/manual/en/standards.control.php

switch大括号换行:
switch (…)
{
case 1:

break;

default:
}
支持换行者:
http://www.possibility.com/Cpp/CppCodingStandard.html#switch

数组小括号换行:
有争议无定论,待讨论。
$user = array(
“id” => “123”,
“name” => “user1”,
“email” => “a@example.com”,
)
支持同行者:
http://pear.php.net/manual/en/standards.arrays.php

数组内部换行:
2维及以上数组的数组内部换行。

$user = array(
‘id’ => ‘123’,
‘name’ => ‘user1′,
’email’ => ‘a@example.com’,
);
1维数组内部不换行?待讨论。

$users_id = array(’23’,’12’,’24’);

数组最后的逗号:
数组每一行最后要有逗号,这样方便以后添加。不过前端JSON最后不能有逗号,否则有的浏览器不支持,待讨论。
比如
$user = array(
‘id’ => ‘123’,
‘name’ => ‘user1’, //正确
);
$user = array(
‘id’ => ‘123’,
‘name’ => ‘user1’ //错误
);

单引号与双引号:
优先使用单引号,当需要转义时使用双引号。这与JSON不同,JSON全是双引号,待讨论。
比如:
echo ‘name is:’ . $name . ‘.’ . “\n”;
$user = array(
‘id’ => ‘123’,
);

条件判断的大括号:
必须有大括号,即使只有一行。
正确:
if(!empty($name))
{
doSomething();
}
错误:
if(!empty($name))
doSomething();

回车换行:
使用换行LF(\n,0a,Unix风格)。不使用CR+LF(Windows风格)。
参考:http://zh.wikipedia.org/zh-cn/%E6%8F%9B%E8%A1%8C
eclipse——》workspace——》New text file line delimiter——》Other:Unix

编码:
使用UTF-8 no BOM。不得使用Windows记事本进行保存,因为记事本是UTF-8 BOM CR+LF。
eclipse——》workspace——》Text file encoding——》Other:UTF-8

缩进:
使用4个空格进行缩进,也可以采用tab进行缩进。有争议无定论,待讨论。
支持4个空格者:
http://www.oracle.com/technetwork/java/codeconventions-136091.html#262

支持2个空格者:
http://google-styleguide.googlecode.com/svn/trunk/cppguide.xml#Spaces_vs._Tabs

支持3、4或8个空格者:
http://www.possibility.com/Cpp/CppCodingStandard.html#indent

要保证缩进正确,如果使用4个空格,一定不要出现5个空格或者11个空格。
eclipse——》General——》Editor——》Text Editors——》show whitespace characters
vim ~/.vimrc
set expandtab
set softtabstop=4
set shiftwidth=4

HTTP协议缓存:
文章使用Last Modified表示最后修改时间,不禁止缓存。
header(‘Last Modified:Sat, 30 Oct 2010 13:21:21 GMT’);
需要用户登录的页面,禁止缓存。
header(‘Cache-Control:max-age=0’);
header(‘Cache-Control:private’);

HTTP协议编码与mime:
web输出一定要声明编码与mime。charset与分号之间要有一个空格。小写utf-8还是大写UTF-8,尚未找到文档,待调研。
比如
header(‘Content-Type:application/json; charset=UTF-8’);
header(‘Content-Type:application/xml; charset=UTF-8’);
header(‘Content-Type:application/xhtml+xml; charset=UTF-8’);
header(‘Content-Type:text/plain; charset=UTF-8’);
header(‘Content-Type:text/html; charset=UTF-8’);

专有名词大小写:
在类、函数、文件名、目录名等各种地方,不特殊对待专有名词,不采用全大写。
原因:专有名词难以界定,比如HTML、CSS、CRUD。而且全大写导致与驼峰冲突,比如页面助手类,全大写是HTMLHelper,不如HtmlHelper。
支持不特殊处理:
HTML是专有名词,但mime中就使用Content-Type:text/html,而不是text/HTML。
例子:
采用UserDb.php,而不是UserDB.php。

[转载]判断一个点是否在指定三角形内(1)

mikel阅读(933)

[转载]判断一个点是否在指定三角形内(1) – flyinghearts – 博客园.

问题:判断点P是否在三角形ABC

判断一个点是否在在三角形内,最常用的两种方法:面积法、向量同向法。算法虽然很简单,但要做到高效却不容易,要考虑到二维、三维的区别,还要考虑到坐标是用浮点数还是用整数来表示。

在二维平面上,问题相对简单,一般只需6次乘法计算。但在三维平面时问题要复杂很多,在网上看到的算法,一般都需要30次乘法计算(如果已知点P在平面ABC上,则需21次)。实际上,在三维坐标系下,可以做到增加1次比较,将乘法计算降到13次(如果点P在平面ABC上,则最多只要8次乘法计算)。

最常用的两种方法:面积法和向量同向法本质上是等价的。

向量同向法:若点P在三角形内,则三个向量:ab × apap × acpb × pc平行同向(它们也与向量ab × ac平行同向),由于这三个向量均有可能为0,直接判断它们平行同向相当麻烦,但考虑到ab × ac不可能为0,直接判断“向量:ab × apap × acpb × pc均与ab × ac平行同向”反而更简单。

面积法:当点p在三角形abc内时,4个三角形的面积满足: abc = abp + apc + pbc

对面积的计算,可以通过向量的向量积计算得到: 面积 abc = |ab × ac| / 2

表面上,要计算4个三角形的面积,但根据下面的公式:

ap × ap = 0, pb × pc = (ab – ap) × (ac – ap) = ab × ac – ab × ap – ap × ac

可以少算一次矢量积

公式: |ab × ac| = |ab × ap| + |ap × ac| + |(ab × ac – ab × ap – ap × ac)|

对任意向量abc |a + b + c| = |a| + |b| + |c| <==> 向量abc 平行同向

因而,面积法和向量同向法本质上是等价的。

下面先讨论二维坐标系(每个点X,都看作是原点O到该点X的二维向量OX)。

先定义一个二维向量模板:

template<typename T> class Vec2 {

T x, y;

public:

typedef T value_type;

Vec2(T xx = 0, T yy = 0) : x(xx), y(yy) {};

T cross(const Vec2& v) const { return x * v.y y * v.x;} // 矢量积

Vec2 operator-(const Vec2& v) const { return Vec2(x v.x, y v.y); }

};

如果坐标采用浮点数,考虑到浮点数取绝对值方便(有专门的浮点指令),但彼此间比较大小存在误差,采用面积法比较方便:

typedef Vec2<double> Vd2;

bool is_in_triangle(const Vd2& a, const Vd2& b, const Vd2& c, const Vd2& p)

{

Vd2 ab(b a), ac(c a), ap(p a);

//用矢量积计算面积,下面4个值的绝对值,是对应的三角形的面积的两倍,

double abc = ab.cross(ac);

double abp = ab.cross(ap);

double apc = ap.cross(ac);

double pbc = abc abp apc; //等于pb.cross(pc)

//面积法:4个三角形的面积差 等于 0

double delta = fabs(abc) fabs(abp) fabs(apc) fabs(pbc);

return fabs(delta) < DBL_EPSILON;

}

如果坐标采用整数表示,代码相对麻烦点:

typedef Vec2<int> Vi2;

bool is_in_triangle(const Vi2& a, const Vi2& b, const Vi2& c, const Vi2& p)

{

Vi2 ab(b a), ac(c a), ap(p a);

//用矢量积计算面积,下面4个值的绝对值,是对应的三角形的面积的两倍,

int abc = ab.cross(ac);

int abp = ab.cross(ap);

int apc = ap.cross(ac);

int pbc = abc abp apc; //等于pb.cross(pc)

//方法1: 面积法:4个三角形的面积差 等于 0

return abs(abc) == abs(abp) + abs(apc) + abs(pbc)

//方法2: 矢量同向法: abp apc pbc 均与 abc 同向:

if (abc < 0) { abp = abp; apc = apc; pbc = pbc; }

return (abp >= 0) & (apc >= 0) & (pbc >= 0);

}

方法1:要计算4次绝对值,看似需要4次条件跳转,但主流的编译器,都能采用位运算直接计算绝对值(注意:GCC需要加额外的参数),不需要任何条件跳转。

方法2:比方法1指令少,但多1次条件跳转。

哪种方法效率较高,与编译器生成的具体代码有关。

上面代码中,可采用的两种优化方法:

① 对整数x取绝对值,可以利用位运算:

y = 0 (当x >= 0

= -1 (当x < 0

(编译器可以利用cdqsar等指令直接由x计算出y值)

abs(x)  =  (x xor y) – y

或: = (x + y) xor y

或: = x – (2 * x & y)

对整数abc a >= 0 && b >= 0 && c >= 0 等价于

(a >= 0) & (b >= 0) & (c >= 0) 等价于:

(a | b | c) >= 0

为避免编译器没有进行相关优化,直接手动优化,可得:

inline int chg_sign(int x, int sign) //sign只能取0或-1,函数分别返回x、-x

{

return (x + sign) ^ sign;

//return (x ^ sign) – sign;

}

bool is_in_triangle(const Vi2& a, const Vi2& b, const Vi2& c, const Vi2& p)

{

Vi2 ab(b a), ac(c a), ap(p a);

//用矢量积计算面积,下面4个值的绝对值,是对应的三角形的面积的两倍,

int abc = ab.cross(ac);

int abp = ab.cross(ap);

int apc = ap.cross(ac);

int pbc = abc abp apc; //等于pb.cross(pc)

//方法3: 矢量同向法(优化版)

const int sign = (abc >= 0) 1;

//const int sign = abc >> (sizeof(abc) * CHAR_BIT – 1);

return (chg_sign(abp, sign) | chg_sign(apc, sign) | chg_sign(pbc, sign)) >= 0;

}

作者: flyinghearts
出处: http://www.cnblogs.com/flyinghearts/
本文采用知识共享署名-非商业性使用-相同方式共享 2.5 中国大陆许可协议进行许可,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

[转载]分享E-WebTemplates国外精美网页模板(FLASH+PSD源文件+HTML)(1~40)

mikel阅读(1241)

[转载]【网页设计】分享E-WebTemplates国外精美网页模板(FLASH+PSD源文件+HTML)(1~40) – 悠游人生 – 博客园.

都是国外E-WebTemplates网站上的网页模板,自己用采集程序把下载链接采集下来的。大概一共159套,样式都很漂亮,每套都含有PSD源文件和生成的HTML。

已经看过的童鞋请54,咔咔。。。

web page template Html website template
下载地址 free web design templates
cool web page design templates
free web page template HTML website template
下载地址 free web design templates
cool web page design templates
free html web template free html website template
下载地址 free web design templates
cool web page design templates
free HTML web template free html website template
下载地址 free web design templates
cool web page design templates
free web template free website design template
下载地址 free web design templates
cool web page design templates
free website template free professional web template
下载地址 free web design templates
cool web page design templates
free professional template free professional web template
下载地址 free web design templates
cool web page design templates
free professional design template HTML website template
下载地址 free web design templates
cool web page design templates
free HTML web page template Html website template
下载地址 free web design templates
cool web page design templates
free professional web template free pro website template
下载地址 free web design templates
cool web page design templates
Professional website templates Professional web template
下载地址 free web design templates
cool web page design templates
free Professional html template free Professional web page template
下载地址 free web design templates
cool web page design templates
free professional web template free professional website template
下载地址 free web design templates
cool web page design templates
free HTML professional template free professional html template
下载地址 free web design templates
cool web page design templates
professional web template free professional web template
下载地址 free web design templates
cool web page design templates
free professional html template free pro web design template
下载地址 free web design templates
cool web page design templates
professional web page template free html web template
下载地址 free web design templates
cool web page design templates
free web page template PRO website template
下载地址 free web design templates
cool web page design templates
free photoshop website template free photoshop web template
下载地址 free web design templates
cool web page design templates
free PSD web page template free photoshop web templates
下载地址 free web design templates
cool web page design templates
free PSD web page template free photoshop website template
下载地址 free web design templates
cool web page design templates
photoshop web page templates free PSD web template
下载地址 free web design templates
cool web page design templates
free photoshop website template free photoshop website template
下载地址 free web design templates
cool web page design templates
free PSD template free web page template
下载地址 free web design templates
cool web page design templates
free PSD template free web page template
下载地址 free web design templates
cool web page design templates
free photoshop template free photoshop website templates
下载地址 free web design templates
cool web page design templates
free PSD website template free Photoshop web page Template
下载地址 free web design templates
cool web page design templates
free photoshop HTML template free HTML photoshop template
下载地址 free web design templates
cool web page design templates
free PSD template free HTML toys template
下载地址 free web design templates
cool web page design templates
free photoshop web template free PSD templates
下载地址 free web design templates
cool web page design templates

[转载]ActionScript3.0中未公开的addFrameScript方法

mikel阅读(1346)

[转载]ActionScript3.0中未公开的addFrameScript方法 – 小枫_AS3.0 – 博客园.

addFrameScript的功能是允许你指定在flash player播放头播放到指定的位置时触发事件.这个方法可以接收四个参数,但常用的只有前两个,关键的意思就是:表示执行到指定帧后调用所指定的函数.

语法:
MovieClip.addFrameScript(frame:uint,notify:Function)

注:frame指的是帧的索引,默认是0,也就是说第一帧是0; notify是指调用函数,也就是说为某一帧添加一个函数;

例:

addFrameScript(0,frame1);

function frame1(){

stop();

trace(“这是第一帧”);

}

以上是一个简单的例子,告诉第一帧,停止,并且trace一句话!

实际上addFrameScript()还可以接收任意多组的参数.如下:

MovieClip.addFrameScript(0,frame1Method, 1,frame2Method, 2,frame3Method);
也就是你说可以同时指定多组触发事件,在1,2,3帧上同时指定触发的动作,如果有不止一个动作事件指定在相同的一个帧上,那么,只有后者的动作会被触发.

真是太帅了,有了这个方法,我们就可以动态的为每个帧随意指定要执行的代码了!

另外,如果要移除动作,也非常方便,如:

MovieClip.addFrameScript(0,null)

MovieClip.addFrameScript(9,output,false,false);

据说,As3.0的addFrameScript()方法并没有公开,但是却非常好用!

[转载].NET MVC3 中扩展一个HtmlHelper方法CheckBoxList

mikel阅读(1080)

[转载].NET MVC3 中扩展一个HtmlHelper方法CheckBoxList – 单程列车 – 博客园.

MVC中有DropDownList方法,挺好用,可是最常用的需求,一组checkboxlist咋没个类似方法呢?郁闷之余,自己做一个吧,直接上代码,呵呵

public static MvcHtmlString CheckBoxList(this HtmlHelper helper, string name, IEnumerable
selectList)
{
return CheckBoxList(helper, name, selectList, new { });
}
public static MvcHtmlString CheckBoxList(this HtmlHelper helper, string name, IEnumerable
selectList, object htmlAttributes)
{

IDictionary HtmlAttributes = HtmlHelper.AnonymousObjectToHtmlAttributes(htmlAttributes);

HashSet set = new HashSet();
List
list = new List
();
string selectedValues = Convert.ToString((selectList as SelectList).SelectedValue);
if (!string.IsNullOrEmpty(selectedValues))
{
if (selectedValues.Contains(","))
{
string[] tempStr = selectedValues.Split(',');
for (int i = 0; i &lt; tempStr.Length; i++)
{
set.Add(tempStr[i]);
}

}
else
{
set.Add(selectedValues);
}
}

foreach (SelectListItem item in selectList)
{
item.Selected = (item.Value != null) ? set.Contains(item.Value) : set.Contains(item.Text);
list.Add(item);
}
selectList = list;

HtmlAttributes.Add("type", "checkbox");
HtmlAttributes.Add("id", name);
HtmlAttributes.Add("name", name);
HtmlAttributes.Add("style", "margin:0 0 0 10px;line-height:30px; vertical-align:-8px;border:none;");

StringBuilder stringBuilder = new StringBuilder();

foreach (SelectListItem selectItem in selectList)
{
IDictionary newHtmlAttributes = HtmlAttributes.DeepCopy();
newHtmlAttributes.Add("value", selectItem.Value);
if(selectItem.Selected)
{
newHtmlAttributes.Add("checked", "checked");
}

TagBuilder tagBuilder = new TagBuilder("input");
tagBuilder.MergeAttributes(newHtmlAttributes);
string inputAllHtml= tagBuilder.ToString(TagRenderMode.SelfClosing);
stringBuilder.AppendFormat(@"<label> {0}  {1}</label>",
inputAllHtml, selectItem.Text);
}
return MvcHtmlString.Create(stringBuilder.ToString());

}
private static IDictionary DeepCopy(this IDictionary ht)
{
Dictionary _ht=new Dictionary();

foreach (var p in ht)
{
_ht.Add(p.Key, p.Value);
}
return _ht;
}

可以直接拿去用

生成的每一个checkbox外部都有一个label,感觉不错,不喜欢可以去掉,还有一个 HtmlAttributes.Add(“style”, “margin:0 0 0 10px;line-height:30px; vertical-align:-8px;border:none;”); 是为了让显示更好看的,如果在你的样式下面位置不好看你可以把这行去掉

[转载]发布新浪微博API SDK,附Demo地址!!

mikel阅读(991)

[转载]发布新浪微博API SDK,附Demo地址!! – DreamTrue – 博客园.

新浪微博没有发布官方的C#版SDK,为了弥补这个遗憾,只好自己动手丰衣足食啦

本次发布的SDK,实现了图片上传功能,支持中文和特殊标点符号,

并且采用了外观模式,隐藏底层实现,开发者直接调用SDK方法即可,现有功能经测试全部通过。

不过由于精力有限,SDK未能涉及到全部的API,如果大家觉得不错,可联系我共同完善。

SDK SVN地址:
https://subversion.assembla.com/svn/easyportal-web-weibo/
SDK Demo地址:
http://demo.zhanghq.net/sinaweibo

获取新浪所有表情截图

上传微博截图:

http://demo.zhanghq.net/sinaweibo/Message/Upload

上传微博前请先连接到新浪

SDK里的演示站点,需要安装MVC3

PS:新浪API的开发过程比较坑爹,很多API文档跟实际差别比较大,不少状况只能通过不停调试解决,弄了将近半个月,总算可以在项目中用了,:)

[转载]JavaScript上传头像截图,仿flash

mikel阅读(1409)

[转载]【原创】JS上传头像,仿flash – loogn – 博客园.

flash上传头像多不胜举了,可JS仿flash的见的不多,也是工作需要,就试着写写看!不料,设想还真的可行

先看两个效果图(在FF下):

1,选择上传图片区域

2,上传后图片到img标签

下面是我整个的思路:

一、用ajaxFileUpload.js异步上传图片。这个不用多说了,挺简单的东西。

二、div拖拽用JQuery-ui。这个也不多说了。

三、上传过图片的处理。

编辑容器是300*300,如果图片不在300*300之内,这里会生成一个maxHeight=300,maxWidth=300的缩略图,

用于设置编辑容器的背景,如果原文件为123.jpg,这里生成的文件为123.jpg.view.jpg,当然,文件123.jpg.view.jpg可能不会生成!

返回数据为{ result:” + result + “,size:” + size + “,msg:\”” + msg + “\”,w:” + ww + “,h:” + hh + “}”。

result 是1或0,表是否上传成功,

size 是缩放比率,默认为1,有缩略图时为缩小的倍数,如果缩略到原来的3/4,size为0.75

msg 如果result=1,msg是文件地址,如果result=0,msg是错误信息

w,h是原图的宽高,如果有缩略图,则为缩略图的宽高。

四、选择图片区域

头像目标大小为175*175,编辑时在右边显示。目标头像要随选区的移动而移动,这个可以定位背景要实现,但它还要随选区的大小变化而变化,这个用背景恐怕是难以实现了吧!

反正我是不知道怎么做,所以这里选择用真正的图片,可图片从哪来呢?从服务端来!想必图片验证码大家都熟悉,这里的真正图片就是这样得来的。在选区drag和resize后(当然也可

在进行时请求,效果更动态,不过嘿嘿…),即 stop时要向服务器请求显示的图片,请求数据要包含size,即上面得到的0.75,还有选区的位置和大小。

到服务器后你会发现选区的位置(x,y)和大小(w,h)是针对缩略图的,这时 size就有用了,由size缩略,由size还原,真是解玲还需系玲人啊,把x,y,w,h都除以size,得到的位置和大小便对应到原图上了。于是 乎,剪切吧!返回吧!好,剪切,返@#!,晕,这里还不能返回呢!因为剪切过后你也不知道大小是不是符合

我们的目标大小(175*175)啊! 所以这里不能急着返回给用户看,还要做最后的包装,把大的压缩,把小的放大,统统成175*175达标后才可返回。于是,

页面上就可以看到我们选区的头像了~

五、确定保存

这里逻辑就简单多了,选择图片区域时我们生成了图片输出到页面,这里我们可以用同样的方法生成图片,保存就OK了,这里还有一个清理操作,

最终的123.jpg是没用的,123.jpg.view.jpg也是没用的,有用的是我们借助123.jpg.view.jpg从132.jpg中抽离出来的456.jpg!

六、整个功能放在一个html里,哪里用,就load到哪里!

js:
$(function() {
$("#divUp").load("uploadAvatar.htm?n=" + Math.random());
})
function OnAvatarUploaded(file) {
$("#img").attr("src", file + "?n=" + Math.random()); //防止缓存
}

html:
<div style="height: 500px; clear: both; margin: 80px auto; width: 800px;">
<div style="width: 175px; height: 175px; float: left; border: 1px solid #cccccc;"><img id="img" style="width: 175px; height: 175px;" alt="" /></div>
<div id="divUp" style="width: 520px; float: left; margin-left: 20px;"></div>
</div>

*******************

总体思路及步骤到这就完了。

功能没有flash的强大,但一般的上传头像也可以满足了,想生成头像缩略图也很简单,下面会附源码,看一下就知道在哪加了。

handler里代码有点乱,没有整理,不好意思啦!

下载

[转载]国产开源敏捷工具-fKanban

mikel阅读(965)

[转载]国产开源敏捷工具-fKanban – kkun – 博客园.

OK,敏捷软件开发中看板的功能不言而喻,

在此之前在国外找了N多类似的工具,要么收费,要么太过简陋,要么,嗯,插入一句,本人多少有些视觉控,太丑
在找了两天左右,对比了N多看板,SCRUM管理工具后,决定,静下心来,这东西自己搞!

再插一句:之前用的那个Scrum Dashboard还是蛮不错滴,说它不错是因为它与TFS集成了

自己搞,大概经过也许也值得借鉴下,一开始为了练手使用了HTML5 离线存储技术,参考这篇小文:HTML5 离线存储之Web SQL

用户体验超级好,另存为页面也能使用!不用登录,不用部署,打开就用!

对于个人使用来说,要求相当低调,只要你能打开页面,就可以使用,完全没有任何限制

但缺点也是非常明显,那就是在公司设置了任务后,到家里就看不到了!啊??不能同步!离线存储么…

后来想过同步技术,最后还是放弃了,太过复杂,需求同SVN,TFS源码管理需求!双向同步,冲突处理,自动合并,阿弥陀佛!

还有一缺点,在团队中无法共享!只能大家伙围观我一人的屏幕,然后自己玩,别人看,不爽不爽!

终究还是要联机的~又改回联机的看板了,这次谁都可以看了,设计思路也简单的要命~

完全没有会员注册,登录,权限管理这些东东,我承认这些是需要的!慢慢搞嘛,实事上已经在规划当中

现在使用仅要求部署在支持MVC3的服务器上,然后打开非IE浏览器,可以用了~默认使用匿名数据库,默认滴,

可以在设置里设置数据库名称,猛击保存则会在服务器端创建一个以此命名,以.database结尾的SQLITE数据库!

即每个人的SCRUM都是一个单独的数据库进行管理~设置一次后就再不用管了~这个数据库名会存储在本地localStorage里~
页面参考了IPAD上一个的KANBAN软件的界面,还是很漂亮滴~

给我灵感的IPAD看板界面欣赏:

clip_image002

OK,谢谢您让我说了这么多,大概看一眼长什么模样,希饭就拿去用~最好别找砖~
东东很简单,没什么含金量,但基于使用的目的,我想它会有存在的价值滴,分享出来~

我都不知道MIT是什么样的开源协议,随便选了一项目就开源了~地址:http://fKanban.codeplex.com

有名字才好出来见人~fkanban,不难听吧?其实不咋滴,f = Free,就它了,

起名字是个大活,不费脑细胞了,反正不想叫狗蛋类,不然语文老师会杀了我

山寨的看板界面欣赏:

看板 Kanban Online

抄袭?!有木有?有木有?…

——-
后记:最好下载源码,编译部署,注意SQLITE X64或者X32版本不同,其它还依赖MVC3,没有了
建议您下载源码不是说代码写得有多漂亮,而是那个1.0版本有BUG~

本文版权与博客园共有,转载请注明出处

[转载]30佳精美的免费Flash网站模板下载(附带源文件)

mikel阅读(950)

[转载]30佳精美的免费Flash网站模板下载(附带源文件) – 梦想天空(山边小溪) – 博客园.

对于网页设计师来说,Flash非常有用,是网页重要的组成部分。本文收集了30佳精美的免费Flash网站模板,附带FLA源文件,有免费作品集模板,摄影模板,个人模板等,都有可动态配置的Flash画廊,个人和商业使用都免费,赶紧挑喜欢的下载吧。

214 accordion

Free Flash Website Templates with .FLA Source Files

演示下载

Bokeh

Free Flash Website Templates with .FLA Source Files

演示下载

Reflection

Free Flash Website Templates with .FLA Source Files

演示下载

Fisheye Image Gallery

Free Flash Website Templates with .FLA Source Files

演示下载

Photographer Field

Free Flash Website Templates with .FLA Source Files

演示下载

Photographer Minimal

Free Flash Website Templates with .FLA Source Files

演示下载

indie boy yellowish

Free Flash Website Templates with .FLA Source Files

演示下载

black dirty grid

Free Flash Website Templates with .FLA Source Files

演示下载

Fruit Co.

Free Flash Website Templates with .FLA Source Files

演示下载

Foodart

Free Flash Website Templates with .FLA Source Files

演示下载

Foodart – 3 columns

Free Flash Website Templates with .FLA Source Files

演示下载

Portoflio Designer Toy white Rainbow

Free Flash Website Templates with .FLA Source Files

演示下载

Portolfio Art white Pixel Pattern

Free Flash Website Templates with .FLA Source Files

演示下载

portfolio illustartor black

Free Flash Website Templates with .FLA Source Files

演示下载

Portfolio Minimal Splash white

Free Flash Website Templates with .FLA Source Files

演示下载

personal flash template colorful lights

Free Flash Website Templates with .FLA Source Files

演示下载

Art Sketch Yellow

Free Flash Website Templates with .FLA Source Files

演示下载

Bio Cyberpunk

Free Flash Website Templates with .FLA Source Files

演示下载

free real estate template minimal

Free Flash Website Templates with .FLA Source Files

演示下载

real estate simple black

Free Flash Website Templates with .FLA Source Files

演示下载

Classic Real Estate

Free Flash Website Templates with .FLA Source Files

演示下载

architect dream portfolio

Free Flash Website Templates with .FLA Source Files

演示下载

hotel divided

Free Flash Website Templates with .FLA Source Files

演示下载

Architect Company

Free Flash Website Templates with .FLA Source Files

演示下载

Interior Designer Black

Free Flash Website Templates with .FLA Source Files

演示下载

Music Allure

Free Flash Website Templates with .FLA Source Files

演示下载

Music Red Wood

Free Flash Website Templates with .FLA Source Files

演示下载

Music Dragonfly Gradient

Free Flash Website Templates with .FLA Source Files

演示下载

v-shape gallery

Free Flash Website Templates with .FLA Source Files

演示下载

Nature

Free Flash Website Templates with .FLA Source Files

演示下载

Free Flash Video Player

Free Flash Website Templates with .FLA Source Files

演示下载

Mini Red

Free Flash Website Templates with .FLA Source Files

演示下载