Thursday, October 9, 2008

Improve mapidev

In order to gain more visibility and gain more readers, i'm thinking about to switch my language to english.

Hope this could be useful, and most of all will helps to let more people to know what i write.

Numeri di telefono on the fly

NB: Italian only, this script is useful for italian only readers. This script recive as input an italian phone number and give its holder as output.

In questo post vediamo come ricavere on the fly informazioni su intestatari di numeri di telefono.

Si tratta di due scritp pensati per essere eseguiti direttamente dall'interprete php.

Può essere utile in ufficio sapere in anticipo chi sta telefonando e consultare il sito delle pagine bianche può risultare un dispendio di tempo. Questi script si occupano di interrogare il sito delle pagine bianche fornendo un numero di telefono; se questo è presente nell'elenco verrà visualizzato nella shell evitando i tempi di attesa del browser.

Gli script si servono della libreria curl, quindi è necessario averla propriamente installata sulla propria macchina.

Grazie alla curl, lo script interroga lo script delle pagine bianche incaricato di restituire il numero di telefono; ricevono in risposta il codice html che verrebbe normalmente visualizzato nel broswer. A questo punto il comportamento degli script è differente. Uno ricava i dati servendosi di regex; l'altro istanzia due oggetti: un DOMDocument e un DOMXPath; i dati vengono ricavati con query xpath.

La pagina di risposta delle pagine bianche formatta i dati all'interno di tag che (salvo grosse modifiche alla pagina!!) sono sempre gli stessi;, in questo modo è possibile ricavare i dati. Vediamo il codice degli script, tenendo presente che grosso modo la performance è praticamente identica.

pagine_bianche_regex.php

if($argc != 2) die("Parametro necessario: Numero di telefono\nNon devono essere presenti spazi all'interno del numero.\n\n");
$tel = $argv[1];
$url = "http://www.paginebianche.it/execute.cgi?btt=1&ts=106&cb=8&l=it&mr=10&rk=&om=&qs=$tel";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$out = curl_exec($ch);
$m = array();
$test = preg_match('/<h3 class\=\"org\">([a-zA-z\s]+)<\/h3>/',$out, $m);
echo "\n\t$tel";
if($test == 0) die("\n\tNumero Non Trovato\n\n");
echo "\n\tIntestatario/a: ".$m[1]."\n";
preg_match('/<span class="postal\-code">([0-9]+)<\/span>/', $out, $m);
echo "\tIndirizzo: ".$m[1]." ";
preg_match('/<span class="locality">([a-zA-z\s]+)<\/span>/', $out, $m);
echo $m[1]." ";
preg_match('/<span class="region">\(([A-Z]{2})\)<\/span>/', $out, $m);
echo $m[1]." ";
preg_match('/<span class="street\-address">([A-Za-z\s0-9,]+)<\/span>/', $out, $m);
echo $m[1]."\n\n";
curl_close($ch);

pagine_bianche_xpath.php

