Update ConvertUTF,poly2tri [ci build]

This commit is contained in:
halx99 2021-06-01 11:47:19 +08:00
parent b30a6789b9
commit e0beb6cf27
15 changed files with 354 additions and 353 deletions

View File

@ -30,9 +30,12 @@
#include "ConvertUTF.h"
#include <limits>
using namespace llvm;
NS_CC_BEGIN
namespace StringUtils {
std::string CC_DLL format(const char* format, ...)
{
va_list args;
@ -393,6 +396,24 @@ long getCharacterCountInUTF8String(const std::string& utf8)
return getUTF8StringLength((const UTF8*)utf8.c_str());
}
bool hasNonAsciiUTF8(const char* str, size_t len) {
for (size_t i = 0; i < len;)
{
int numByte = getNumBytesForUTF8(str[i]);
if (numByte > 1)
{ // byte=1, is ascii character
if (isLegalUTF8Sequence((const UTF8*) &str[i], (const UTF8*) &str[i] + numByte))
return true;
}
i += numByte;
}
return false;
}
bool isLegalUTF8String(const char* str, size_t len) {
return ::isLegalUTF8String((const UTF8**)&str, (const UTF8*)str + len);
}
StringUTF8::StringUTF8()
{

View File

@ -213,7 +213,15 @@ CC_DLL unsigned int getIndexOfLastNotChar16(const std::vector<char16_t>& str, ch
*/
CC_DLL std::vector<char16_t> getChar16VectorFromUTF16String(const std::u16string& utf16);
/**
* @brief Whether has non-ascii utf-8 characters
*/
CC_DLL bool hasNonAsciiUTF8(const char* str, size_t len);
/**
* @brief isLegalUTF8String, contains ascii characters
*/
CC_DLL bool isLegalUTF8String(const char* str, size_t len);
/**
* Utf8 sequence

View File

@ -167,7 +167,7 @@ if(BUILD_EXT_EDTAA3FUNC)
endif(BUILD_EXT_EDTAA3FUNC)
if(BUILD_EXT_CONVERTUTF)
add_subdirectory(ConvertUTF)
target_link_libraries(external convertUTF)
target_link_libraries(external ConvertUTF)
endif(BUILD_EXT_CONVERTUTF)
if(BUILD_EXT_POLY2TRI)
add_subdirectory(poly2tri)

View File

@ -1,12 +1,11 @@
set(lib_name convertUTF)
set(lib_name ConvertUTF)
set(target_name ${lib_name})
project(${lib_name})
add_library(${target_name} STATIC
ConvertUTF.c
ConvertUTFWrapper.cpp
ConvertUTF.cpp
)
target_include_directories(${target_name} PUBLIC .)

View File

@ -1,9 +1,8 @@
/*===--- ConvertUTF.c - Universal Character Names conversions ---------------===
*
* The LLVM Compiler Infrastructure
*
* This file is distributed under the University of Illinois Open Source
* License. See LICENSE.TXT for details.
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
* See https://llvm.org/LICENSE.txt for license information.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*
*===------------------------------------------------------------------------=*/
/*
@ -46,13 +45,41 @@
------------------------------------------------------------------------ */
#include "ConvertUTF.h"
#ifdef CVTUTF_DEBUG
#include <stdio.h>
#endif
#include <assert.h>
#include <string.h>
/*
* This code extensively uses fall-through switches.
* Keep the compiler from warning about that.
*/
#if defined(__clang__) && defined(__has_warning)
# if __has_warning("-Wimplicit-fallthrough")
# define ConvertUTF_DISABLE_WARNINGS \
_Pragma("clang diagnostic push") \
_Pragma("clang diagnostic ignored \"-Wimplicit-fallthrough\"")
# define ConvertUTF_RESTORE_WARNINGS \
_Pragma("clang diagnostic pop")
# endif
#elif defined(__GNUC__) && __GNUC__ > 6
# define ConvertUTF_DISABLE_WARNINGS \
_Pragma("GCC diagnostic push") \
_Pragma("GCC diagnostic ignored \"-Wimplicit-fallthrough\"")
# define ConvertUTF_RESTORE_WARNINGS \
_Pragma("GCC diagnostic pop")
#endif
#ifndef ConvertUTF_DISABLE_WARNINGS
# define ConvertUTF_DISABLE_WARNINGS
#endif
#ifndef ConvertUTF_RESTORE_WARNINGS
# define ConvertUTF_RESTORE_WARNINGS
#endif
ConvertUTF_DISABLE_WARNINGS
namespace llvm {
static const int halfShift = 10; /* used for shifting by 10 bits */
@ -63,8 +90,6 @@ static const UTF32 halfMask = 0x3FFUL;
#define UNI_SUR_HIGH_END (UTF32)0xDBFF
#define UNI_SUR_LOW_START (UTF32)0xDC00
#define UNI_SUR_LOW_END (UTF32)0xDFFF
#define false 0
#define true 1
/* --------------------------------------------------------------------- */
@ -394,6 +419,99 @@ Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
/* --------------------------------------------------------------------- */
static unsigned
findMaximalSubpartOfIllFormedUTF8Sequence(const UTF8 *source,
const UTF8 *sourceEnd) {
UTF8 b1, b2, b3;
assert(!isLegalUTF8Sequence(source, sourceEnd));
/*
* Unicode 6.3.0, D93b:
*
* Maximal subpart of an ill-formed subsequence: The longest code unit
* subsequence starting at an unconvertible offset that is either:
* a. the initial subsequence of a well-formed code unit sequence, or
* b. a subsequence of length one.
*/
if (source == sourceEnd)
return 0;
/*
* Perform case analysis. See Unicode 6.3.0, Table 3-7. Well-Formed UTF-8
* Byte Sequences.
*/
b1 = *source;
++source;
if (b1 >= 0xC2 && b1 <= 0xDF) {
/*
* First byte is valid, but we know that this code unit sequence is
* invalid, so the maximal subpart has to end after the first byte.
*/
return 1;
}
if (source == sourceEnd)
return 1;
b2 = *source;
++source;
if (b1 == 0xE0) {
return (b2 >= 0xA0 && b2 <= 0xBF) ? 2 : 1;
}
if (b1 >= 0xE1 && b1 <= 0xEC) {
return (b2 >= 0x80 && b2 <= 0xBF) ? 2 : 1;
}
if (b1 == 0xED) {
return (b2 >= 0x80 && b2 <= 0x9F) ? 2 : 1;
}
if (b1 >= 0xEE && b1 <= 0xEF) {
return (b2 >= 0x80 && b2 <= 0xBF) ? 2 : 1;
}
if (b1 == 0xF0) {
if (b2 >= 0x90 && b2 <= 0xBF) {
if (source == sourceEnd)
return 2;
b3 = *source;
return (b3 >= 0x80 && b3 <= 0xBF) ? 3 : 2;
}
return 1;
}
if (b1 >= 0xF1 && b1 <= 0xF3) {
if (b2 >= 0x80 && b2 <= 0xBF) {
if (source == sourceEnd)
return 2;
b3 = *source;
return (b3 >= 0x80 && b3 <= 0xBF) ? 3 : 2;
}
return 1;
}
if (b1 == 0xF4) {
if (b2 >= 0x80 && b2 <= 0x8F) {
if (source == sourceEnd)
return 2;
b3 = *source;
return (b3 >= 0x80 && b3 <= 0xBF) ? 3 : 2;
}
return 1;
}
assert((b1 >= 0x80 && b1 <= 0xC1) || b1 >= 0xF5);
/*
* There are no valid sequences that start with these bytes. Maximal subpart
* is defined to have length 1 in these cases.
*/
return 1;
}
/* --------------------------------------------------------------------- */
/*
* Exported function to return the total number of bytes in a codepoint
* represented in UTF-8, given the value of the first byte.
@ -402,22 +520,6 @@ unsigned getNumBytesForUTF8(UTF8 first) {
return trailingBytesForUTF8[first] + 1;
}
int getUTF8StringLength(const UTF8* utf8)
{
const UTF8** source = &utf8;
const UTF8* sourceEnd = utf8 + strlen((const char*)utf8);
int ret = 0;
while (*source != sourceEnd) {
int length = trailingBytesForUTF8[**source] + 1;
if (length > sourceEnd - *source || !isLegalUTF8(*source, length))
return 0;
*source += length;
++ret;
}
return ret;
}
/* --------------------------------------------------------------------- */
/*
@ -509,9 +611,10 @@ ConversionResult ConvertUTF8toUTF16 (
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF8toUTF32 (
static ConversionResult ConvertUTF8toUTF32Impl(
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags,
Boolean InputIsPartial) {
ConversionResult result = conversionOK;
const UTF8* source = *sourceStart;
UTF32* target = *targetStart;
@ -519,12 +622,42 @@ ConversionResult ConvertUTF8toUTF32 (
UTF32 ch = 0;
unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
if (extraBytesToRead >= sourceEnd - source) {
result = sourceExhausted; break;
if (flags == strictConversion || InputIsPartial) {
result = sourceExhausted;
break;
} else {
result = sourceIllegal;
/*
* Replace the maximal subpart of ill-formed sequence with
* replacement character.
*/
source += findMaximalSubpartOfIllFormedUTF8Sequence(source,
sourceEnd);
*target++ = UNI_REPLACEMENT_CHAR;
continue;
}
}
if (target >= targetEnd) {
result = targetExhausted; break;
}
/* Do this check whether lenient or strict */
if (!isLegalUTF8(source, extraBytesToRead+1)) {
result = sourceIllegal;
if (flags == strictConversion) {
/* Abort conversion. */
break;
} else {
/*
* Replace the maximal subpart of ill-formed sequence with
* replacement character.
*/
source += findMaximalSubpartOfIllFormedUTF8Sequence(source,
sourceEnd);
*target++ = UNI_REPLACEMENT_CHAR;
continue;
}
}
/*
* The cases all fall through. See "Note A" below.
@ -539,10 +672,6 @@ ConversionResult ConvertUTF8toUTF32 (
}
ch -= offsetsFromUTF8[extraBytesToRead];
if (target >= targetEnd) {
source -= (extraBytesToRead+1); /* Back up the source pointer! */
result = targetExhausted; break;
}
if (ch <= UNI_MAX_LEGAL_UTF32) {
/*
* UTF-16 surrogate values are illegal in UTF-32, and anything
@ -569,6 +698,36 @@ ConversionResult ConvertUTF8toUTF32 (
return result;
}
ConversionResult ConvertUTF8toUTF32Partial(const UTF8 **sourceStart,
const UTF8 *sourceEnd,
UTF32 **targetStart,
UTF32 *targetEnd,
ConversionFlags flags) {
return ConvertUTF8toUTF32Impl(sourceStart, sourceEnd, targetStart, targetEnd,
flags, /*InputIsPartial=*/true);
}
ConversionResult ConvertUTF8toUTF32(const UTF8 **sourceStart,
const UTF8 *sourceEnd, UTF32 **targetStart,
UTF32 *targetEnd, ConversionFlags flags) {
return ConvertUTF8toUTF32Impl(sourceStart, sourceEnd, targetStart, targetEnd,
flags, /*InputIsPartial=*/false);
}
int getUTF8StringLength(const UTF8* utf8) {
const UTF8** source = &utf8;
const UTF8* sourceEnd = utf8 + strlen((const char*) utf8);
int ret = 0;
while (*source != sourceEnd) {
int length = trailingBytesForUTF8[**source] + 1;
if (length > sourceEnd - *source || !isLegalUTF8(*source, length))
return 0;
*source += length;
++ret;
}
return ret;
}
/* ---------------------------------------------------------------------
Note A.
@ -587,3 +746,7 @@ ConversionResult ConvertUTF8toUTF32 (
similarly unrolled loops.
--------------------------------------------------------------------- */
} // namespace llvm
ConvertUTF_RESTORE_WARNINGS

