Как упростить фигуры для триангуляции с помощью three.js и jsclipper

Это зависит от того, что вы пытаетесь сделать.

В настоящее время вы настроили его как нормализованную базу данных, и это нормально, и то, как вы это делаете, уместно.

Однако есть и другие способы сделать это.

У вас может быть коллекция сообщений, в которой есть встроенные комментарии для каждого сообщения со ссылками на пользователей, которые вы можете итеративно запросить. Вы можете сохранить имя пользователя с комментариями, вы можете сохранить их все в одном документе.

Вещь с NoSQL предназначена для гибких схем и очень быстрого чтения и записи. В типичной ферме больших данных база данных является самым узким местом, у вас меньше двигателей баз данных, чем у приложений и передних серверов ... они дороже, но более мощные, а также на жестком диске сравнительно дешево. Нормализация исходит из концепции попытки сэкономить место, но она требует затрат на то, чтобы ваши базы данных выполняли сложные соединения и проверяли целостность отношений, выполняя каскадные операции.

С NoSQL, если вы согласитесь, что избыточность и пространство для хранения не являются проблемами из-за их стоимости (как в процессорное время, необходимое для обновления и затраты на жесткий диск для хранения дополнительных данных), денормализация не является проблемой (для встроенных массивов, которые становятся сотнями тысяч элементов, это может быть проблемой производительности, но большую часть времени это не проблема). Кроме того, у вас будет несколько серверов приложений и интерфейсов для каждого кластера баз данных. Попросите их сделать тяжелый подъем соединений и позволить серверам баз данных придерживаться чтения и записи.

TL; DR: То, что вы делаете, прекрасно, и есть другие способы сделать это. Ознакомьтесь с образцами моделей данных документации mongodb для некоторых замечательных примеров. http://docs.mongodb.org/manual/data-modeling/

0
задан oisi 17 March 2019 в 19:05
поделиться

1 ответ

Немного сложно понять, в чем проблема на самом деле. 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 ]
0
ответ дан Timo Kähkönen 17 March 2019 в 19:05
поделиться
Другие вопросы по тегам:

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