if($argc != 2) die("Parametro necessario: Numero di telefono\nNon devono essere presenti spazi all'interno del numero.\n\n");
$tel = $argv[1];
$url = "http://www.paginebianche.it/execute.cgi?btt=1&ts=106&cb=8&l=it&mr=10&rk=&om=&qs=$tel";
$ch = curl_init();
curl_setopt($ch, CURLOPT_URL, $url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$out = curl_exec($ch);
$html = DOMDocument::loadHTML($out);
$xp = new DOMXpath($html);
echo "\n\t$tel";
$data = $xp->query("//h3[@class=\"org\"]");
if($data->length == 0) exit("\n\tNumero Non Trovato\n\n");
echo "\n\tIntestatario/a: ".$data->item(0)->nodeValue;
$data = $xp->query("//span[@class=\"postal-code\"]");
echo "\n\tIndirizzo: ".$data->item(0)->nodeValue;
$data = $xp->query("//span[@class=\"locality\"]");
echo " ".$data->item(0)->nodeValue;
$data = $xp->query("//span[@class=\"region\"]");
echo " ".$data->item(0)->nodeValue;
$data = $xp->query("//span[@class=\"street-address\"]");
echo " ".$data->item(0)->nodeValue."\n\n";
curl_close($ch);

Wednesday, October 8, 2008

A little help

Im gonna show you a simple function in php that will help you to generate the easiest insert mysql query (yet another...).

I use it in a personal web application, someone could find it useful too. It's just an alpha definition, but i really doubt to bring new modifications.

Context:

This function have been called in a asynchronous way from javascript (by XHR), so the parameters comes from $_GET array.

The function accept these parameters as input:

  • $table: name of the table the query concern;
  • $get_unset: ignored $_GET array's indexes that don't need to build the query;
  • $auto_id: this boolean flag is set to true if in that table exist an index called id which is autoincrement

It is clear the follow adaptations should be take into consideration: add an array parameter as a substitute of $_GET array, so $unset_get could be remove from the parameters list. 

Here the code:

function generate_query($table, $get_unset = null, $auto_id = true) {
  $field = "";
  $value = "";
  foreach($get_unset as $gu) unset($_GET[$gu]);
  $query = "INSERT INTO $table(";
  foreach($_GET as $k => $v) {
    $field .= "$k, ";
    $value .= "'$v', ";
  }
  if($auto_id) $query .= "id, ";
  $query .= substr($field, 0, -1).") VALUES(";
  if($auto_id) $query.="null, ";
  $query .= substr($value, 0, -1).")";
  return $query;
}

Tuesday, October 7, 2008

Xiaolin Wu look like circle

Xiaolin Wu had implement an algorithm to draw fast antialiased lines and circles.

In this post i will consider the circle.

His idea is based on draw the points next to the real circumference. Drawing that points with different intensity so that will be inverse proportion to the distance from the center and the total sum of the intensities will be constant.

The lemma that leads the plot loop is interesting as complex, so i advise you to search others resources, such as "Graphics Gems II" (you can find on google books the description i'm talkin about).

But i thought to change a little Xiaolin Wu's algorithm in this way:

  • I first plot the original circle;
  • I add two points with different intensity to the nearest real one.
It's a very fast way to draw antialias circle in php.

If you need a fast antialias cirlce to draw in php here's an implementation:

[EDIT : antialias circle full implementation here]

function distance(rad, y) {
real_point = SQRT ( rad*rad - y*y)
return CEIL(real_point) - real_point
}

i = rad
j = 0
I(i, j) = I
T = 0

WHILE ( i <= j ) { j = j + 1; IF distance(rad, j) > T THEN i = i + 1
I(i, j) = distance(rad, j)
I(i - 1, j) = distance(rad, j)
T = distance(rad, j)
}

How I translate sum pieces in PHP?

function distance($r, $y) {
$real_point = sqrt(pow($r, 2) - pow($y, 2));
return ceil($real_point) - $real_point;
}

function new_color($i) {
return $i * 127;
}

// ... plot loop

$current_distance = distance($r, $y);
$transparency = new_color($current_distance);

$alpha = imagecolorallocatealpha($img, /* colore */, $transparency);
$alpha2 = imagecolorallocatealpha($img, /* colore */, 127 - $transparency);

imagesetpixel($image, $x, $y, imagecolorallocate(/* ... */)); // real point
imagesetpixel($image, $x - 1, $y, $alpha2 ); // nearest, inside
imagesetpixel($image, $x + 1, $y, $alpha ); //nearest, outside

The results, high zoom to recognize how the algorithm works:

Finally the result:

Rectangles

Objective: A function allow to draw a rectangle, so we want to supply top-left corner coordinates, width and height. These variables must be retrive by click-drag-relase mouse.

The most easy way consists by click and drag the mouse in bottom-right direction. Retrive the 4 variables will be easy as follow:

  • x coordinate: first mouse click x coordinate;
  • y coordinate: first mouse click y coordinate;
  • width: mouse relase - x coordinate;
  • height: mouse relase - y coordinate.

Well these easy calculations doesn't work in the follow other instances:

  1. Mouse direction is to top-right (negative height);
  2. Mouse direction is top-left (both widht and height negatives);
  3. Mouse direction is bottom-left (width negative).

It is easy to get real width and height, we only need to take measurements as absolute value; find out the top-left corner coordinates too.

If a size is less then zero, it means that its coordinate will be the same as the mouse coordinate at the relase point.



width = mouse_end_x - mouse_start_x
height = mouse_end_y - mouse_start_y
IF ( width < 0 ) THEN rect_x = mouse_end_x ELSE rect_x = mouse_start_x
IF ( height < 0 ) THEN rect_y = mouse_end_y ELSE rect_y = mouse_start_y
rectangle ( rect_x, rect_y, |width|, |height| )