View File

@ -1,9 +1,8 @@
/*===--- ConvertUTF.h - Universal Character Names conversions ---------------===
*
* The LLVM Compiler Infrastructure
*
* This file is distributed under the University of Illinois Open Source
* License. See LICENSE.TXT for details.
* Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
* See https://llvm.org/LICENSE.txt for license information.
* SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
*
*==------------------------------------------------------------------------==*/
/*
@ -90,7 +89,15 @@
#ifndef LLVM_SUPPORT_CONVERTUTF_H
#define LLVM_SUPPORT_CONVERTUTF_H
#include <stddef.h> /* ptrdiff_t */
#include <cstddef>
#include <string>
#include <system_error>
// Wrap everything in namespace llvm so that programs can link with llvm and
// their own version of the unicode libraries.
namespace llvm {
/* ---------------------------------------------------------------------
The following 4 definitions are compiler-specific.
The C standard does not guarantee that wchar_t has at least
@ -128,15 +135,22 @@ typedef enum {
lenientConversion
} ConversionFlags;
/* This is for C++ and does no harm in C */
#ifdef __cplusplus
extern "C" {
#endif
ConversionResult ConvertUTF8toUTF16 (
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
/**
* Convert a partial UTF8 sequence to UTF32. If the sequence ends in an
* incomplete code unit sequence, returns \c sourceExhausted.
*/
ConversionResult ConvertUTF8toUTF32Partial(
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
/**
* Convert a partial UTF8 sequence to UTF32. If the sequence ends in an
* incomplete code unit sequence, returns \c sourceIllegal.
*/
ConversionResult ConvertUTF8toUTF32(
const UTF8** sourceStart, const UTF8* sourceEnd,
UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
@ -163,92 +177,9 @@ Boolean isLegalUTF8String(const UTF8 **source, const UTF8 *sourceEnd);
unsigned getNumBytesForUTF8(UTF8 firstByte);
// adxe-specific
int getUTF8StringLength(const UTF8* utf8);
#ifdef __cplusplus
}
/*************************************************************************/
/* Below are LLVM-specific wrappers of the functions above. */
//#include "llvm/ADT/ArrayRef.h"
//#include "llvm/ADT/StringRef.h"
#include <vector>
#include <string>
namespace llvm {
/**
* Convert an UTF8 StringRef to UTF8, UTF16, or UTF32 depending on
* WideCharWidth. The converted data is written to ResultPtr, which needs to
* point to at least WideCharWidth * (Source.Size() + 1) bytes. On success,
* ResultPtr will point one after the end of the copied string. On failure,
* ResultPtr will not be changed, and ErrorPtr will be set to the location of
* the first character which could not be converted.
* \return true on success.
*/
bool ConvertUTF8toWide(unsigned WideCharWidth, const std::string& Source,
char *&ResultPtr, const UTF8 *&ErrorPtr);
/**
* Convert an Unicode code point to UTF8 sequence.
*
* \param Source a Unicode code point.
* \param [in,out] ResultPtr pointer to the output buffer, needs to be at least
* \c UNI_MAX_UTF8_BYTES_PER_CODE_POINT bytes. On success \c ResultPtr is
* updated one past end of the converted sequence.
*
* \returns true on success.
*/
bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr);
/**
* Convert the first UTF8 sequence in the given source buffer to a UTF32
* code point.
*
* \param [in,out] source A pointer to the source buffer. If the conversion
* succeeds, this pointer will be updated to point to the byte just past the
* end of the converted sequence.
* \param sourceEnd A pointer just past the end of the source buffer.
* \param [out] target The converted code
* \param flags Whether the conversion is strict or lenient.
*
* \returns conversionOK on success
*
* \sa ConvertUTF8toUTF32
*/
static inline ConversionResult convertUTF8Sequence(const UTF8 **source,
const UTF8 *sourceEnd,
UTF32 *target,
ConversionFlags flags) {
if (*source == sourceEnd)
return sourceExhausted;
unsigned size = getNumBytesForUTF8(**source);
if ((ptrdiff_t)size > sourceEnd - *source)
return sourceExhausted;
return ConvertUTF8toUTF32(source, *source + size, &target, target + 1, flags);
}
/**
* Returns true if a blob of text starts with a UTF-16 big or little endian byte
* order mark.
*/
bool hasUTF16ByteOrderMark(const char* SrcBytes, size_t len);
/**
* Converts a stream of raw bytes assumed to be UTF16 into a UTF8 std::string.
*
* \param [in] SrcBytes A buffer of what is assumed to be UTF-16 encoded text.
* \param [out] Out Converted UTF-8 is stored here on success.
* \returns true on success
*/
bool convertUTF16ToUTF8String(const std::u16string& utf16, std::string &Out);
} /* end namespace llvm */
#endif
/* --------------------------------------------------------------------- */
#endif

View File

@ -1,144 +0,0 @@
//===-- ConvertUTFWrapper.cpp - Wrap ConvertUTF.h with clang data types -----===
//
// The LLVM Compiler Infrastructure
//
// This file is distributed under the University of Illinois Open Source
// License. See LICENSE.TXT for details.
//
//===----------------------------------------------------------------------===//
#include "ConvertUTF.h"
//#include "llvm/Support/SwapByteOrder.h"
#include <string>
#include <vector>
#include <stdint.h> // uint16_t
#include <assert.h>
#include <memory.h>
namespace llvm {
bool ConvertUTF8toWide(unsigned WideCharWidth, const std::string& Source,
char *&ResultPtr, const UTF8 *&ErrorPtr) {
assert(WideCharWidth == 1 || WideCharWidth == 2 || WideCharWidth == 4);
ConversionResult result = conversionOK;
// Copy the character span over.
if (WideCharWidth == 1) {
const UTF8 *Pos = reinterpret_cast<const UTF8*>(Source.data());
if (!isLegalUTF8String(&Pos, reinterpret_cast<const UTF8*>(Source.data() + Source.length()))) {
result = sourceIllegal;
ErrorPtr = Pos;
} else {
memcpy(ResultPtr, Source.data(), Source.size());
ResultPtr += Source.size();
}
} else if (WideCharWidth == 2) {
const UTF8 *sourceStart = (const UTF8*)Source.data();
// FIXME: Make the type of the result buffer correct instead of
// using reinterpret_cast.
UTF16 *targetStart = reinterpret_cast<UTF16*>(ResultPtr);
ConversionFlags flags = strictConversion;
result = ConvertUTF8toUTF16(
&sourceStart, sourceStart + Source.size(),
&targetStart, targetStart + 2*Source.size(), flags);
if (result == conversionOK)
ResultPtr = reinterpret_cast<char*>(targetStart);
else
ErrorPtr = sourceStart;
} else if (WideCharWidth == 4) {
const UTF8 *sourceStart = (const UTF8*)Source.data();
// FIXME: Make the type of the result buffer correct instead of
// using reinterpret_cast.
UTF32 *targetStart = reinterpret_cast<UTF32*>(ResultPtr);
ConversionFlags flags = strictConversion;
result = ConvertUTF8toUTF32(
&sourceStart, sourceStart + Source.size(),
&targetStart, targetStart + 4*Source.size(), flags);
if (result == conversionOK)
ResultPtr = reinterpret_cast<char*>(targetStart);
else
ErrorPtr = sourceStart;
}
assert((result != targetExhausted)
&& "ConvertUTF8toUTFXX exhausted target buffer");
return result == conversionOK;
}
bool ConvertCodePointToUTF8(unsigned Source, char *&ResultPtr) {
const UTF32 *SourceStart = &Source;
const UTF32 *SourceEnd = SourceStart + 1;
UTF8 *TargetStart = reinterpret_cast<UTF8 *>(ResultPtr);
UTF8 *TargetEnd = TargetStart + 4;
ConversionResult CR = ConvertUTF32toUTF8(&SourceStart, SourceEnd,
&TargetStart, TargetEnd,
strictConversion);
if (CR != conversionOK)
return false;
ResultPtr = reinterpret_cast<char*>(TargetStart);
return true;
}
bool hasUTF16ByteOrderMark(const char* S, size_t len) {
return (len >= 2 &&
((S[0] == '\xff' && S[1] == '\xfe') ||
(S[0] == '\xfe' && S[1] == '\xff')));
}
/// SwapByteOrder_16 - This function returns a byte-swapped representation of
/// the 16-bit argument.
inline uint16_t SwapByteOrder_16(uint16_t value) {
#if defined(_MSC_VER) && !defined(_DEBUG)
// The DLL version of the runtime lacks these functions (bug!?), but in a
// release build they're replaced with BSWAP instructions anyway.
return _byteswap_ushort(value);
#else
uint16_t Hi = value << 8;
uint16_t Lo = value >> 8;
return Hi | Lo;
#endif
}
bool convertUTF16ToUTF8String(const std::u16string& utf16, std::string &Out) {
assert(Out.empty());
// Avoid OOB by returning early on empty input.
if (utf16.empty())
return true;
const UTF16 *Src = reinterpret_cast<const UTF16 *>(utf16.data());
const UTF16 *SrcEnd = reinterpret_cast<const UTF16 *>(utf16.data() + utf16.length());
// Byteswap if necessary.
std::vector<UTF16> ByteSwapped;
if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_SWAPPED) {
ByteSwapped.insert(ByteSwapped.end(), Src, SrcEnd);
for (size_t I = 0, E = ByteSwapped.size(); I != E; ++I)
ByteSwapped[I] = SwapByteOrder_16(ByteSwapped[I]);
Src = &ByteSwapped[0];
SrcEnd = &ByteSwapped[ByteSwapped.size() - 1] + 1;
}
// Skip the BOM for conversion.
if (Src[0] == UNI_UTF16_BYTE_ORDER_MARK_NATIVE)
Src++;
// Just allocate enough space up front. We'll shrink it later.
Out.resize(utf16.length() * UNI_MAX_UTF8_BYTES_PER_CODE_POINT + 1);
UTF8 *Dst = reinterpret_cast<UTF8 *>(&Out[0]);
UTF8 *DstEnd = Dst + Out.size();
ConversionResult CR =
ConvertUTF16toUTF8(&Src, SrcEnd, &Dst, DstEnd, strictConversion);
assert(CR != targetExhausted);
if (CR != conversionOK) {
Out.clear();
return false;
}
Out.resize(reinterpret_cast<char *>(Dst) - &Out[0]);
return true;
}
} // end namespace llvm

4
external/README.md vendored
View File

@ -36,7 +36,7 @@
## ConvertUTF
- Upstream: https://github.com/llvm/llvm-project
- Version: NA
- Version: git 2946cd7 without LLVM-specific wrappers of the functions
- License: Apache-2.0 WITH LLVM-exception
## curl
@ -153,7 +153,7 @@
## poly2tri
- Upstream: https://github.com/jhasse/poly2tri
- Version: NA
- Version: git 7f0487a
- License: BSD-3-Clause
## pugixml

View File

@ -243,6 +243,17 @@ Point* Triangle::PointCCW(const Point& point)
return nullptr;
}
// The neighbor across to given point
Triangle* Triangle::NeighborAcross(const Point& point)
{
if (&point == points_[0]) {
return neighbors_[0];
} else if (&point == points_[1]) {
return neighbors_[1];
}
return neighbors_[2];
}
// The neighbor clockwise to given point
Triangle* Triangle::NeighborCW(const Point& point)
{
@ -349,23 +360,6 @@ void Triangle::SetDelunayEdgeCW(const Point& p, bool e)
}
}
// The neighbor across to given point
Triangle& Triangle::NeighborAcross(const Point& opoint)
{
Triangle* neighbor = nullptr;
if (&opoint == points_[0]) {
neighbor = neighbors_[0];
} else if (&opoint == points_[1]) {
neighbor = neighbors_[1];
} else {
neighbor = neighbors_[2];
}
if (neighbor == nullptr) {
throw std::runtime_error("NeighborAcross - null neighbor");
}
return *neighbor;
}
void Triangle::DebugPrint()
{
std::cout << *points_[0] << " " << *points_[1] << " " << *points_[2] << std::endl;

View File

@ -176,6 +176,7 @@ void MarkConstrainedEdge(Point* p, Point* q);
int Index(const Point* p);
int EdgeIndex(const Point* p1, const Point* p2);
Triangle* NeighborAcross(const Point& point);
Triangle* NeighborCW(const Point& point);
Triangle* NeighborCCW(const Point& point);
bool GetConstrainedEdgeCCW(const Point& p);
@ -203,8 +204,6 @@ void ClearDelunayEdges();
inline bool IsInterior();
inline void IsInterior(bool b);
Triangle& NeighborAcross(const Point& opoint);
void DebugPrint();
bool CircumcicleContains(const Point&) const;
@ -260,7 +259,7 @@ inline bool operator ==(const Point& a, const Point& b)
inline bool operator !=(const Point& a, const Point& b)
{
return !(a.x == b.x) && !(a.y == b.y);
return !(a.x == b.x) || !(a.y == b.y);
}
/// Peform the dot product on two vectors.

View File

@ -1,5 +1,5 @@
/*
* Poly2Tri Copyright (c) 2009-2018, Poly2Tri Contributors
* Poly2Tri Copyright (c) 2009-2021, Poly2Tri Contributors
* https://github.com/jhasse/poly2tri
*
* All rights reserved.
@ -68,4 +68,4 @@ CDT::~CDT()
delete sweep_;
}
}
} // namespace p2t

View File

@ -65,17 +65,25 @@ void Sweep::FinalizationPolygon(SweepContext& tcx)
// Get an Internal triangle to start with
Triangle* t = tcx.front()->head()->next->triangle;
Point* p = tcx.front()->head()->next->point;
while (!t->GetConstrainedEdgeCW(*p)) {
while (t && !t->GetConstrainedEdgeCW(*p)) {
t = t->NeighborCCW(*p);
}
// Collect interior triangles constrained by edges
if (t) {
tcx.MeshClean(*t);
}
}
Node& Sweep::PointEvent(SweepContext& tcx, Point& point)
{
Node& node = tcx.LocateNode(point);
Node* node_ptr = tcx.LocateNode(point);
if (!node_ptr || !node_ptr->point || !node_ptr->next || !node_ptr->next->point)
{
throw std::runtime_error("PointEvent - null node");
}
Node& node = *node_ptr;
Node& new_node = NewFrontTriangle(tcx, point, node);
// Only need to check +epsilon since point never have smaller
@ -108,6 +116,9 @@ void Sweep::EdgeEvent(SweepContext& tcx, Edge* edge, Node* node)
void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangle, Point& point)
{
if (triangle == nullptr) {
throw std::runtime_error("EdgeEvent - null triangle");
}
if (IsEdgeSideOfTriangle(*triangle, ep, eq)) {
return;
}
@ -120,7 +131,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
// We are modifying the constraint maybe it would be better to
// not change the given constraint and just keep a variable for the new constraint
tcx.edge_event.constrained_edge->q = p1;
triangle = &triangle->NeighborAcross(point);
triangle = triangle->NeighborAcross(point);
EdgeEvent(tcx, ep, *p1, triangle, *p1);
} else {
throw std::runtime_error("EdgeEvent - collinear points not supported");
@ -136,7 +147,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
// We are modifying the constraint maybe it would be better to
// not change the given constraint and just keep a variable for the new constraint
tcx.edge_event.constrained_edge->q = p2;
triangle = &triangle->NeighborAcross(point);
triangle = triangle->NeighborAcross(point);
EdgeEvent(tcx, ep, *p2, triangle, *p2);
} else {
throw std::runtime_error("EdgeEvent - collinear points not supported");
@ -155,6 +166,7 @@ void Sweep::EdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* triangl
EdgeEvent(tcx, ep, eq, triangle, point);
} else {
// This triangle crosses constraint so lets flippin start!
assert(triangle);
FlipEdgeEvent(tcx, ep, eq, triangle, point);
}
}
@ -215,7 +227,6 @@ void Sweep::Fill(SweepContext& tcx, Node& node)
if (!Legalize(tcx, *triangle)) {
tcx.MapTriangleToNodes(*triangle);
}
}
void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
@ -224,7 +235,7 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
// Fill right holes
Node* node = n.next;
while (node->next) {
while (node && node->next) {
// if HoleAngle exceeds 90 degrees then break.
if (LargeHole_DontFill(node)) break;
Fill(tcx, *node);
@ -234,7 +245,7 @@ void Sweep::FillAdvancingFront(SweepContext& tcx, Node& n)
// Fill left holes
node = n.prev;
while (node->prev) {
while (node && node->prev) {
// if HoleAngle exceeds 90 degrees then break.
if (LargeHole_DontFill(node)) break;
Fill(tcx, *node);
@ -610,7 +621,6 @@ void Sweep::FillRightConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
}
}
}
}
void Sweep::FillRightConvexEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
@ -691,12 +701,17 @@ void Sweep::FillLeftConcaveEdgeEvent(SweepContext& tcx, Edge* edge, Node& node)
}
}
}
}
void Sweep::FlipEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle* t, Point& p)
{
Triangle& ot = t->NeighborAcross(p);
assert(t);
Triangle* ot_ptr = t->NeighborAcross(p);
if (ot_ptr == nullptr)
{
throw std::runtime_error("FlipEdgeEvent - null neighbor across");
}
Triangle& ot = *ot_ptr;
Point& op = *ot.OppositePoint(*t, p);
if (InScanArea(p, *t->PointCCW(p), *t->PointCW(p), op)) {
@ -762,10 +777,26 @@ Point& Sweep::NextFlipPoint(Point& ep, Point& eq, Triangle& ot, Point& op)
void Sweep::FlipScanEdgeEvent(SweepContext& tcx, Point& ep, Point& eq, Triangle& flip_triangle,
Triangle& t, Point& p)
{
Triangle& ot = t.NeighborAcross(p);
Point& op = *ot.OppositePoint(t, p);
Triangle* ot_ptr = t.NeighborAcross(p);
if (ot_ptr == nullptr) {
throw std::runtime_error("FlipScanEdgeEvent - null neighbor across");
}
if (InScanArea(eq, *flip_triangle.PointCCW(eq), *flip_triangle.PointCW(eq), op)) {
Point* op_ptr = ot_ptr->OppositePoint(t, p);
if (op_ptr == nullptr) {
throw std::runtime_error("FlipScanEdgeEvent - null opposing point");
}
Point* p1 = flip_triangle.PointCCW(eq);
Point* p2 = flip_triangle.PointCW(eq);
if (p1 == nullptr || p2 == nullptr) {
throw std::runtime_error("FlipScanEdgeEvent - null on either of points");
}
Triangle& ot = *ot_ptr;
Point& op = *op_ptr;
if (InScanArea(eq, *p1, *p2, op)) {
// flip with new edge op->eq
FlipEdgeEvent(tcx, eq, op, &ot, op);
// TODO: Actually I just figured out that it should be possible to
@ -790,5 +821,4 @@ Sweep::~Sweep() {
}
}
} // namespace p2t

View File

@ -33,7 +33,7 @@
* Zalik, B.(2008)'Sweep-line algorithm for constrained Delaunay triangulation',
* International Journal of Geographical Information Science
*
* "FlipScan" Constrained Edge Algorithm invented by Thomas ?hl?n, thahlen@gmail.com
* "FlipScan" Constrained Edge Algorithm invented by Thomas Åhlén, thahlen@gmail.com
*/
#ifndef SWEEP_H

View File

@ -87,8 +87,8 @@ void SweepContext::InitTriangulation()
double dx = kAlpha * (xmax - xmin);
double dy = kAlpha * (ymax - ymin);
head_ = new Point(xmax + dx, ymin - dy);
tail_ = new Point(xmin - dx, ymin - dy);
head_ = new Point(xmin - dx, ymin - dy);
tail_ = new Point(xmax + dx, ymin - dy);
// Sort points along y-axis
std::sort(points_.begin(), points_.end(), cmp);
@ -114,17 +114,17 @@ void SweepContext::AddToMap(Triangle* triangle)
map_.push_back(triangle);
}
Node& SweepContext::LocateNode(const Point& point)
Node* SweepContext::LocateNode(const Point& point)
{
// TODO implement search tree
return *front_->LocateNode(point.x);
return front_->LocateNode(point.x);
}
void SweepContext::CreateAdvancingFront()
{
// Initial triangle
Triangle* triangle = new Triangle(*points_[0], *tail_, *head_);
Triangle* triangle = new Triangle(*points_[0], *head_, *tail_);
map_.push_back(triangle);
@ -207,4 +207,4 @@ SweepContext::~SweepContext()
}
}
} // namespace p2t

View File

@ -66,7 +66,7 @@ Point* tail() const;
size_t point_count() const;
Node& LocateNode(const Point& point);
Node* LocateNode(const Point& point);
void RemoveNode(Node* node);