Счетчик зеркального отражения JavaScript

Немного сложно понять, в чем проблема на самом деле. Clipper (также при использовании SimplifyPolygons или SimplifyPolygon) может создавать только слабо простые многоугольники, что означает, что могут быть псевдопублицированные точки: хотя последовательные координаты гарантируются не идентичными, некоторые из следующих точек могут иметь одну и ту же координату. Также координата может быть на линии между двумя точками.

После упрощения (или любой другой логической операции) вы можете выполнить шаг очистки, используя смещение с небольшим отрицательным значением: https://sourceforge.net/p/jsclipper/wiki/documentation/#clipperlibclipperoffsetexecute .

Это, возможно, удаляет все псевдопублицированные точки.

Я также сделал поплавковую версию Clipper ( http://jsclipper.sourceforge.net/6.4.2.2_fpoint/ ). Он тщательно протестирован, но поскольку Ангус Джонсон, автор оригинальной C # Clipper (с которого портирована JS-версия), считает, что использование float вызывает проблемы с устойчивостью, хотя, по моим тестам, таких проблем нет, оригинальный C # float версия не существует. Версия с плавающей точкой проще в использовании, и вы можете попробовать небольшое отрицательное смещение: например. -0,001 или -0,01.

Вы также можете попробовать PolyTree или ExPolygons ( https://sourceforge.net/p/jsclipper/wiki/ExPolygons%20and%20PolyTree%206/ ). ExPolygons может использоваться для получения отверстий и контуров, а PolyTree может использоваться для получения полного родителя-дочернего отношения отверстий и контуров.

1117] Последнее средство - функция сломанной ручки. Он обнаруживает все псевдодублирующиеся точки и создает для них эффект разбитого пера, чтобы в результате не было дубликатов. Прикрепленные изображения показывают, что означает этот эффект, используя большое значение nib-effect, чтобы сделать эффект более понятным. Триангуляция многоугольника Three.js не удалась в псевдопубликатных точках . Существует обсуждение https://github.com/mrdoob/three.js/issues/3386 этой темы.

enter image description here enter image description here

  // Make polygons to simple by making "a broken pen tip" effect on each semi-adjacent (duplicate) vertex
  // ORIGPOLY can be a contour
  // or exPolygon structure

  function BreakPenNibs(ORIGPOLY, dist, scale)
  {
    if (!dist || dist < 0) return;
    var sqrt = Math.sqrt;
    var allpoints = {}, point = {};
    var key = "";
    var currX = 0.0,
      currY = 0.0;
    var prevX = 0.0,
      prevY = 0.0;
    var nextX = 0.0,
      nextY;
    var x = 0.0,
      y = 0.0,
      length = 0.0,
      i = 0,
      duplcount = 0,
      j = 0;
    var prev_i = 0,
      next_i = 0,
      last_i;
    var extra_vertices = new Array(100),
      moved_vertices = new Array(100);

    // Get first all duplicates
    var duplicates = new Array(100),
      indexi = "",
      indexstr = "",
      arraystr = "",
      polys, outer, holes;
    if (ORIGPOLY instanceof Array) 
    {
      outer = ORIGPOLY;
    }
    else if (ORIGPOLY.outer instanceof Array) 
    {
      outer = ORIGPOLY.outer;
    }

      else return;
    if (ORIGPOLY.holes instanceof Array) holes = ORIGPOLY.holes;
    else holes = [];
    polys = [outer].concat(holes);
    var polys_length = polys.length;
    // Get first max lenght of arrays
    var max_index_len = 0;
    var arr_len;
    i = polys_length;
    while (i--)
    {
      arr_len = polys[i].length;
      if (arr_len > max_index_len) max_index_len = arr_len;
    }
    max_index_len = max_index_len.toString().length;
    var max_polys_length = polys_length.toString().length;
    var poly;
    j = polys_length;
    var scaling = scale/10;
    while (j--)
    {
      poly = polys[j];
      ilen = poly.length;
      i = ilen;
      while (i--)
      {
        point = poly[i];
        //key = Math.round(point.X) + ":" + Math.round(point.Y);
        
        key = (Math.round(point.X / scaling) * scaling)
        + ":" + (Math.round(point.Y / scaling) * scaling);
        indexi = allpoints[key];
        if (typeof (indexi) != "undefined")
        {
          // first found duplicate
          duplicates[duplcount] = indexi;
          duplcount++;

          arraystr = j.toString();
          while (arraystr.length < max_polys_length) arraystr = "0" + arraystr;
          indexstr = i.toString();
          while (indexstr.length < max_index_len) indexstr = "0" + indexstr;
          duplicates[duplcount] = arraystr + "." + indexstr;
          duplcount++;
        }
        arraystr = j.toString();
        while (arraystr.length < max_polys_length) arraystr = "0" + arraystr;
        indexstr = i.toString();
        while (indexstr.length < max_index_len) indexstr = "0" + indexstr;

        allpoints[key] = arraystr + "." + indexstr;
      }
    }
    if (!duplcount) return;

    duplicates.length = duplcount;
    duplicates.sort();
    //console.log(JSON.stringify(duplicates));

    var splitted, poly_index = 0,
      nth_dupl = 0;
    var prev_poly_index = -1;
    poly_index = 0;
    for (j = 0; j < duplcount; j++)
    {
      splitted = duplicates[j].split(".");

      poly_index = parseInt(splitted[0], 10);
      if (poly_index != prev_poly_index) nth_dupl = 0;
      else nth_dupl++;
      i = parseInt(splitted[1], 10);
      poly = polys[poly_index];
      len = poly.length;
      if (poly[0].X === poly[len - 1].X &&
        poly[0].Y === poly[len - 1].Y)
      {
        last_i = len - 2;
      }
      else
      {
        last_i = len - 1;
      }
      point = poly[i];

      // Calculate "broken pen tip" effect
      // for current point by finding
      // a coordinate at a distance dist
      // along the edge between current and
      // previous point
      // This is inlined to maximize speed
      currX = point.X;
      currY = point.Y;
      if (i === 0) prev_i = last_i; // last element in array
      else prev_i = i - 1;

      prevX = poly[prev_i].X;
      prevY = poly[prev_i].Y;
      
      x=0;y=0;
      if (!point.Collinear)
      {
        length = sqrt((-currX + prevX) * (-currX + prevX) + (currY - prevY) * (currY - prevY));

//console.log(length);
        x = currX - (dist * (currX - prevX)) / length;
        y = currY - (dist * (currY - prevY)) / length;
      }
        // save the found (calculated) point
        moved_vertices[j] = {
          X: x,
          Y: y,
          Collinear:point.Collinear,
          index: i,
          poly_index: poly_index
        };
      
      // "broken nib effect" for next point also
      if (i == len - 1) next_i = 0;
      else next_i = i + 1;
      nextX = poly[next_i].X;
      nextY = poly[next_i].Y;
      x=0;y=0;
      if (!point.Collinear)
      {
      length = sqrt((-currX + nextX) * (-currX + nextX) + (currY - nextY) * (currY - nextY));
      x = currX - (dist * (currX - nextX)) / length;
      y = currY - (dist * (currY - nextY)) / length;
      }
        // save the found (calculated) point
      extra_vertices[j] = {
        X: x,
        Y: y,
        Collinear:point.Collinear,
        index: i + nth_dupl,
        poly_index: poly_index
      };
      prev_poly_index = poly_index;
        
    }

    moved_vertices.length = extra_vertices.length = duplcount;
    //console.log("MOVED:" + JSON.stringify(moved_vertices));
    //console.log("EXTRA:" + JSON.stringify(extra_vertices));

    // Update moved coordinates
    i = duplcount;
    var point2;
    while (i--)
    {
      point = moved_vertices[i];
      x = point.X;
      y = point.Y;
      // Faster than isNaN: http://jsperf.com/isnan-alternatives
      if (x != x || x == Infinity || x == -Infinity) continue;
      if (y != y || y == Infinity || y == -Infinity) continue;
      point2 = polys[point.poly_index][point.index];
      point2.X = point.X;
      point2.Y = point.Y;
      point2.Collinear = point.Collinear;
    }

    // Add an extra vertex
    // This is needed to remain the angle of the next edge
    for (i = 0; i < duplcount; i++)
    {
      point = extra_vertices[i];
      x = point.X;
      y = point.Y;
      // Faster than isNaN: http://jsperf.com/isnan-alternatives
      if (x != x || x == Infinity || x == -Infinity) continue;
      if (y != y || y == Infinity || y == -Infinity) continue;
      polys[point.poly_index].splice(point.index + 1, 0,
      {
        X: point.X,
        Y: point.Y,
        Collinear: point.Collinear
      });
    }
    
    // Remove collinear points
    // and for some reason coming
    // sequential duplicates
    // TODO: check why seq. duplicates becomes
    j = polys.length;
    var prev_point = null;
    while (j--)
    {
      poly = polys[j];
      ilen = poly.length;
      i = ilen;
      while (i--)
      {
        point = poly[i];
        if(prev_point!=null && point.X == prev_point.X && point.Y == prev_point.Y) poly.splice(i, 1);
        else
        if(point.Collinear) poly.splice(i, 1);
      prev_point = point;
      }
    }
    //console.log(JSON.stringify(polys));
    // because original array is modified, no need to return anything
  }
  
  var BreakPenNipsOfExPolygons = function (exPolygons, dist, scale)
  {
    var i = 0,
      j = 0,
      ilen = exPolygons.length,
      jlen = 0;
    for (; i < ilen; i++)
    {
      //if(i!=4) continue;
      BreakPenNibs(exPolygons[i], dist, scale);
    }
  };

[1119 ]

17
задан Kevin Vermeer 29 November 2011 в 17:37
поделиться

1 ответ

They're using a combination of CSS and JavaScript. The flip animation is powered by a CSS Sprite-like technique.

First of all, they have a very tall image called filmstrip.png that contains every flip "state" for each number (0 to 9; have a look at a scaled-down detail and you'll see what I mean).

Then, in the HTML, each digit is made up of three nested elements:

  • The first is a container element, which has its width and height set to the dimensions of a single flip "state", and its overflow set to hidden. This element is positioned relatively.

  • The second element is positioned absolutely (and because the first element is positioned relatively, this second element is positioned absolutely relative to the first element).

  • The third element has its background-image set to filmstrip.png, and its width and height set to the dimensions of this image.

The JavaScript then seems to rapidly change the top property of the second element, causing different parts of filmstrip.png to be exposed one after another, thus resulting in a flip animation.

Steve

25
ответ дан 30 November 2019 в 10:46
поделиться
Другие вопросы по тегам:

Похожие вопросы: