Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
Menu
Open sidebar
David Thompson
SMTK
Commits
12a2e2fc
Commit
12a2e2fc
authored
Jan 26, 2016
by
David Thompson
Browse files
Progress on face creation.
parent
b7cedaf2
Changes
2
Hide whitespace changes
Inline
Side-by-side
smtk/bridge/polygon/operators/CreateFaces.cxx
View file @
12a2e2fc
...
...
@@ -208,6 +208,7 @@ struct EdgeFragment
int
m_segment
;
// Offset into edge's point sequence defining the segment containing this fragment.
bool
m_sense
;
// True when fragment and model edge are codirectional; false when they are antidirectional.
RegionIdSet
::
value_type
m_regionId
[
2
];
// Union-Find region to each side of edge; 0: region CCW of edge, 1: region CW of edge.
FragmentId
m_next
[
2
];
// Next co-fragment in region; 0: opposite of fragment dir, 1: along fragment dir.
internal
::
Point
&
lo
()
{
return
this
->
m_lo
;
}
const
internal
::
Point
&
lo
()
const
{
return
this
->
m_lo
;
}
...
...
@@ -232,6 +233,23 @@ struct EdgeFragment
* upper (\a fromLowerEnd is false) endpoint of the fragment.
*/
RegionIdSet
::
value_type
&
cwRegion
(
bool
fromLowerEnd
)
{
return
this
->
m_regionId
[
fromLowerEnd
?
0
:
1
];
}
/**\brief Return the next fragment bounding the region to the left of the fragment.
*
*/
FragmentId
&
nextFragment
(
bool
forwardDir
)
{
return
this
->
m_next
[
forwardDir
?
1
:
0
];
}
/// Debug dump of fragment
void
dump
(
RegionIdSet
&
ufind
)
const
{
std
::
cout
<<
" "
<<
this
->
lo
().
x
()
/
1182720.0
<<
" "
<<
this
->
lo
().
y
()
/
1182720.0
<<
" -- "
<<
this
->
hi
().
x
()
/
1182720.0
<<
" "
<<
this
->
hi
().
y
()
/
1182720.0
<<
" "
<<
this
->
m_edge
.
name
()
<<
", seg "
<<
this
->
m_segment
<<
" regIds "
<<
ufind
.
find
(
this
->
m_regionId
[
0
])
<<
" "
<<
ufind
.
find
(
this
->
m_regionId
[
1
])
<<
" next "
<<
this
->
m_next
[
0
]
<<
" "
<<
this
->
m_next
[
1
]
<<
"
\n
"
;
}
};
typedef
std
::
vector
<
EdgeFragment
>
FragmentArray
;
// List of all output fragments forming loops.
...
...
@@ -404,8 +422,34 @@ typedef smtk::common::UnionFind<int> RegionIdSet;
/// A structure to hold chains of coedges bounding regions of space.
struct
Region
{
std
::
deque
<
std
::
pair
<
FragmentId
,
bool
>
>
m_boundary
;
// size_t = fragment id, bool = sense rel to fragment
FragmentId
m_seedFragment
;
bool
m_seedSense
;
//std::deque<std::pair<FragmentId,bool> > m_boundary; // size_t = fragment id, bool = sense rel to fragment
std
::
set
<
int
>
m_innerLoops
;
Region
()
:
m_seedFragment
(
-
1
),
m_seedSense
(
true
)
{
}
Region
(
FragmentId
seedFrag
,
bool
seedSense
)
:
m_seedFragment
(
seedFrag
),
m_seedSense
(
seedSense
)
{
}
void
merge
(
const
Region
*
other
)
{
if
(
!
other
)
{
return
;
}
if
(
this
->
m_seedFragment
==
-
1
)
{
this
->
m_seedFragment
=
other
->
m_seedFragment
;
this
->
m_seedSense
=
other
->
m_seedSense
;
for
(
std
::
set
<
int
>::
const_iterator
it
=
other
->
m_innerLoops
.
begin
();
it
!=
other
->
m_innerLoops
.
end
();
++
it
)
{
this
->
m_innerLoops
.
insert
(
*
it
);
}
}
}
};
/// A map to hold each region's definition indexed by its UF region ID.
...
...
@@ -450,15 +494,40 @@ struct Neighborhood
std
::
vector
<
FragmentId
>
m_fragmentsToQueue
;
std
::
list
<
FragmentId
>
m_ring
;
// offsets into m_fragments that order a neighborhood CCW
/**\brief Return the orientation of a fragment relative to the neighborhood.
*
* Returns true when the neighborhood is placed at the left/lower end of the fragment
* and true otherwise.
* This is used to obtain the proper region ID when winding around
* the edges incident to the neighborhood.
*/
bool
isFragmentOutgoing
(
const
EdgeFragment
&
frag
)
{
return
frag
.
lo
()
<=
this
->
m_point
->
position
();
}
/// The space between \a ringA and \a ringB is not interrupted; mark coedges of A/B as same region.
void
assignAndMergeRegions
(
const
std
::
list
<
FragmentId
>::
iterator
&
ringA
,
const
std
::
list
<
FragmentId
>::
iterator
&
ringB
)
{
std
::
cout
<<
" A-B: "
<<
*
ringA
<<
" "
<<
*
ringB
<<
"
\n
"
;
EdgeFragment
&
fragA
((
*
this
->
m_fragments
)[
*
ringA
]);
EdgeFragment
&
fragB
((
*
this
->
m_fragments
)[
*
ringB
]);
bool
orientA
=
this
->
fragmentOrientation
(
fragA
);
// true when m_point is coincident with fragA.lower
bool
orientB
=
this
->
fragmentOrientation
(
fragB
);
// Determine sense wrt neighborhood (isOutX == true => fragment's other vertex hasn't been processed yet).
bool
isOutA
=
this
->
isFragmentOutgoing
(
fragA
);
// true when m_point is coincident with fragA.lower
bool
isOutB
=
this
->
isFragmentOutgoing
(
fragB
);
// XXX FIXME URHERE TODO!!!
// Merging fragments should always be done according to the following logic:
// - all incomplete fragment chains point from low-to-high (x_min to x_max, then y_min to y_max)
// - completed fragment chains must be oriented to match the region (CCW for outer loops, CW for inner loops);
// that means: fragA is outgoing, fragB is incoming. In terms of vertices, the order must be B-x-A.
// - when linking chains ending at fragA and fragB:
// - if either fragment is starting (i.e., isOutA or isOutB), then that fragment must be the new chain
// end and the chain must go from low to high.
// - if !isOutA && !isOutB (both fragments ending), then the chain should be oriented from B to A.
// - the chain direction is independent of the region-merge winner?
// TODO. Fix so that no regionId is ever < 0.
// Then this code becomes moot and we just:
...
...
@@ -468,16 +537,27 @@ struct Neighborhood
// - pop loser (!= winner) from m_regions and hold onto it.
// - append/prepend m_regions[loser] to m_regions[winner] (append if winner = fragA, prepend if winner = fragB)
// - if m_regions[winner] is closed, output region and add it as an inner loop to the region containing the neighborhood (if any).
RegionIdSet
::
value_type
idA
=
this
->
m_regionIds
.
find
(
fragA
.
ccwRegion
(
orientA
));
RegionIdSet
::
value_type
idB
=
this
->
m_regionIds
.
find
(
fragB
.
cwRegion
(
orientB
));
RegionIdSet
::
value_type
idA
=
this
->
m_regionIds
.
find
(
fragA
.
ccwRegion
(
isOutA
));
RegionIdSet
::
value_type
idB
=
this
->
m_regionIds
.
find
(
fragB
.
cwRegion
(
isOutB
));
RegionIdSet
::
value_type
winner
;
if
(
idA
!=
idB
)
{
// Merge regions on inside of A--B. Add coedges (of exiting edges on inside of A--B) to region.
RegionIdSet
::
value_type
winner
=
this
->
m_regionIds
.
mergeSets
(
idA
,
idB
);
winner
=
this
->
m_regionIds
.
mergeSets
(
idA
,
idB
);
RegionIdSet
::
value_type
loser
=
(
winner
==
idA
?
idB
:
idA
);
// If this is a new region, create a record for it.
if
(
!
this
->
m_regions
[
winner
])
{
this
->
m_regions
[
winner
]
=
smtk
::
shared_ptr
<
Region
>
(
new
Region
(
*
ringB
,
!
isOutB
));
}
this
->
m_regions
[
winner
]
->
merge
(
this
->
m_regions
[
loser
].
get
());
}
else
{
// Add coedges (of exiting edges on inside of A--B) to region.
winner
=
idA
;
}
//xxx
// Link one coedge of B to A.
fragB
.
nextFragment
(
!
isOutB
)
=
*
ringA
;
/*
if (this->m_point.position() > fragA.lo())
{
this->m_regions[winner].insert(fragA.xxx)
...
...
@@ -486,6 +566,17 @@ struct Neighborhood
// to m_regions[whichever fragX.regionId[z] *is* returned by mergeSets] depending on
// whether survivor X == A (prepend m_regions[m_regionIds->find(B)]) or X == b (append ...find(A)).
}
*/
/*
if (!isOutA && !isOutB && edgeA.below(edgeB))
{
// Both edges are ending here... we should mark the A-B region
// as an inner loop contained by the edges immediately above
// and below neighborhood.
xxx
}
*/
// TODO. Could also check whether fragments are both segment-end events;
// if so, see whether chain is complete and output a "create face
...
...
@@ -570,7 +661,7 @@ struct Neighborhood
{
for
(
int
i
=
0
;
i
<
2
;
++
i
)
if
(
frag
.
m_regionId
[
i
]
<
0
)
frag
.
m_regionId
[
i
]
=
this
->
m_regionIds
.
create
Set
();
frag
.
m_regionId
[
i
]
=
this
->
m_regionIds
.
new
Set
();
if
(
this
->
m_ring
.
size
()
<
2
)
{
// No matter where we insert, the order will be CCW. So insert at beginning:
...
...
@@ -604,6 +695,7 @@ struct Neighborhood
void
processQueue
()
{
std
::
cout
<<
"Neighborhood::processQueue()
\n
"
;
// If we have any incident edges (and it is highly suspicious if we don't)
// then loop over adjacent pairs assigning/merging region IDs.
if
(
!
this
->
m_ring
.
empty
())
...
...
@@ -620,7 +712,6 @@ struct Neighborhood
this
->
assignAndMergeRegions
(
ringA
,
ringB
);
}
}
std
::
cout
<<
"Neighborhood::processQueue()
\n
"
;
std
::
list
<
FragmentId
>::
iterator
rit
;
for
(
rit
=
this
->
m_ring
.
begin
();
rit
!=
this
->
m_ring
.
end
();
++
rit
)
{
...
...
@@ -670,6 +761,33 @@ struct Neighborhood
this
->
m_point
->
advance
(
pt
);
}
}
void
dumpRegions
()
{
FragmentArray
::
const_iterator
fit
;
std
::
cout
<<
"
\n
Fragments
\n
"
;
std
::
size_t
i
=
0
;
for
(
fit
=
this
->
m_fragments
->
begin
();
fit
!=
this
->
m_fragments
->
end
();
++
fit
,
++
i
)
{
std
::
cout
<<
" "
<<
i
<<
" "
;
fit
->
dump
(
this
->
m_regionIds
);
}
std
::
cout
<<
"
\n
Regions
\n
"
;
std
::
set
<
RegionId
>
found
=
this
->
m_regionIds
.
roots
();
for
(
std
::
set
<
RegionId
>::
const_iterator
rit
=
found
.
begin
();
rit
!=
found
.
end
();
++
rit
)
{
std
::
cout
<<
" Region "
<<
*
rit
;
smtk
::
shared_ptr
<
Region
>
regRec
=
this
->
m_regions
[
*
rit
];
if
(
regRec
)
{
std
::
cout
<<
" seed frag "
<<
regRec
->
m_seedFragment
<<
" sense "
<<
regRec
->
m_seedSense
<<
" has "
<<
regRec
->
m_innerLoops
.
size
()
<<
" holes.
\n
"
;
}
else
{
std
::
cout
<<
" has no record!
\n
"
;
}
}
}
};
#if 0
...
...
@@ -924,6 +1042,9 @@ smtk::model::OperatorResult CreateFaces::operateInternal()
}
}
// Dump report of regions discovered and chains bounding regions.
neighborhood
.
dumpRegions
();
// Create vertex-use, chain, edge-use, loop, and face records
smtk
::
model
::
OperatorResult
result
;
if
(
ok
)
...
...
smtk/bridge/polygon/operators/CreateFaces.h
View file @
12a2e2fc
...
...
@@ -36,7 +36,7 @@ typedef std::set<FragmentId, EdgeFragmentComparator> ActiveSegmentTree;
typedef
std
::
vector
<
EdgeFragment
>
FragmentArray
;
typedef
int
RegionId
;
typedef
smtk
::
common
::
UnionFind
<
RegionId
>
RegionIdSet
;
typedef
std
::
map
<
RegionId
,
Region
>
RegionDefinitions
;
typedef
std
::
map
<
RegionId
,
smtk
::
shared_ptr
<
Region
>
>
RegionDefinitions
;
/**\brief Create a face given a set of point coordinates or edges (but not both).
*
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment