mirror of
				https://github.com/SoftFever/OrcaSlicer.git
				synced 2025-11-02 20:51:23 -07:00 
			
		
		
		
	admesh refactoring: Using boost::object_pool for linked list memory
allocation.
This commit is contained in:
		
							parent
							
								
									590c290ede
								
							
						
					
					
						commit
						5fc465b7e8
					
				
					 3 changed files with 284 additions and 266 deletions
				
			
		| 
						 | 
				
			
			@ -28,8 +28,9 @@
 | 
			
		|||
#include <algorithm>
 | 
			
		||||
#include <vector>
 | 
			
		||||
 | 
			
		||||
#include <boost/predef/other/endian.h>
 | 
			
		||||
#include <boost/log/trivial.hpp>
 | 
			
		||||
#include <boost/detail/endian.hpp>
 | 
			
		||||
#include <boost/pool/object_pool.hpp>
 | 
			
		||||
 | 
			
		||||
#include "stl.h"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -42,11 +43,11 @@ struct HashEdge {
 | 
			
		|||
	int  hash(int M) const { return ((key[0] / 11 + key[1] / 7 + key[2] / 3) ^ (key[3] / 11  + key[4] / 7 + key[5] / 3)) % M; }
 | 
			
		||||
 | 
			
		||||
	// Index of a facet owning this edge.
 | 
			
		||||
	int            facet_number;
 | 
			
		||||
	int        facet_number;
 | 
			
		||||
	// Index of this edge inside the facet with an index of facet_number.
 | 
			
		||||
	// If this edge is stored backwards, which_edge is increased by 3.
 | 
			
		||||
	int            which_edge;
 | 
			
		||||
	struct HashEdge  *next;
 | 
			
		||||
	int        which_edge;
 | 
			
		||||
	HashEdge  *next;
 | 
			
		||||
 | 
			
		||||
	void load_exact(stl_file *stl, const stl_vertex *a, const stl_vertex *b)
 | 
			
		||||
	{
 | 
			
		||||
| 
						 | 
				
			
			@ -69,15 +70,15 @@ struct HashEdge {
 | 
			
		|||
	  	// Switch negative zeros to positive zeros, so memcmp will consider them to be equal.
 | 
			
		||||
	  	for (size_t i = 0; i < 6; ++ i) {
 | 
			
		||||
	    	unsigned char *p = (unsigned char*)(this->key + i);
 | 
			
		||||
	#ifdef BOOST_LITTLE_ENDIAN
 | 
			
		||||
	#if BOOST_ENDIAN_LITTLE_BYTE
 | 
			
		||||
	    	if (p[0] == 0 && p[1] == 0 && p[2] == 0 && p[3] == 0x80)
 | 
			
		||||
	      		// Negative zero, switch to positive zero.
 | 
			
		||||
	      		p[3] = 0;
 | 
			
		||||
	#else /* BOOST_LITTLE_ENDIAN */
 | 
			
		||||
	#else /* BOOST_ENDIAN_LITTLE_BYTE */
 | 
			
		||||
	    	if (p[0] == 0x80 && p[1] == 0 && p[2] == 0 && p[3] == 0)
 | 
			
		||||
	      		// Negative zero, switch to positive zero.
 | 
			
		||||
	      		p[0] = 0;
 | 
			
		||||
	#endif /* BOOST_LITTLE_ENDIAN */
 | 
			
		||||
	#endif /* BOOST_ENDIAN_LITTLE_BYTE */
 | 
			
		||||
	  	}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -115,7 +116,7 @@ struct HashTableEdges {
 | 
			
		|||
	HashTableEdges(size_t number_of_faces) {
 | 
			
		||||
		this->M = (int)hash_size_from_nr_faces(number_of_faces);
 | 
			
		||||
		this->heads.assign(this->M, nullptr);
 | 
			
		||||
		this->tail = new HashEdge;
 | 
			
		||||
		this->tail = pool.construct();
 | 
			
		||||
		this->tail->next = this->tail;
 | 
			
		||||
		for (int i = 0; i < this->M; ++ i)
 | 
			
		||||
			this->heads[i] = this->tail;
 | 
			
		||||
| 
						 | 
				
			
			@ -124,80 +125,32 @@ struct HashTableEdges {
 | 
			
		|||
	    for (int i = 0; i < this->M; ++ i) {
 | 
			
		||||
	    	for (HashEdge *temp = this->heads[i]; this->heads[i] != this->tail; temp = this->heads[i]) {
 | 
			
		||||
	        	this->heads[i] = this->heads[i]->next;
 | 
			
		||||
	        	delete temp;
 | 
			
		||||
	        	pool.destroy(temp);
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
	        	++ this->freed;
 | 
			
		||||
#endif /* NDEBUG */
 | 
			
		||||
	      	}
 | 
			
		||||
	    }
 | 
			
		||||
		this->heads.clear();
 | 
			
		||||
		delete this->tail;
 | 
			
		||||
		pool.destroy(this->tail);
 | 
			
		||||
		this->tail = nullptr;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void insert_edge(stl_file *stl, const HashEdge &edge, void (*match_neighbors)(stl_file *stl, const HashEdge &edge_a, const HashEdge &edge_b))
 | 
			
		||||
	void insert_edge_exact(stl_file *stl, const HashEdge &edge)
 | 
			
		||||
	{
 | 
			
		||||
		int       chain_number = edge.hash(this->M);
 | 
			
		||||
		HashEdge *link         = this->heads[chain_number];
 | 
			
		||||
		if (link == this->tail) {
 | 
			
		||||
			// This list doesn't have any edges currently in it.  Add this one.
 | 
			
		||||
			HashEdge *new_edge = new HashEdge(edge);
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
			++ this->malloced;
 | 
			
		||||
#endif /* NDEBUG */
 | 
			
		||||
			new_edge->next = this->tail;
 | 
			
		||||
			this->heads[chain_number] = new_edge;
 | 
			
		||||
		} else if (edges_equal(edge, *link)) {
 | 
			
		||||
			// This is a match.  Record result in neighbors list.
 | 
			
		||||
			match_neighbors(stl, edge, *link);
 | 
			
		||||
			// Delete the matched edge from the list.
 | 
			
		||||
			this->heads[chain_number] = link->next;
 | 
			
		||||
			delete link;
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
			++ this->freed;
 | 
			
		||||
#endif /* NDEBUG */
 | 
			
		||||
		} else {
 | 
			
		||||
			// Continue through the rest of the list.
 | 
			
		||||
			for (;;) {
 | 
			
		||||
				if (link->next == this->tail) {
 | 
			
		||||
					// This is the last item in the list. Insert a new edge.
 | 
			
		||||
					HashEdge *new_edge = new HashEdge;
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
					++ this->malloced;
 | 
			
		||||
#endif /* NDEBUG */
 | 
			
		||||
					*new_edge = edge;
 | 
			
		||||
					new_edge->next = this->tail;
 | 
			
		||||
					link->next = new_edge;
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
					++ this->collisions;
 | 
			
		||||
#endif /* NDEBUG */
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				if (edges_equal(edge, *link->next)) {
 | 
			
		||||
					// This is a match.  Record result in neighbors list.
 | 
			
		||||
					match_neighbors(stl, edge, *link->next);
 | 
			
		||||
					// Delete the matched edge from the list.
 | 
			
		||||
					HashEdge *temp = link->next;
 | 
			
		||||
					link->next = link->next->next;
 | 
			
		||||
					delete temp;
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
					++ this->freed;
 | 
			
		||||
#endif /* NDEBUG */
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				// This is not a match.  Go to the next link.
 | 
			
		||||
				link = link->next;
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
				++ this->collisions;
 | 
			
		||||
#endif /* NDEBUG */
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
		this->insert_edge(stl, edge, [stl](const HashEdge& edge1, const HashEdge& edge2) { record_neighbors(stl, edge1, edge2); });
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	void insert_edge_nearby(stl_file *stl, const HashEdge &edge)
 | 
			
		||||
	{
 | 
			
		||||
		this->insert_edge(stl, edge, [stl](const HashEdge& edge1, const HashEdge& edge2) { match_neighbors_nearby(stl, edge1, edge2); });
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Hash table on edges
 | 
			
		||||
	std::vector<HashEdge*> 	heads;
 | 
			
		||||
	HashEdge* 				tail;
 | 
			
		||||
	int           			M;
 | 
			
		||||
	boost::object_pool<HashEdge> pool;
 | 
			
		||||
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
	size_t 					malloced   	= 0;
 | 
			
		||||
| 
						 | 
				
			
			@ -216,198 +169,260 @@ private:
 | 
			
		|||
		return (it == primes.end()) ? primes.back() : *it;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
	// MatchNeighbors(stl_file *stl, const HashEdge &edge_a, const HashEdge &edge_b)
 | 
			
		||||
	template<typename MatchNeighbors>
 | 
			
		||||
	void insert_edge(stl_file *stl, const HashEdge &edge, MatchNeighbors match_neighbors)
 | 
			
		||||
	{
 | 
			
		||||
		int       chain_number = edge.hash(this->M);
 | 
			
		||||
		HashEdge *link         = this->heads[chain_number];
 | 
			
		||||
		if (link == this->tail) {
 | 
			
		||||
			// This list doesn't have any edges currently in it.  Add this one.
 | 
			
		||||
			HashEdge *new_edge = pool.construct(edge);
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
			++ this->malloced;
 | 
			
		||||
#endif /* NDEBUG */
 | 
			
		||||
			new_edge->next = this->tail;
 | 
			
		||||
			this->heads[chain_number] = new_edge;
 | 
			
		||||
		} else if (edges_equal(edge, *link)) {
 | 
			
		||||
			// This is a match.  Record result in neighbors list.
 | 
			
		||||
			match_neighbors(edge, *link);
 | 
			
		||||
			// Delete the matched edge from the list.
 | 
			
		||||
			this->heads[chain_number] = link->next;
 | 
			
		||||
			pool.destroy(link);
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
			++ this->freed;
 | 
			
		||||
#endif /* NDEBUG */
 | 
			
		||||
		} else {
 | 
			
		||||
			// Continue through the rest of the list.
 | 
			
		||||
			for (;;) {
 | 
			
		||||
				if (link->next == this->tail) {
 | 
			
		||||
					// This is the last item in the list. Insert a new edge.
 | 
			
		||||
					HashEdge *new_edge = pool.construct();
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
					++ this->malloced;
 | 
			
		||||
#endif /* NDEBUG */
 | 
			
		||||
					*new_edge = edge;
 | 
			
		||||
					new_edge->next = this->tail;
 | 
			
		||||
					link->next = new_edge;
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
					++ this->collisions;
 | 
			
		||||
#endif /* NDEBUG */
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				if (edges_equal(edge, *link->next)) {
 | 
			
		||||
					// This is a match.  Record result in neighbors list.
 | 
			
		||||
					match_neighbors(edge, *link->next);
 | 
			
		||||
					// Delete the matched edge from the list.
 | 
			
		||||
					HashEdge *temp = link->next;
 | 
			
		||||
					link->next = link->next->next;
 | 
			
		||||
					pool.destroy(temp);
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
					++ this->freed;
 | 
			
		||||
#endif /* NDEBUG */
 | 
			
		||||
					break;
 | 
			
		||||
				}
 | 
			
		||||
				// This is not a match.  Go to the next link.
 | 
			
		||||
				link = link->next;
 | 
			
		||||
#ifndef NDEBUG
 | 
			
		||||
				++ this->collisions;
 | 
			
		||||
#endif /* NDEBUG */
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Edges equal for hashing. Edgesof different facet are allowed to be matched.
 | 
			
		||||
	static inline bool edges_equal(const HashEdge &edge_a, const HashEdge &edge_b)
 | 
			
		||||
	{
 | 
			
		||||
	    return edge_a.facet_number != edge_b.facet_number && edge_a == edge_b;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static void record_neighbors(stl_file *stl, const HashEdge &edge_a, const HashEdge &edge_b)
 | 
			
		||||
	{
 | 
			
		||||
		// Facet a's neighbor is facet b
 | 
			
		||||
		stl->neighbors_start[edge_a.facet_number].neighbor[edge_a.which_edge % 3] = edge_b.facet_number;	/* sets the .neighbor part */
 | 
			
		||||
		stl->neighbors_start[edge_a.facet_number].which_vertex_not[edge_a.which_edge % 3] = (edge_b.which_edge + 2) % 3; /* sets the .which_vertex_not part */
 | 
			
		||||
 | 
			
		||||
		// Facet b's neighbor is facet a
 | 
			
		||||
		stl->neighbors_start[edge_b.facet_number].neighbor[edge_b.which_edge % 3] = edge_a.facet_number;	/* sets the .neighbor part */
 | 
			
		||||
		stl->neighbors_start[edge_b.facet_number].which_vertex_not[edge_b.which_edge % 3] = (edge_a.which_edge + 2) % 3; /* sets the .which_vertex_not part */
 | 
			
		||||
 | 
			
		||||
		if (((edge_a.which_edge < 3) && (edge_b.which_edge < 3)) || ((edge_a.which_edge > 2) && (edge_b.which_edge > 2))) {
 | 
			
		||||
			// These facets are oriented in opposite directions, their normals are probably messed up.
 | 
			
		||||
			stl->neighbors_start[edge_a.facet_number].which_vertex_not[edge_a.which_edge % 3] += 3;
 | 
			
		||||
			stl->neighbors_start[edge_b.facet_number].which_vertex_not[edge_b.which_edge % 3] += 3;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Count successful connects:
 | 
			
		||||
		// Total connects:
 | 
			
		||||
		stl->stats.connected_edges += 2;
 | 
			
		||||
		// Count individual connects:
 | 
			
		||||
		switch (stl->neighbors_start[edge_a.facet_number].num_neighbors()) {
 | 
			
		||||
		case 1:	++ stl->stats.connected_facets_1_edge; break;
 | 
			
		||||
		case 2: ++ stl->stats.connected_facets_2_edge; break;
 | 
			
		||||
		case 3: ++ stl->stats.connected_facets_3_edge; break;
 | 
			
		||||
		default: assert(false);
 | 
			
		||||
		}
 | 
			
		||||
		switch (stl->neighbors_start[edge_b.facet_number].num_neighbors()) {
 | 
			
		||||
		case 1:	++ stl->stats.connected_facets_1_edge; break;
 | 
			
		||||
		case 2: ++ stl->stats.connected_facets_2_edge; break;
 | 
			
		||||
		case 3: ++ stl->stats.connected_facets_3_edge; break;
 | 
			
		||||
		default: assert(false);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	static void match_neighbors_nearby(stl_file *stl, const HashEdge &edge_a, const HashEdge &edge_b)
 | 
			
		||||
	{
 | 
			
		||||
		record_neighbors(stl, edge_a, edge_b);
 | 
			
		||||
 | 
			
		||||
		// Which vertices to change
 | 
			
		||||
		int facet1 = -1;
 | 
			
		||||
		int facet2 = -1;
 | 
			
		||||
		int vertex1, vertex2;
 | 
			
		||||
		stl_vertex new_vertex1, new_vertex2;
 | 
			
		||||
		{
 | 
			
		||||
			int v1a; // pair 1, facet a
 | 
			
		||||
			int v1b; // pair 1, facet b
 | 
			
		||||
			int v2a; // pair 2, facet a
 | 
			
		||||
			int v2b; // pair 2, facet b
 | 
			
		||||
			// Find first pair.
 | 
			
		||||
			if (edge_a.which_edge < 3) {
 | 
			
		||||
				v1a = edge_a.which_edge;
 | 
			
		||||
				v2a = (edge_a.which_edge + 1) % 3;
 | 
			
		||||
			} else {
 | 
			
		||||
				v2a = edge_a.which_edge % 3;
 | 
			
		||||
				v1a = (edge_a.which_edge + 1) % 3;
 | 
			
		||||
			}
 | 
			
		||||
			if (edge_b.which_edge < 3) {
 | 
			
		||||
				v1b = edge_b.which_edge;
 | 
			
		||||
				v2b = (edge_b.which_edge + 1) % 3;
 | 
			
		||||
			} else {
 | 
			
		||||
				v2b = edge_b.which_edge % 3;
 | 
			
		||||
				v1b = (edge_b.which_edge + 1) % 3;
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Of the first pair, which vertex, if any, should be changed
 | 
			
		||||
			if (stl->facet_start[edge_a.facet_number].vertex[v1a] != stl->facet_start[edge_b.facet_number].vertex[v1b]) {
 | 
			
		||||
				// These facets are different.
 | 
			
		||||
				if (   (stl->neighbors_start[edge_a.facet_number].neighbor[v1a] == -1)
 | 
			
		||||
			        && (stl->neighbors_start[edge_a.facet_number].neighbor[(v1a + 2) % 3] == -1)) {
 | 
			
		||||
			  		// This vertex has no neighbors.  This is a good one to change.
 | 
			
		||||
			  		facet1 = edge_a.facet_number;
 | 
			
		||||
			  		vertex1 = v1a;
 | 
			
		||||
			  		new_vertex1 = stl->facet_start[edge_b.facet_number].vertex[v1b];
 | 
			
		||||
				} else {
 | 
			
		||||
				  	facet1 = edge_b.facet_number;
 | 
			
		||||
			  		vertex1 = v1b;
 | 
			
		||||
			  		new_vertex1 = stl->facet_start[edge_a.facet_number].vertex[v1a];
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
 | 
			
		||||
			// Of the second pair, which vertex, if any, should be changed.
 | 
			
		||||
			if (stl->facet_start[edge_a.facet_number].vertex[v2a] == stl->facet_start[edge_b.facet_number].vertex[v2b]) {
 | 
			
		||||
				// These facets are different.
 | 
			
		||||
				if (  (stl->neighbors_start[edge_a.facet_number].neighbor[v2a] == -1)
 | 
			
		||||
			       && (stl->neighbors_start[edge_a.facet_number].neighbor[(v2a + 2) % 3] == -1)) {
 | 
			
		||||
			  		// This vertex has no neighbors.  This is a good one to change.
 | 
			
		||||
			  		facet2 = edge_a.facet_number;
 | 
			
		||||
			  		vertex2 = v2a;
 | 
			
		||||
			  		new_vertex2 = stl->facet_start[edge_b.facet_number].vertex[v2b];
 | 
			
		||||
				} else {
 | 
			
		||||
			  		facet2 = edge_b.facet_number;
 | 
			
		||||
			  		vertex2 = v2b;
 | 
			
		||||
			  		new_vertex2 = stl->facet_start[edge_a.facet_number].vertex[v2a];
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		auto change_vertices = [stl](int facet_num, int vnot, stl_vertex new_vertex)
 | 
			
		||||
		{
 | 
			
		||||
			int first_facet = facet_num;
 | 
			
		||||
			bool direction = false;
 | 
			
		||||
 | 
			
		||||
			for (;;) {
 | 
			
		||||
				int pivot_vertex;
 | 
			
		||||
				int next_edge;
 | 
			
		||||
				if (vnot > 2) {
 | 
			
		||||
					if (direction) {
 | 
			
		||||
						pivot_vertex = (vnot + 1) % 3;
 | 
			
		||||
						next_edge = vnot % 3;
 | 
			
		||||
					}
 | 
			
		||||
					else {
 | 
			
		||||
						pivot_vertex = (vnot + 2) % 3;
 | 
			
		||||
						next_edge = pivot_vertex;
 | 
			
		||||
					}
 | 
			
		||||
					direction = !direction;
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					if (direction) {
 | 
			
		||||
						pivot_vertex = (vnot + 2) % 3;
 | 
			
		||||
						next_edge = pivot_vertex;
 | 
			
		||||
					}
 | 
			
		||||
					else {
 | 
			
		||||
						pivot_vertex = (vnot + 1) % 3;
 | 
			
		||||
						next_edge = vnot;
 | 
			
		||||
					}
 | 
			
		||||
				}
 | 
			
		||||
	#if 0
 | 
			
		||||
				if (stl->facet_start[facet_num].vertex[pivot_vertex](0) == new_vertex(0) &&
 | 
			
		||||
					stl->facet_start[facet_num].vertex[pivot_vertex](1) == new_vertex(1) &&
 | 
			
		||||
					stl->facet_start[facet_num].vertex[pivot_vertex](2) == new_vertex(2))
 | 
			
		||||
					printf("Changing vertex %f,%f,%f: Same !!!\r\n", new_vertex(0), new_vertex(1), new_vertex(2));
 | 
			
		||||
				else {
 | 
			
		||||
					if (stl->facet_start[facet_num].vertex[pivot_vertex](0) != new_vertex(0))
 | 
			
		||||
						printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",
 | 
			
		||||
							stl->facet_start[facet_num].vertex[pivot_vertex](0),
 | 
			
		||||
							*reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex](0)),
 | 
			
		||||
							new_vertex(0),
 | 
			
		||||
							*reinterpret_cast<const int*>(&new_vertex(0)));
 | 
			
		||||
					if (stl->facet_start[facet_num].vertex[pivot_vertex](1) != new_vertex(1))
 | 
			
		||||
						printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",
 | 
			
		||||
							stl->facet_start[facet_num].vertex[pivot_vertex](1),
 | 
			
		||||
							*reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex](1)),
 | 
			
		||||
							new_vertex(1),
 | 
			
		||||
							*reinterpret_cast<const int*>(&new_vertex(1)));
 | 
			
		||||
					if (stl->facet_start[facet_num].vertex[pivot_vertex](2) != new_vertex(2))
 | 
			
		||||
						printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",
 | 
			
		||||
							stl->facet_start[facet_num].vertex[pivot_vertex](2),
 | 
			
		||||
							*reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex](2)),
 | 
			
		||||
							new_vertex(2),
 | 
			
		||||
							*reinterpret_cast<const int*>(&new_vertex(2)));
 | 
			
		||||
				}
 | 
			
		||||
	#endif
 | 
			
		||||
				stl->facet_start[facet_num].vertex[pivot_vertex] = new_vertex;
 | 
			
		||||
				vnot = stl->neighbors_start[facet_num].which_vertex_not[next_edge];
 | 
			
		||||
				facet_num = stl->neighbors_start[facet_num].neighbor[next_edge];
 | 
			
		||||
				if (facet_num == -1)
 | 
			
		||||
					break;
 | 
			
		||||
 | 
			
		||||
				if (facet_num == first_facet) {
 | 
			
		||||
					// back to the beginning
 | 
			
		||||
					BOOST_LOG_TRIVIAL(info) << "Back to the first facet changing vertices: probably a mobius part. Try using a smaller tolerance or don't do a nearby check.";
 | 
			
		||||
					return;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		if (facet1 != -1) {
 | 
			
		||||
			int vnot1 = (facet1 == edge_a.facet_number) ? 
 | 
			
		||||
		  		(edge_a.which_edge + 2) % 3 :
 | 
			
		||||
				(edge_b.which_edge + 2) % 3;
 | 
			
		||||
			if (((vnot1 + 2) % 3) == vertex1)
 | 
			
		||||
		  		vnot1 += 3;
 | 
			
		||||
			change_vertices(facet1, vnot1, new_vertex1);
 | 
			
		||||
		}
 | 
			
		||||
		if (facet2 != -1) {
 | 
			
		||||
			int vnot2 = (facet2 == edge_a.facet_number) ?
 | 
			
		||||
		  		(edge_a.which_edge + 2) % 3 :
 | 
			
		||||
				(edge_b.which_edge + 2) % 3;
 | 
			
		||||
			if (((vnot2 + 2) % 3) == vertex2)
 | 
			
		||||
		  		vnot2 += 3;
 | 
			
		||||
			change_vertices(facet2, vnot2, new_vertex2);
 | 
			
		||||
		}
 | 
			
		||||
		stl->stats.edges_fixed += 2;
 | 
			
		||||
	}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
static void record_neighbors(stl_file *stl, const HashEdge &edge_a, const HashEdge &edge_b)
 | 
			
		||||
{
 | 
			
		||||
	// Facet a's neighbor is facet b
 | 
			
		||||
	stl->neighbors_start[edge_a.facet_number].neighbor[edge_a.which_edge % 3] = edge_b.facet_number;	/* sets the .neighbor part */
 | 
			
		||||
	stl->neighbors_start[edge_a.facet_number].which_vertex_not[edge_a.which_edge % 3] = (edge_b.which_edge + 2) % 3; /* sets the .which_vertex_not part */
 | 
			
		||||
 | 
			
		||||
	// Facet b's neighbor is facet a
 | 
			
		||||
	stl->neighbors_start[edge_b.facet_number].neighbor[edge_b.which_edge % 3] = edge_a.facet_number;	/* sets the .neighbor part */
 | 
			
		||||
	stl->neighbors_start[edge_b.facet_number].which_vertex_not[edge_b.which_edge % 3] = (edge_a.which_edge + 2) % 3; /* sets the .which_vertex_not part */
 | 
			
		||||
 | 
			
		||||
	if (((edge_a.which_edge < 3) && (edge_b.which_edge < 3)) || ((edge_a.which_edge > 2) && (edge_b.which_edge > 2))) {
 | 
			
		||||
		// These facets are oriented in opposite directions, their normals are probably messed up.
 | 
			
		||||
		stl->neighbors_start[edge_a.facet_number].which_vertex_not[edge_a.which_edge % 3] += 3;
 | 
			
		||||
		stl->neighbors_start[edge_b.facet_number].which_vertex_not[edge_b.which_edge % 3] += 3;
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	// Count successful connects:
 | 
			
		||||
	// Total connects:
 | 
			
		||||
	stl->stats.connected_edges += 2;
 | 
			
		||||
	// Count individual connects:
 | 
			
		||||
	switch (stl->neighbors_start[edge_a.facet_number].num_neighbors()) {
 | 
			
		||||
	case 1:	++ stl->stats.connected_facets_1_edge; break;
 | 
			
		||||
	case 2: ++ stl->stats.connected_facets_2_edge; break;
 | 
			
		||||
	case 3: ++ stl->stats.connected_facets_3_edge; break;
 | 
			
		||||
	default: assert(false);
 | 
			
		||||
	}
 | 
			
		||||
	switch (stl->neighbors_start[edge_b.facet_number].num_neighbors()) {
 | 
			
		||||
	case 1:	++ stl->stats.connected_facets_1_edge; break;
 | 
			
		||||
	case 2: ++ stl->stats.connected_facets_2_edge; break;
 | 
			
		||||
	case 3: ++ stl->stats.connected_facets_3_edge; break;
 | 
			
		||||
	default: assert(false);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
static void match_neighbors_nearby(stl_file *stl, const HashEdge &edge_a, const HashEdge &edge_b)
 | 
			
		||||
{
 | 
			
		||||
	record_neighbors(stl, edge_a, edge_b);
 | 
			
		||||
 | 
			
		||||
	// Which vertices to change
 | 
			
		||||
	int facet1 = -1;
 | 
			
		||||
	int facet2 = -1;
 | 
			
		||||
	int vertex1, vertex2;
 | 
			
		||||
	stl_vertex new_vertex1, new_vertex2;
 | 
			
		||||
	{
 | 
			
		||||
		int v1a; // pair 1, facet a
 | 
			
		||||
		int v1b; // pair 1, facet b
 | 
			
		||||
		int v2a; // pair 2, facet a
 | 
			
		||||
		int v2b; // pair 2, facet b
 | 
			
		||||
		// Find first pair.
 | 
			
		||||
		if (edge_a.which_edge < 3) {
 | 
			
		||||
			v1a = edge_a.which_edge;
 | 
			
		||||
			v2a = (edge_a.which_edge + 1) % 3;
 | 
			
		||||
		} else {
 | 
			
		||||
			v2a = edge_a.which_edge % 3;
 | 
			
		||||
			v1a = (edge_a.which_edge + 1) % 3;
 | 
			
		||||
		}
 | 
			
		||||
		if (edge_b.which_edge < 3) {
 | 
			
		||||
			v1b = edge_b.which_edge;
 | 
			
		||||
			v2b = (edge_b.which_edge + 1) % 3;
 | 
			
		||||
		} else {
 | 
			
		||||
			v2b = edge_b.which_edge % 3;
 | 
			
		||||
			v1b = (edge_b.which_edge + 1) % 3;
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Of the first pair, which vertex, if any, should be changed
 | 
			
		||||
		if (stl->facet_start[edge_a.facet_number].vertex[v1a] != stl->facet_start[edge_b.facet_number].vertex[v1b]) {
 | 
			
		||||
			// These facets are different.
 | 
			
		||||
			if (   (stl->neighbors_start[edge_a.facet_number].neighbor[v1a] == -1)
 | 
			
		||||
		        && (stl->neighbors_start[edge_a.facet_number].neighbor[(v1a + 2) % 3] == -1)) {
 | 
			
		||||
		  		// This vertex has no neighbors.  This is a good one to change.
 | 
			
		||||
		  		facet1 = edge_a.facet_number;
 | 
			
		||||
		  		vertex1 = v1a;
 | 
			
		||||
		  		new_vertex1 = stl->facet_start[edge_b.facet_number].vertex[v1b];
 | 
			
		||||
			} else {
 | 
			
		||||
			  	facet1 = edge_b.facet_number;
 | 
			
		||||
		  		vertex1 = v1b;
 | 
			
		||||
		  		new_vertex1 = stl->facet_start[edge_a.facet_number].vertex[v1a];
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
		// Of the second pair, which vertex, if any, should be changed.
 | 
			
		||||
		if (stl->facet_start[edge_a.facet_number].vertex[v2a] == stl->facet_start[edge_b.facet_number].vertex[v2b]) {
 | 
			
		||||
			// These facets are different.
 | 
			
		||||
			if (  (stl->neighbors_start[edge_a.facet_number].neighbor[v2a] == -1)
 | 
			
		||||
		       && (stl->neighbors_start[edge_a.facet_number].neighbor[(v2a + 2) % 3] == -1)) {
 | 
			
		||||
		  		// This vertex has no neighbors.  This is a good one to change.
 | 
			
		||||
		  		facet2 = edge_a.facet_number;
 | 
			
		||||
		  		vertex2 = v2a;
 | 
			
		||||
		  		new_vertex2 = stl->facet_start[edge_b.facet_number].vertex[v2b];
 | 
			
		||||
			} else {
 | 
			
		||||
		  		facet2 = edge_b.facet_number;
 | 
			
		||||
		  		vertex2 = v2b;
 | 
			
		||||
		  		new_vertex2 = stl->facet_start[edge_a.facet_number].vertex[v2a];
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	auto change_vertices = [stl](int facet_num, int vnot, stl_vertex new_vertex)
 | 
			
		||||
	{
 | 
			
		||||
		int first_facet = facet_num;
 | 
			
		||||
		bool direction = false;
 | 
			
		||||
 | 
			
		||||
		for (;;) {
 | 
			
		||||
			int pivot_vertex;
 | 
			
		||||
			int next_edge;
 | 
			
		||||
			if (vnot > 2) {
 | 
			
		||||
				if (direction) {
 | 
			
		||||
					pivot_vertex = (vnot + 1) % 3;
 | 
			
		||||
					next_edge = vnot % 3;
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					pivot_vertex = (vnot + 2) % 3;
 | 
			
		||||
					next_edge = pivot_vertex;
 | 
			
		||||
				}
 | 
			
		||||
				direction = !direction;
 | 
			
		||||
			}
 | 
			
		||||
			else {
 | 
			
		||||
				if (direction) {
 | 
			
		||||
					pivot_vertex = (vnot + 2) % 3;
 | 
			
		||||
					next_edge = pivot_vertex;
 | 
			
		||||
				}
 | 
			
		||||
				else {
 | 
			
		||||
					pivot_vertex = (vnot + 1) % 3;
 | 
			
		||||
					next_edge = vnot;
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
#if 0
 | 
			
		||||
			if (stl->facet_start[facet_num].vertex[pivot_vertex](0) == new_vertex(0) &&
 | 
			
		||||
				stl->facet_start[facet_num].vertex[pivot_vertex](1) == new_vertex(1) &&
 | 
			
		||||
				stl->facet_start[facet_num].vertex[pivot_vertex](2) == new_vertex(2))
 | 
			
		||||
				printf("Changing vertex %f,%f,%f: Same !!!\r\n", new_vertex(0), new_vertex(1), new_vertex(2));
 | 
			
		||||
			else {
 | 
			
		||||
				if (stl->facet_start[facet_num].vertex[pivot_vertex](0) != new_vertex(0))
 | 
			
		||||
					printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",
 | 
			
		||||
						stl->facet_start[facet_num].vertex[pivot_vertex](0),
 | 
			
		||||
						*reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex](0)),
 | 
			
		||||
						new_vertex(0),
 | 
			
		||||
						*reinterpret_cast<const int*>(&new_vertex(0)));
 | 
			
		||||
				if (stl->facet_start[facet_num].vertex[pivot_vertex](1) != new_vertex(1))
 | 
			
		||||
					printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",
 | 
			
		||||
						stl->facet_start[facet_num].vertex[pivot_vertex](1),
 | 
			
		||||
						*reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex](1)),
 | 
			
		||||
						new_vertex(1),
 | 
			
		||||
						*reinterpret_cast<const int*>(&new_vertex(1)));
 | 
			
		||||
				if (stl->facet_start[facet_num].vertex[pivot_vertex](2) != new_vertex(2))
 | 
			
		||||
					printf("Changing coordinate x, vertex %e (0x%08x) to %e(0x%08x)\r\n",
 | 
			
		||||
						stl->facet_start[facet_num].vertex[pivot_vertex](2),
 | 
			
		||||
						*reinterpret_cast<const int*>(&stl->facet_start[facet_num].vertex[pivot_vertex](2)),
 | 
			
		||||
						new_vertex(2),
 | 
			
		||||
						*reinterpret_cast<const int*>(&new_vertex(2)));
 | 
			
		||||
			}
 | 
			
		||||
#endif
 | 
			
		||||
			stl->facet_start[facet_num].vertex[pivot_vertex] = new_vertex;
 | 
			
		||||
			vnot = stl->neighbors_start[facet_num].which_vertex_not[next_edge];
 | 
			
		||||
			facet_num = stl->neighbors_start[facet_num].neighbor[next_edge];
 | 
			
		||||
			if (facet_num == -1)
 | 
			
		||||
				break;
 | 
			
		||||
 | 
			
		||||
			if (facet_num == first_facet) {
 | 
			
		||||
				// back to the beginning
 | 
			
		||||
				BOOST_LOG_TRIVIAL(info) << "Back to the first facet changing vertices: probably a mobius part. Try using a smaller tolerance or don't do a nearby check.";
 | 
			
		||||
				return;
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	};
 | 
			
		||||
 | 
			
		||||
	if (facet1 != -1) {
 | 
			
		||||
		int vnot1 = (facet1 == edge_a.facet_number) ? 
 | 
			
		||||
	  		(edge_a.which_edge + 2) % 3 :
 | 
			
		||||
			(edge_b.which_edge + 2) % 3;
 | 
			
		||||
		if (((vnot1 + 2) % 3) == vertex1)
 | 
			
		||||
	  		vnot1 += 3;
 | 
			
		||||
		change_vertices(facet1, vnot1, new_vertex1);
 | 
			
		||||
	}
 | 
			
		||||
	if (facet2 != -1) {
 | 
			
		||||
		int vnot2 = (facet2 == edge_a.facet_number) ?
 | 
			
		||||
	  		(edge_a.which_edge + 2) % 3 :
 | 
			
		||||
			(edge_b.which_edge + 2) % 3;
 | 
			
		||||
		if (((vnot2 + 2) % 3) == vertex2)
 | 
			
		||||
	  		vnot2 += 3;
 | 
			
		||||
		change_vertices(facet2, vnot2, new_vertex2);
 | 
			
		||||
	}
 | 
			
		||||
	stl->stats.edges_fixed += 2;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// This function builds the neighbors list.  No modifications are made
 | 
			
		||||
// to any of the facets.  The edges are said to match only if all six
 | 
			
		||||
// floats of the first edge matches all six floats of the second edge.
 | 
			
		||||
| 
						 | 
				
			
			@ -445,7 +460,7 @@ void stl_check_facets_exact(stl_file *stl)
 | 
			
		|||
			edge.facet_number = i;
 | 
			
		||||
			edge.which_edge = j;
 | 
			
		||||
			edge.load_exact(stl, &facet.vertex[j], &facet.vertex[(j + 1) % 3]);
 | 
			
		||||
			hash_table.insert_edge(stl, edge, record_neighbors);
 | 
			
		||||
			hash_table.insert_edge_exact(stl, edge);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -476,7 +491,7 @@ void stl_check_facets_nearby(stl_file *stl, float tolerance)
 | 
			
		|||
        		edge.which_edge = j;
 | 
			
		||||
        		if (edge.load_nearby(stl, facet.vertex[j], facet.vertex[(j + 1) % 3], tolerance))
 | 
			
		||||
          			// Only insert edges that have different keys.
 | 
			
		||||
          			hash_table.insert_edge(stl, edge, match_neighbors_nearby);
 | 
			
		||||
          			hash_table.insert_edge_nearby(stl, edge);
 | 
			
		||||
      		}
 | 
			
		||||
    	}
 | 
			
		||||
  	}
 | 
			
		||||
| 
						 | 
				
			
			@ -654,7 +669,7 @@ void stl_fill_holes(stl_file *stl)
 | 
			
		|||
	  		edge.facet_number = i;
 | 
			
		||||
	  		edge.which_edge = j;
 | 
			
		||||
	  		edge.load_exact(stl, &facet.vertex[j], &facet.vertex[(j + 1) % 3]);
 | 
			
		||||
	  		hash_table.insert_edge(stl, edge, record_neighbors);
 | 
			
		||||
	  		hash_table.insert_edge_exact(stl, edge);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -704,7 +719,7 @@ void stl_fill_holes(stl_file *stl)
 | 
			
		|||
	        			edge.facet_number = stl->stats.number_of_facets - 1;
 | 
			
		||||
	        			edge.which_edge = k;
 | 
			
		||||
	        			edge.load_exact(stl, &new_facet.vertex[k], &new_facet.vertex[(k + 1) % 3]);
 | 
			
		||||
	        			hash_table.insert_edge(stl, edge, record_neighbors);
 | 
			
		||||
	        			hash_table.insert_edge_exact(stl, edge);
 | 
			
		||||
	      			}
 | 
			
		||||
	      			break;
 | 
			
		||||
	    		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,6 +25,8 @@
 | 
			
		|||
#include <string.h>
 | 
			
		||||
#include <math.h>
 | 
			
		||||
 | 
			
		||||
#include <boost/pool/object_pool.hpp>
 | 
			
		||||
 | 
			
		||||
#include "stl.h"
 | 
			
		||||
 | 
			
		||||
static void reverse_facet(stl_file *stl, int facet_num)
 | 
			
		||||
| 
						 | 
				
			
			@ -120,8 +122,9 @@ void stl_fix_normal_directions(stl_file *stl)
 | 
			
		|||
  	};
 | 
			
		||||
 | 
			
		||||
  	// Initialize linked list.
 | 
			
		||||
   	stl_normal *head = new stl_normal;
 | 
			
		||||
  	stl_normal *tail = new stl_normal;
 | 
			
		||||
  	boost::object_pool<stl_normal> pool;
 | 
			
		||||
   	stl_normal *head = pool.construct();
 | 
			
		||||
  	stl_normal *tail = pool.construct();
 | 
			
		||||
	head->next = tail;
 | 
			
		||||
	tail->next = tail;
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -168,7 +171,7 @@ void stl_fix_normal_directions(stl_file *stl)
 | 
			
		|||
        		// If we haven't fixed this facet yet, add it to the list:
 | 
			
		||||
        		if (norm_sw[stl->neighbors_start[facet_num].neighbor[j]] != 1) {
 | 
			
		||||
	          		// Add node to beginning of list.
 | 
			
		||||
	          		stl_normal *newn = new stl_normal;
 | 
			
		||||
	          		stl_normal *newn = pool.construct();
 | 
			
		||||
	          		newn->facet_num = stl->neighbors_start[facet_num].neighbor[j];
 | 
			
		||||
	          		newn->next = head->next;
 | 
			
		||||
	          		head->next = newn;
 | 
			
		||||
| 
						 | 
				
			
			@ -189,7 +192,7 @@ void stl_fix_normal_directions(stl_file *stl)
 | 
			
		|||
      		}
 | 
			
		||||
      		stl_normal *temp = head->next;	// Delete this facet from the list.
 | 
			
		||||
      		head->next = head->next->next;
 | 
			
		||||
      		delete temp;
 | 
			
		||||
      		pool.destroy(temp);
 | 
			
		||||
    	} else { // If we ran out of facets to fix: All of the facets in this part have been fixed.
 | 
			
		||||
      		++ stl->stats.number_of_parts;
 | 
			
		||||
      		if (checked >= stl->stats.number_of_facets)
 | 
			
		||||
| 
						 | 
				
			
			@ -211,8 +214,8 @@ void stl_fix_normal_directions(stl_file *stl)
 | 
			
		|||
    	}
 | 
			
		||||
  	}
 | 
			
		||||
 | 
			
		||||
	delete head;
 | 
			
		||||
	delete tail;
 | 
			
		||||
	pool.destroy(head);
 | 
			
		||||
	pool.destroy(tail);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
void stl_fix_normal_values(stl_file *stl)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -25,7 +25,7 @@
 | 
			
		|||
 | 
			
		||||
#include <boost/log/trivial.hpp>
 | 
			
		||||
#include <boost/nowide/cstdio.hpp>
 | 
			
		||||
#include <boost/detail/endian.hpp>
 | 
			
		||||
#include <boost/predef/other/endian.h>
 | 
			
		||||
 | 
			
		||||
#include "stl.h"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -114,7 +114,7 @@ bool stl_print_neighbors(stl_file *stl, char *file)
 | 
			
		|||
  	return true;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifndef BOOST_LITTLE_ENDIAN
 | 
			
		||||
#if BOOST_ENDIAN_BIG_BYTE
 | 
			
		||||
// Swap a buffer of 32bit data from little endian to big endian and vice versa.
 | 
			
		||||
void stl_internal_reverse_quads(char *buf, size_t cnt)
 | 
			
		||||
{
 | 
			
		||||
| 
						 | 
				
			
			@ -141,11 +141,11 @@ bool stl_write_binary(stl_file *stl, const char *file, const char *label)
 | 
			
		|||
	#define SEEK_SET 0
 | 
			
		||||
#endif
 | 
			
		||||
	fseek(fp, LABEL_SIZE, SEEK_SET);
 | 
			
		||||
#ifdef BOOST_LITTLE_ENDIAN
 | 
			
		||||
#if BOOST_ENDIAN_LITTLE_BYTE
 | 
			
		||||
	fwrite(&stl->stats.number_of_facets, 4, 1, fp);
 | 
			
		||||
	for (const stl_facet &facet : stl->facet_start)
 | 
			
		||||
	  	fwrite(&facet, SIZEOF_STL_FACET, 1, fp);
 | 
			
		||||
#else /* BOOST_LITTLE_ENDIAN */
 | 
			
		||||
#else /* BOOST_ENDIAN_LITTLE_BYTE */
 | 
			
		||||
	char buffer[50];
 | 
			
		||||
	// Convert the number of facets to little endian.
 | 
			
		||||
	memcpy(buffer, &stl->stats.number_of_facets, 4);
 | 
			
		||||
| 
						 | 
				
			
			@ -157,7 +157,7 @@ bool stl_write_binary(stl_file *stl, const char *file, const char *label)
 | 
			
		|||
		stl_internal_reverse_quads(buffer, 48);
 | 
			
		||||
		fwrite(buffer, SIZEOF_STL_FACET, 1, fp);
 | 
			
		||||
	}
 | 
			
		||||
#endif /* BOOST_LITTLE_ENDIAN */
 | 
			
		||||
#endif /* BOOST_ENDIAN_LITTLE_BYTE */
 | 
			
		||||
	fclose(fp);
 | 
			
		||||
	return true;
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue